Office タイプ ライブラリでアクセスしているオブジェクトの "オブジェクト ダンパー" を実装しようとしています (うまくいきません)。
おそらく、VS のデバッグ ウィンドウには System.__ComObject オブジェクトの「動的ビュー」があり、私が望むことを効果的に行うためです。
何か案は?
Office タイプ ライブラリでアクセスしているオブジェクトの "オブジェクト ダンパー" を実装しようとしています (うまくいきません)。
おそらく、VS のデバッグ ウィンドウには System.__ComObject オブジェクトの「動的ビュー」があり、私が望むことを効果的に行うためです。
何か案は?
また、オブジェクトへのアクセスに使用できるインターフェイスを取得するためのメソッドも作成しました。使用する:
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
コードにIDispatchインターフェイスが必要です。
[Guid("00020400-0000-0000-C000-000000000046"), ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IDispatch
{
[PreserveSig]
int GetTypeInfoCount(out int pctinfo);
[PreserveSig]
int GetTypeInfo(
[MarshalAs(UnmanagedType.U4)] int iTInfo,
[MarshalAs(UnmanagedType.U4)] int lcid,
out System.Runtime.InteropServices.ComTypes.ITypeInfo ppTInfo);
[PreserveSig]
int GetIDsOfNames(
ref Guid riid,
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)]
string[] rgszNames,
int cNames,
int lcid,
[MarshalAs(UnmanagedType.LPArray)] int[] rgDispId);
[PreserveSig]
int Invoke(
int dispIdMember,
ref Guid riid,
uint lcid,
ushort wFlags,
ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams,
out object pVarResult,
ref System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo,
IntPtr[] puArgErr);
}
私のメソッドはCOMオブジェクトをIDispatchにキャストし、アンマネージタイプ情報を取得し、非公開のMarshalメソッドGetTypeInfoGuidからオブジェクトタイプGUIDを取得して、現在のAppDomainのアセンブリで検索します。
internal static Func<ITypeInfo,Guid> GetTypeInfoGuid = (Func<ITypeInfo,Guid>)Delegate.CreateDelegate(typeof(Func<ITypeInfo,Guid>), typeof(Marshal).GetMethod("GetTypeInfoGuid", BindingFlags.NonPublic | BindingFlags.Static, null, new[]{typeof(ITypeInfo)}, null), true);
public static Type GetCOMObjectType(object comobject)
{
if(!Marshal.IsComObject(comobject))
{
throw new ArgumentException("This is not COM object.", "comobject");
}
IDispatch dispatch = (IDispatch)comobject;
ITypeInfo info;
dispatch.GetTypeInfo(0,0, out info);
Guid guid = GetTypeInfoGuid(info);
foreach(Assembly a in AppDomain.CurrentDomain.GetAssemblies())
{
foreach(Type t in a.GetTypes())
{
if(t.IsInterface && t.IsImport && t.GUID == guid)
{
return t;
}
}
}
return Type.GetTypeFromCLSID(guid);
}
適切なタイプが見つからない場合、メソッドはSystem.__ComObjectのタイプを返します。ただし、そこからGUIDプロパティ値を取得できるため、少なくともGUIDを取得できます。使用法:
object controls = axWindowsMediaPlayer1.cdromCollection;
Type t = GetCOMObjectType(controls);
Console.WriteLine(t);
Console.WriteLine(t.GUID);
/*Output:
WMPLib.IWMPCdromCollection
ee4c8fe2-34b2-11d3-a3bf-006097c9b344 */
お役に立てれば。幸運を。☺</p>
編集:より簡単だが遅い方法を見つけました:
object controls = axWindowsMediaPlayer1.cdromCollection;
IDispatch dispatch = (IDispatch)controls;
ITypeInfo info;
dispatch.GetTypeInfo(0,0, out info);
Type t = Marshal.GetTypeForITypeInfo(Marshal.GetIUnknownForObject(info));
Console.WriteLine(t);