有没有一种方法在C#中访问COM对象的虚拟方法表以获取函数的地址?
经过大量的搜索和拼凑不同的部分解决方案,我找到了如何做到这一点。
首先,您需要为您要访问的对象定义COM coclass:
[ComImport, Guid("..."), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface ISomeCOMInterface
{
// Define interface methods here, using PInvoke conversion between types
}
接下来,您需要实例化COM对象。有几种方法可以做到这一点。由于我对DirectSound感兴趣,所以我使用了:
[DllImport("dsound.dll", EntryPoint = "DirectSoundCreate", ...]
static extern void DirectSoundCreate(IntPtr GUID, [Out, MarshalAs(UnmanagedType.Interface)] out IDirectSound directSound, IntPtr pUnkOuter);
IDirectSound directSound;
DirectSoundCreate(IntPtr.Zero, out directSound, IntPtr.Zero);
现在我已经有了我的COM对象,我可以使用Hans的建议Marshal.GetComInterfaceForObject()
:
IntPtr comPtr = Marshal.GetComInterfaceForObject(directSound, typeof(IDirectSound));
IntPtr vTable = Marshal.ReadIntPtr(comPtr);
int start = Marshal.GetStartComSlot(typeof(IDirectSound));
int end = Marshal.GetEndComSlot(typeof(IDirectSound));
ComMemberType mType = 0;
for (int i = start; i <= end; i++)
{
System.Reflection.MemberInfo mi = Marshal.GetMethodInfoForComSlot(typeof(IDirectSound), i, ref mType);
Console.WriteLine("Method {0} at address 0x{1:X}", mi.Name, Marshal.ReadIntPtr(vTable, i * Marshal.SizeOf(typeof(IntPtr))).ToInt64());
}
额外阅读/参考资料:
我能想到的最接近的方法是Marshal.GetFunctionPointerForDelegate
,尽管这至少比非托管COM方法多了一层(因为COM调用将被包装在.NET委托中)。
您需要这些信息做什么?