简体   繁体   中英

How do I use Marshal.QueryInterface?

I am trying to work with some embedded objects in Word documents. An earlier poster told me that this is not straight forward. Here is an excerpt of the linked answer:

"As I mentioned earlier, utilizing the embedded object's programming model to perform the save is something of a shortcut. There is a more involved solution that will work with any embedded object. In order for the object to be embedded in the first place, it must support one of the COM IPersist interfaces (ie IPersistStorage, IPersistStreamInit, IPersistFile, etc). Therefore, an embedded object can always be extracted by calling Marshal.QueryInterface on the OLEFormat.Object (to determine the appropriate persistance interface), casting accordingly and then calling the appropriate method. Depending on which persistence interface you use, you may need to call some additional methods to expose the appropriate storage over the top of a file. Also, depending on the type of embedded object, you may still need to activate the object prior to being able to successfully QueryInterface for the persistance interfaces."

So I am interested in exposing which interface the object is implementing. The closest I could find is here . The code so far is below and any help with the Marshal.QueryInterface is greatly appreciated.

// Opening the word document
object missing = Type.Missing;
this.document = wordApp.Documents.Open(
                ref fn, ref confirmConversions, ref readOnly, ref missing, ref missing, ref missing,
                ref missing, ref missing, ref missing, ref missing, ref missing,
                ref missing, ref missing, ref missing, ref missing, ref missing);

foreach (Microsoft.Office.Interop.Word.InlineShape inlineShape in this.document.InlineShapes)
            {
                if (inlineShape.OLEFormat.ProgID != null)
                {
                    switch (inlineShape.OLEFormat.ProgID)
                    {
                        // This is a pdf file
                        case "AcroExch.Document.7":
                            //Marshal.QueryInterface(IntPtr pUnk, ref Guid iid, out IntPtr ppv);
                            break;
                        default:
                            break;
                    }
                }
            }

Marshal.QueryInterface shouldn't be necessary - if you take a COM object and cast it to a COM interface type, .NET does the QueryInterface call for you. That is, you can write: IPersistStorage persist = (IPersistStorage) obj;

However it's not clear to me which object in the code implements IPersistStorage , IPersistStreamInit etc.

I am not sure what you intend to do but calling QueryInterface can be done. The only problem is that you have a ProgID here and you need to get the CLSID from it first. You can do by pInvoking the CLSIDFromProgId function.

[DllImport("ole32.dll")]
static extern int CLSIDFromProgID([MarshalAs(UnmanagedType.LPWStr)] string lpszProgID, out Guid pclsid);

And then, you can call this as follows:

Marshal.QueryInterface(IntPtr.Zero, CLSIDFromProgID(progID), out pInterface);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM