1

我有一个 COM 组件,我想使用 VB.NET 的后期绑定来调用它(使用痛苦的 Primary Interop Assembly - PIA 方法)

我的 COM 方法的 IDL 签名如下所示:

HRESULT Send([in]BSTR bstrRequestData,
             [out]VARIANT *pvbstrResponseData,
             [out]VARIANT *pvnExtCompCode,
             [out,retval]int *pnCompletionCode);

所以 VB.NET 术语中的 2 个“ByRef”参数和一个返回值。

我尝试像这样调用这个方法:

Dim parameters(2) As Object
parameters(0) = "data"
parameters(1) = New Object()
parameters(2) = New Object()

Dim p As New ParameterModifier(3)
p(1) = True
p(2) = True
Dim parameterMods() As ParameterModifier = {p}

objReturn = MyObject.GetType().InvokeMember("Send", _
                                            BindingFlags.InvokeMethod, _
                                            Nothing, _
                                            MyObject, _
                                            parameters, _
                                            parameterMods, _
                                            Nothing, _
                                            Nothing)

这失败了一个异常:{“无效的被调用者。(来自HRESULT的异常:0x80020010(DISP_E_BADCALLEE))”}

我认为这意味着我在 parameterMods 数组中做错了。因为如果我注释掉将 ParameterMods 数组的任何值设置为“True” - 它会起作用。它当然不会更新 [out] 参数的参数,因此它没有按预期工作。

由于该方法也有返回值,还有其他需要考虑的吗?MSDN 示例几乎完全符合我的要求,只是该示例没有返回值。任何帮助表示赞赏。

4

1 回答 1

1

一个问题是您的参数和 ParameterModifier 数组具有不同的大小。我相信它们必须匹配,以便 CLR/BCL 可以将每个参数与 ParameterModifier 匹配。

如果 PIA 是使用保留签名属性生成的,则该方法实际上有 4 个参数而不是 3 个。您需要扩展数组以容纳 4 个成员,并且 pnCompletionCode 的返回值将在参数数组的最后一个索引中通话完成。

另外我很好奇你为什么使用这种调用方法。既然您使用的是 VB.Net,为什么不禁用 Option Explicit 并使用 VB 后期活页夹。这比自己编写反射代码要容易得多(并且通常会更正确,因为它会处理奇怪的编组规则)。

Option Explicit Off
...
Dim obj As Object = DirectCast(MyObject,Object)
obj.Send("data", new Object(), new Object())
于 2009-05-23T10:29:00.170 回答