How to use late binding method to call with ByRef parameters
I have a COM component that I want to call using late binding with VB.NET (using the torturous Primary Interop Assembly - PIA method)
My IDL signature for a COM method looks like this:
HRESULT Send([in]BSTR bstrRequestData,
[out]VARIANT *pvbstrResponseData,
[out]VARIANT *pvnExtCompCode,
[out,retval]int *pnCompletionCode);
So there are 2 'ByRef' parameters in VB.NET lingo and return value.
I am trying to call this method like this:
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 with exception: {"Invalid call" (Exception from HRESULT: 0x80020010 (DISP_E_BADCALLEE)) "}
I assume this means that I am doing something wrong in my parameterMods array. Because if I comment out setting any value of the ParameterMods array to "True" it works. It does not, of course, update parameters that are [out] parameters, and therefore it does not work 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, except the example has no return value. Any help is appreciated.
a source to share
One problem is that your arguments and ParameterModifier arrays are different sizes. I believe they should match so that the CLR / BCL can map each argument to a ParameterModifier.
If the PIA was generated with persistence attribute attributes, the method actually has 4 arguments instead of 3. You will need to expand the arrays to hold 4 members, and the pnCompletionCode return value will be at the last index of the argument array after the call completes.
Also I am wondering why you are using this calling method. Since you are using VB.Net why not disable Option Explicit and use the latest VB binder. This is much easier than writing out the reflection code yourself (and will generally be a little more correct because it will deal with strange sorting rules).
Option Explicit Off
...
Dim obj As Object = DirectCast(MyObject,Object)
obj.Send("data", new Object(), new Object())
a source to share