У меня есть следующая устаревшая функция VB6, которую я хочу вызвать из C #.
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 (поскольку он всегда был более дружественным к COM, чем C #).
Со следующим кодом 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, чтобы использовать _10 _ / _ 11_ вместо miscRepayment
, тогда код выполняется без генерации исключения. Я даже установил точку останова в коде COM-объекта VB6 и могу подтвердить, что код на этом конце выполняется правильно. Очевидно, что при установке для параметра miscRepayment
значения _14 _ / _ 15_ в .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()
Со всем кодом, который вызывает исключение, COM-объект VB6 никогда не вызывается. Код взаимодействия COM должен подавляться при попытке маршалинга параметра ref
.
При поиске в Google я встречал несколько примеров с использованием Type.InvokeMember
, но параметры ref
всегда относятся к простым типам, таким как целые числа и строки.
dyanmic miscRepayment
наobject miscRepayment
? (И относитесь к нему как кdynamic
позже, если это сработает ... но я не используюdynamic
или C # 4. Кроме того, есть ли способ получить группу динамических методов? Например, принудительно отключить от нее действие / функцию / делегат?) - person   schedule 16.12.2011dynamic
наobject
, как вы предложили, но он по-прежнему вызывает то же исключение. Не уверен насчет твоего последнего бита. - person John Mills   schedule 16.12.2011((MyDelegate)it.method)(...);
, но это не так - по крайней мере, из-за того, что это выражение - похоже. Можете ли вы заставить его работать с помощью обычного отражения? Это, по крайней мере, означало бы, эй, это как-то работает! (или нет). - person   schedule 16.12.2011type.GetMethod("CreateMiscRepayment")
возвращает ноль.type.GetMethods()
возвращает 7 методов, но это общедоступные методы в MarshalByRefObject. - person John Mills   schedule 16.12.2011vb6ComObject
, позвонивActivator.CreateInstance(Type.GetTypeFromProgID(progId)
. Я не имею в виду сборку взаимодействия; надеялся, что динамика позволит мне обойтись без этого. - person John Mills   schedule 16.12.2011IDispatch
- это все, что у нас есть, поэтому будет работать только позднее связывание. Я также попробую запросить тип, возвращаемыйGetTypeFromProgID(progId)
, чтобы узнать, содержит ли он методы. - person John Mills   schedule 16.12.2011