I have the following VB6 function that I want to call from C #.
Public Function CreateMiscRepayment(ByRef objMiscRepayment As MiscRepayment) As Variant ' Code that sets objMiscRepayment here End Function
I use the following C # code, but get an exception:
dynamic vb6ComObject = Activator.CreateInstance(Type.GetTypeFromProgID(progId)); dynamic miscRepayment = null; dynamic result = vb6ComObject.CreateMiscRepayment(ref miscRepayment);
The exception is:
System.ArgumentException: Could not convert argument 0 for call to CreateMiscRepayment. at System.Dynamic.ComRuntimeHelpers.CheckThrowException(Int32 hresult, ExcepInfo& excepInfo, UInt32 argErr, String message) at CallSite.Target(Closure , CallSite , ComObject , Object& ) at CallSite.Target(Closure , CallSite , ComObject , Object& ) at CallSite.Target(Closure , CallSite , Object , Object& ) at CallSite.Target(Closure , CallSite , Object , Object& ) Application\ApplicationClasses.cs(65,0): at ApplicationClasses.CanInstantiateMiscRepayment()
I tried changing the ref to out , but getting the same error. If I omit ref , the method is executed without errors, but, of course, miscRepayment is still null and does not contain the object that should have been deleted.
Update
I tried other ways, including using VB.NET (since it was always more COM friendly than C #).
With the following VB.NET code:
Dim vb6ComObject = Activator.CreateInstance(System.Type.GetTypeFromProgID(progId)) Dim miscRepayment = Nothing Dim result = vb6ComObject.CreateMiscRepayment(miscRepayment)
It throws the following similar, but another exception:
System.Runtime.InteropServices.COMException: Type mismatch. (Exception from HRESULT: 0x80020005 (DISP_E_TYPEMISMATCH)) at Microsoft.VisualBasic.CompilerServices.LateBinding.LateGet(Object o, Type objType, String name, Object[] args, String[] paramnames, Boolean[] CopyBack) at Microsoft.VisualBasic.CompilerServices.NewLateBinding.LateGet(Object Instance, Type Type, String MemberName, Object[] Arguments, String[] ArgumentNames, Type[] TypeArguments, Boolean[] CopyBack) UnitTest1.vb(19,0): at TestProject1.UnitTest1.TestMethod1()
Interestingly, if I change the call in the C # or VB.NET code example to use null / Nothing instead of miscRepayment , then the code is executed without exception. I even set a breakpoint in the code of the VB6 COM object and I can confirm that the code was executed correctly for this purpose. Obviously, when you set the miscRepayment parameter to null / Nothing in .NET, there is no way to get the created object. The problem should be sorting the parameters.
I also tried using Type.InvokeMember with the ParameterModifier argument, which marks miscRepayment as the ref parameter, but gets the following exception:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Runtime.InteropServices.COMException: Type mismatch. (Exception from HRESULT: 0x80020005 (DISP_E_TYPEMISMATCH)) --- End of inner exception stack trace --- at System.RuntimeType.InvokeDispMethod(String name, BindingFlags invokeAttr, Object target, Object[] args, Boolean[] byrefModifiers, Int32 culture, String[] namedParameters) at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams) UnitTest1.vb(18,0): at TestProject1.UnitTest1.TestMethod1()
Finally, I tried the following VB.NET code:
Dim vb6ComObject = Activator.CreateInstance(System.Type.GetTypeFromProgID(progId)) Dim args(0) As Object Microsoft.VisualBasic.CompilerServices.LateBinding.LateCall(vb6ComObject, type, "CreateMiscRepayment", args, Nothing, New Boolean() {True})
It throws the following exception:
System.Runtime.InteropServices.COMException: Type mismatch. (Exception from HRESULT: 0x80020005 (DISP_E_TYPEMISMATCH)) at Microsoft.VisualBasic.CompilerServices.LateBinding.InternalLateCall(Object o, Type objType, String name, Object[] args, String[] paramnames, Boolean[] CopyBack, Boolean IgnoreReturn) at Microsoft.VisualBasic.CompilerServices.LateBinding.LateCall(Object o, Type objType, String name, Object[] args, String[] paramnames, Boolean[] CopyBack) UnitTest1.vb(17,0): at TestProject1.UnitTest1.TestMethod1()
With all the code that throws an exception, the VB6 COM object is never called. The COM interaction code should suffocate when trying to marshal the ref parameter.
On my Google search engines, I have come across several examples using Type.InvokeMember , but the ref parameters are always for simple types such as integers and strings.