对未实现 IDispatch 的 COM 对象的 C# 后期绑定方法调用

C# late bound method invocation on COM object that does not implement IDispatch

提问人:Feem 提问时间:11/5/2023 更新时间:11/5/2023 访问量:22

问:

我需要对实现 IDispatch 的对象执行后期绑定 COM 调用。当我运行这段代码时,我得到一个告诉我这一点。TargetInvocationException

var iid_itaskbarlist = "{C43DC798-95D1-4BEA-9030-BB99E2983A1A}";
var clsid_taskbarlist = "{56FDF344-FD6D-11d0-958A-006097C9A090}";
CLSIDFromString(clsid_taskbarlist, out var clsId);
CLSIDFromString(iid_itaskbarlist, out var iid);
CoCreateInstance(ref clsId, null, CLSCTX_SERVER, ref iid, out var inst);
var t = inst.GetType();
//This next line throws the exception.
t.InvokeMember("HrInit",
     BindingFlags.Public | BindingFlags.NonPublic |
     BindingFlags.Instance | BindingFlags.Static | BindingFlags.InvokeMethod,
     null,
     inst,
     null);

//Boilerplate interop declarations below this line.
[DllImport("ole32.dll", CharSet = CharSet.Unicode)]
static extern int CLSIDFromString(string lpsz, out Guid guid);

[DllImport("ole32.dll")]
static extern int CoCreateInstance(ref Guid clsid,
        [MarshalAs(UnmanagedType.IUnknown)] object inner,
        uint context,
        ref Guid uuid,
        [MarshalAs(UnmanagedType.IUnknown)] out object rReturnedComObject);

static Guid IID_IDispatch = new Guid(0x00020400, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);

const int CLSCTX_INPROC_SERVER = 0x1;
const int CLSCTX_LOCAL_SERVER = 0x4;
const int CLSCTX_REMOTE_SERVER = 0x10;
const int CLSCTX_SERVER = CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER;

我需要知道如何使用后期绑定来做到这一点。我无法在代码中将接口声明为要实例化的 COM 类型,并且在编译时调用它的方法将是未知的。

几点说明:

  1. 这个简单示例正在尝试调用 ITaskBarList4 上的方法。HrInit()
  2. 这是由 Microsoft 提供的,但奇怪的是没有实现 IDispatch。看这里: https://pinvoke.net/default.aspx/shell32/ITaskbarList.html
  3. 为什么 Microsoft 会发布一个没有实现 IDispatch 的官方 COM 接口?
  4. 如果这样做不到,有没有其他方法可以做到?
  5. 我正在 .NET 4.8 和 .NET 7 上对此进行测试。
C# .NET COM

评论

0赞 Simon Mourier 11/5/2023
不可能在非 IDispatch 接口上使用所谓的“后期绑定”,因为名称对于此类接口没有任何意义。它们只是二元合约,其中只有订单或方法以及每个方法的签名代表它。但是,您可以完美地将它们与 C# 一起使用,您“只需”在 C# 中声明该方法。这里有一个 ITaskbarList(3) 的例子 stackoverflow.com/questions/55193899/...
0赞 Simon Mourier 11/5/2023
PS:您不需要CLSIDFromString,CoCreateInstance,所有这些都可以在C#中使用Type.GetTypeFromProgID,Type.GetTypeFromCLSID,ActivatorCreateInstance等完成。
0赞 Feem 11/6/2023
谢谢,这正是我所担心的,这是不可能的。

答: 暂无答案