Как получить тип COM-объекта - PullRequest
25 голосов
/ 16 сентября 2009

Я ссылаюсь на библиотеку COM в Visual Studio, поэтому она автоматически создала для меня соответствующую сборку Interop. Я хотел бы сделать GetType() для этих com-объектов, но они всегда возвращают System.__ComObject. Запрос их для интерфейса работает, хотя:

bool isOfType = someComeObject is ISomeComObject; //this works

Но я действительно хочу, чтобы это возвращало фактический тип объекта com:

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

Кто-нибудь знает, как делать то, что я хочу делать?

Ответы [ 4 ]

50 голосов
/ 16 сентября 2009

Добавьте ссылку на Microsoft.VisualBasic.dll, а затем:

Microsoft.VisualBasic.Information.TypeName(someCOMObject)

MSDN, ссылка здесь .

8 голосов
/ 08 сентября 2017

Принятый ответ Дарина требует зависимости от Microsoft.VisualBasic.dll. Если вы не хотите иметь это, вы можете использовать этот простой вспомогательный класс:

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);
    }
}
2 голосов
/ 16 сентября 2009

Вы в основном поняли это. GetType () для COM-объекта даст вам System .__ ComObject, и вы должны попытаться привести его к чему-то другому, чтобы увидеть, что на самом деле представляет собой объект.

0 голосов
/ 28 сентября 2013

Я наткнулся на этот вопрос несколько дней назад, когда искал полное имя типа объекта System.__ComObject. В итоге я получил имя типа, используя решение Дарина, а затем перебрал все классы во всех сборках, чтобы проверить соответствие:

    typeName = Microsoft.VisualBasic.Information.TypeName(someCOMObject);
    foreach (System.Reflection.Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
    { 
        foreach (Type type in assembly.GetTypes())
        {
            if ((someCOMObject as type)!=null)
                fullTypeName = type.FullName;
        }
    }

Не самое быстрое и элегантное решение, но оно сработало.

...