views:

1104

answers:

1

I have a COM component that I want to call using late-binding from VB.NET (using the painful Primary Interop Assembly - PIA method)

My IDL signature for the COM method looks like:

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

So 2 'ByRef' parameters in VB.NET lingo, and a return value.

I attempt to invoke this method like so:

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)

This fails spectactularly with an exception: {"Invalid callee. (Exception from HRESULT: 0x80020010 (DISP_E_BADCALLEE))"}

I assume this means I'm doing something wrong in my parameterMods array. Because if I comment out setting any value of the ParameterMods array to 'True' - it works. It of course doesnt update the parameters that are [out] parameters and so it's not working as intended.

Is there something else to consider since the method also has a return value? The MSDN example pretty much does exactly what I am doing, with the exception that example did not have a return value. Any help is appreciated.

A: 

One issue is that your argument and ParameterModifier arrays have different sizes. I believe they must match up such so that the CLR/BCL can match every argument with a ParameterModifier.

If the PIA was generated with the preserve signature attributes, the method actually has 4 arguments instead of 3. You'll need to extend the arrays to hold 4 members and the return value of pnCompletionCode will be in the last index of the argument array after the call completes.

Also I'm curious why you're using this method of invocation. Since you're using VB.Net why not disable Option Explicit and use the VB late binder. It's much easier than writing out the reflection code yourself (and will typically be a bit more correct because it will deal with weird marshalling rules).

Option Explicit Off
...
Dim obj As Object = DirectCast(MyObject,Object)
obj.Send("data", new Object(), new Object())
JaredPar
Didn't know VB.NET has a late binder, different language feature than C#. Thanks for that.I will give your suggestion about extending the parameter array length a try. Although I do get the correct value and type put into the objReturn return value.
Adam
Still getting the DISP_E_BADCALLEE HRESULT. Any special data marshalling rules for VARIANT out parameters?
Adam