我有以下要从 C# 调用的旧版 VB6 函数。
Public Function CreateMiscRepayment(ByRef objMiscRepayment As MiscRepayment) As Variant
' Code that sets objMiscRepayment here
End Function
我在 C# 中使用以下代码,但出现异常:
dynamic vb6ComObject = Activator.CreateInstance(Type.GetTypeFromProgID(progId));
dynamic miscRepayment = null;
dynamic result = vb6ComObject.CreateMiscRepayment(ref miscRepayment);
例外是:
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()
我尝试更改ref
为out
但得到相同的错误。如果我省略ref
,该方法执行没有错误,但当然miscRepayment
仍然是 null 而不是包含应该传递出去的对象。
更新
我尝试了其他一些方法,包括使用 VB.NET(因为它一直比 C# 对 COM 更友好)。
使用以下 VB.NET 代码:
Dim vb6ComObject = Activator.CreateInstance(System.Type.GetTypeFromProgID(progId))
Dim miscRepayment = Nothing
Dim result = vb6ComObject.CreateMiscRepayment(miscRepayment)
它引发以下类似但不同的异常:
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()
有趣的是,如果我将 C# 或 VB.NET 示例代码中的调用更改为使用null
/Nothing
而不是,miscRepayment
则代码执行时不会引发异常。我什至在 VB6 COM 对象的代码中设置了一个断点,并且可以确认代码已在该端正确执行。显然,将miscRepayment
参数设置为null
/Nothing
后,.NET 就无法接收创建的对象。问题必须与参数的编组有关。
我也尝试过使用标记Type.InvokeMember
为参数的参数,但得到以下异常:ParameterModifier
miscRepayment
ref
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()
最后,我尝试了以下 VB.NET 代码:
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})
它抛出以下异常:
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()
对于所有引发异常的代码,VB6 COM 对象永远不会被调用。ref
尝试编组参数时,COM 互操作代码必须阻塞。
在我的 Google 搜索中,我遇到了一些使用的示例Type.InvokeMember
,但ref
参数始终用于简单类型,例如整数和字符串。