How to get type of COM object

19,623

Solution 1

Add reference to Microsoft.VisualBasic.dll and then:

Microsoft.VisualBasic.Information.TypeName(someCOMObject)

MSDN reference here.

Solution 2

The accepted answer by Darin requires a dependency to Microsoft.VisualBasic.dll. If you don't want to have that you can use this simple helper class:

public static class TypeInformation
{
    public static string GetTypeName(object comObject)
    {
        var dispatch = comObject as IDispatch;

        if (dispatch == null)
        {
            return null;
        }

        var pTypeInfo = dispatch.GetTypeInfo(0, 1033);

        string pBstrName;
        string pBstrDocString;
        int pdwHelpContext;
        string pBstrHelpFile;
        pTypeInfo.GetDocumentation(
            -1, 
            out pBstrName, 
            out pBstrDocString, 
            out pdwHelpContext, 
            out pBstrHelpFile);

        string str = pBstrName;
        if (str[0] == 95)
        {
            // remove leading '_'
            str = str.Substring(1);
        }

        return str;
    }

    [ComImport]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [Guid("00020400-0000-0000-C000-000000000046")]
    private interface IDispatch
    {
        int GetTypeInfoCount();

        [return: MarshalAs(UnmanagedType.Interface)]
        ITypeInfo GetTypeInfo(
            [In, MarshalAs(UnmanagedType.U4)] int iTInfo,
            [In, MarshalAs(UnmanagedType.U4)] int lcid);

        void GetIDsOfNames(
            [In] ref Guid riid,
            [In, MarshalAs(UnmanagedType.LPArray)] string[] rgszNames,
            [In, MarshalAs(UnmanagedType.U4)] int cNames,
            [In, MarshalAs(UnmanagedType.U4)] int lcid,
            [Out, MarshalAs(UnmanagedType.LPArray)] int[] rgDispId);
    }
}

Solution 3

You've basically figured it out. GetType() on a COM object is going to give you System.__ComObject, and you have to try to cast it to something else to see what the object really is.

Share:
19,623
Admin
Author by

Admin

Updated on June 03, 2022

Comments

  • Admin
    Admin about 2 years

    I am referencing a COM library in Visual Studio, so it has automatically created the corresponding Interop assembly for me. I would like to do a GetType() on these com objects, but they always return System.__ComObject. Querying them for an interface works though:

    bool isOfType = someComeObject is ISomeComObject; //this works
    

    But what I really want is this to return the actual type of the com object:

    Type type = someComeObject.GetType(); //returns System.__ComObject :-(
    

    Does anyone know how to do what I want to do?

  • Admin
    Admin over 14 years
    Hm..is there really no other way? Because I can't test for every possible COM object in existing, I just want the type. The reason is that I am using the type of an object as a key in a dictionary...
  • Admin
    Admin over 14 years
    I just tried this and it works! It does not return the full name though, just the class name, but that's ok for my purposes. I looked at this method in reflector which internally calls 'LegacyTypeNameOfCOMObject' but I can't figure out what it actually does.
  • Admin
    Admin over 14 years
    I wish there was something that could give me the full name of that com object to avoid clashes.
  • AxA
    AxA over 14 years
    Thanks. Any idea if this is possible in C#?
  • Darin Dimitrov
    Darin Dimitrov over 14 years
    Microsoft.VisualBasic.dll is a .NET assembly which can be referenced and used in every application.
  • AxA
    AxA over 14 years
    Watch out if you have COM component written in C++/ATL. You might get a different result than you expect.
  • Żubrówka
    Żubrówka almost 12 years
    Exactly what I was looking for. Thanks!
  • catfood
    catfood almost 12 years
    Darin Dimitrov's solution is great.
  • nawfal
    nawfal over 10 years
    someCOMObject as type? Not sure if that would work.
  • Mike
    Mike over 9 years
  • Robert Synoradzki
    Robert Synoradzki over 7 years
    Because it doesn't.
  • ErrCode
    ErrCode over 6 years
    This seems to work too - just need to ensure there is a reference to System.Runtime.InteropServices.ComTypes for ITypeInfo (Visual Studio IDE auto-suggested Microsoft.VisualStudio.OLE.Interop.ITypeInfo, but this is not the one you want!)
  • pwhty
    pwhty about 6 years
    @nawfal: why not? It's trying to cast "someCOMObject" to the type "type". If it fails (and only then), the result is null. If it doesn't, then it found the correct type. (I know, it took me a few days to come up with that answer :-P)
  • nawfal
    nawfal about 6 years
    @pwhty type is not a type/class in your code, it is an instance of a type. as keyword works on a type
  • Zev Spitz
    Zev Spitz over 3 years
    Is there any way to use this to get the library of the COM object? I have an object from the Word object model for which TypeName returns Shape, but I cannot cast it to Word.Shape source in VBA.
  • brinkdinges
    brinkdinges over 2 years
    As @rpattabi mentions, this doesn't always work. In my case, it just returns "_ComObject".