2022-08-03 (水)
[C#] COM Object から TypeInfoName を取得する
System.__ComObject
のインスタンスから COM インターフェイスの型名を取得する方法です。
環境
- .NET 6.0.302
- C# 10.0
- Visual Studio 2022 Version 17.2.6
- Windows 10 Pro 64bit 21H1 19043.1826
使用例
var type = Type.GetTypeFromProgID("Shell.Application");
var comObject = Activator.CreateInstance(type);
var name = MarshalUtil.GetTypeInfoName(comObject);
Console.WriteLine(name); // IShellDispatch6
実装方法
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
public static class MarshalUtil
{
public static string? GetTypeInfoName(object comObject)
{
if (comObject is not IDispatch dispatch)
return null;
var typeInfo = dispatch.GetTypeInfo(0, 0);
return Marshal.GetTypeInfoName(typeInfo);
}
[ComImport]
[Guid("00020400-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IDispatch
{
int GetTypeInfoCount();
ITypeInfo GetTypeInfo(int iTInfo, int lcid);
}
}
以下のように ITypeInfo.GetDocumentation() を使用すると、名前以外も取得できます。
Marshal.GetTypeInfoName() でも同じく ITypeInfo.GetDocumentation()
を実行しています(ソース)。
var typeInfo = dispatch.GetTypeInfo(0, 0);
typeInfo.GetDocumentation(-1, out var name, out var doc, out var helpContext, out var helpFile);
Console.WriteLine(name); // IShellDispatch6
Console.WriteLine(doc); // Updated IShellDispatch
Console.WriteLine(helpContext); // 0
Console.WriteLine(helpFile); // null
その他の方法
1. Microsoft.VisualBasic.Information.TypeName()
Information.TypeName(Object) メソッド (Microsoft.VisualBasic) | Microsoft Docs
var name = Microsoft.VisualBasic.Information.TypeName(comObject);
ソースとしては以下の順に実行されるようです。同じく ITypeInfo.GetDocumentation()
が実行されます。
- Microsoft.VisualBasic.Information.TypeName()
- Microsoft.VisualBasic.Information.LegacyTypeNameOfCOMObject()
2. IDispatch を定義せずに Marshal で頑張って取得する (.NET Framework 限定)
IntPtr
を使用すれば、IDispatch
の定義なしで取得できるようです。
ただし、 Marshal.GetITypeInfoForType()
が .NET Core で使用できません。
Marshal.GetITypeInfoForType(Type) メソッド (System.Runtime.InteropServices) | Microsoft Docs
var dispatchPtr = Marshal.GetIDispatchForObject(comObject);
var typeInfoPtr = Marshal.GetITypeInfoForType(dispatchPtr.GetType());
var typeInfo = (ITypeInfo)Marshal.GetTypedObjectForIUnknown(typeInfoPtr, typeof(ITypeInfo));
var name = Marshal.GetTypeInfoName(typeInfo);
感謝
Microsoft.VisualBasic.Information.TypeName()
,ITypeInfo.GetDocumentation()
のヒントMarshal.GetTypeInfoName()
のヒント- COM オブジェクトの詳細表示
- IDispatch 定義
2022-08-03 (水)
関連記事
新着記事