如何通过 COM 将未初始化的数组从 VB6 传递到 .NET?
How to pass an uninitialized array from VB6 to .NET via COM?
我想用 VB.NET 编写的新组件替换 VB6 编写的组件。新组件必须与其他 VB6 应用程序一起工作,直到这些应用程序也被替换。我在使用将字符串数组作为参数的函数时遇到问题。
我正在使用包含此函数的 VB6 class 来重现问题:
Public Function MyMethod(arr() As String, arr2() As String, Result$) As Integer
Result = Join(arr, ", ")
MyMethod = 0
End Function
我可以从这样的测试程序 (VB6) 中成功调用它,它显示 "Hello, World":
Dim obj As Object
Dim arr() As String
Dim arr2() As String
Dim result As String
Set obj = CreateObject("MyHelloWorld.MyClass")
'Set obj = CreateObject("HelloWorldCOMNet.MyNetClass")
arr = Split("Hello World", " ")
'ReDim arr2(0)
result = ""
If Not obj.MyMethod(arr, arr2, result) Then
MsgBox result
End If
我无法修改实际的 VB6 应用程序,但我想将 VB6 ActiveX 组件替换为 class 用 .NET 编写的。新的 class 看起来像这样:
<ComClass("cd74ab4a-76ca-4c84-9f49-147e6f6ac01f", "b3314f71-cb8d-48ea-bfe6-9d1995aa4f58", "40c30052-0cc8-4ef6-b1e8-92e4ddbcb515")> _
Public Class MyNetClass
Public Sub New()
MyBase.New()
End Sub
Public Function MyMethod(ByRef arr() As String, ByRef arr2() As String, ByRef result As String) As Short
result = String.Join(", ", arr) + " from .NET"
Return 0
End Function
End Class
我通过在测试应用程序中用 Set obj = CreateObject("HelloWorldCOMNet.MyNetClass")
替换 Set obj = CreateObject("MyHelloWorld.MyClass")
来测试它。
我在 .NET 的构造函数中使用了一个断点 class 来验证它是否已被执行。
当测试应用程序调用 MyMethod
时,发生 FatalExecutionEngineException
。
我将错误缩小到第二个参数 arr2
。当我使用 ReDim arr2(0)
初始化变量时,.NET 代码有效。所以我的猜测是它与这个变量未初始化的事实有关。不幸的是我不能修改实际的 VB6 应用程序。
我使用 OleWoo 比较了方法签名,它们看起来是一样的(除了 id)。
如何修改 .NET 函数的签名以接受未初始化的字符串数组?
编辑:OleWoo 的输出:
[id(0x00000001)]
short MyMethod(
[in, out] SAFEARRAY(BSTR)* arr,
[in, out] SAFEARRAY(BSTR)* arr2,
[in, out] BSTR* result
);
我认为这是 .NET Framework 中的错误。
我将调试器附加到 VB6 应用程序。这是崩溃时的堆栈跟踪:
这是该位置的反汇编代码:
也就是函数DispatchInfo::IsVariantByrefStaticArray。它取消引用 (*V_ARRAYREF(pOle))
的结果而不检查它是否为 NULL。成员 fFeatures
位于偏移量 2,导致地址 0x00000002 发生访问冲突。
我相信这是我偶然发现的问题。我想我将不得不找到另一种方法来解决我原来的问题。
我想用 VB.NET 编写的新组件替换 VB6 编写的组件。新组件必须与其他 VB6 应用程序一起工作,直到这些应用程序也被替换。我在使用将字符串数组作为参数的函数时遇到问题。
我正在使用包含此函数的 VB6 class 来重现问题:
Public Function MyMethod(arr() As String, arr2() As String, Result$) As Integer
Result = Join(arr, ", ")
MyMethod = 0
End Function
我可以从这样的测试程序 (VB6) 中成功调用它,它显示 "Hello, World":
Dim obj As Object
Dim arr() As String
Dim arr2() As String
Dim result As String
Set obj = CreateObject("MyHelloWorld.MyClass")
'Set obj = CreateObject("HelloWorldCOMNet.MyNetClass")
arr = Split("Hello World", " ")
'ReDim arr2(0)
result = ""
If Not obj.MyMethod(arr, arr2, result) Then
MsgBox result
End If
我无法修改实际的 VB6 应用程序,但我想将 VB6 ActiveX 组件替换为 class 用 .NET 编写的。新的 class 看起来像这样:
<ComClass("cd74ab4a-76ca-4c84-9f49-147e6f6ac01f", "b3314f71-cb8d-48ea-bfe6-9d1995aa4f58", "40c30052-0cc8-4ef6-b1e8-92e4ddbcb515")> _
Public Class MyNetClass
Public Sub New()
MyBase.New()
End Sub
Public Function MyMethod(ByRef arr() As String, ByRef arr2() As String, ByRef result As String) As Short
result = String.Join(", ", arr) + " from .NET"
Return 0
End Function
End Class
我通过在测试应用程序中用 Set obj = CreateObject("HelloWorldCOMNet.MyNetClass")
替换 Set obj = CreateObject("MyHelloWorld.MyClass")
来测试它。
我在 .NET 的构造函数中使用了一个断点 class 来验证它是否已被执行。
当测试应用程序调用 MyMethod
时,发生 FatalExecutionEngineException
。
我将错误缩小到第二个参数 arr2
。当我使用 ReDim arr2(0)
初始化变量时,.NET 代码有效。所以我的猜测是它与这个变量未初始化的事实有关。不幸的是我不能修改实际的 VB6 应用程序。
我使用 OleWoo 比较了方法签名,它们看起来是一样的(除了 id)。
如何修改 .NET 函数的签名以接受未初始化的字符串数组?
编辑:OleWoo 的输出:
[id(0x00000001)]
short MyMethod(
[in, out] SAFEARRAY(BSTR)* arr,
[in, out] SAFEARRAY(BSTR)* arr2,
[in, out] BSTR* result
);
我认为这是 .NET Framework 中的错误。
我将调试器附加到 VB6 应用程序。这是崩溃时的堆栈跟踪:
这是该位置的反汇编代码:
也就是函数DispatchInfo::IsVariantByrefStaticArray。它取消引用 (*V_ARRAYREF(pOle))
的结果而不检查它是否为 NULL。成员 fFeatures
位于偏移量 2,导致地址 0x00000002 发生访问冲突。
我相信这是我偶然发现的问题。我想我将不得不找到另一种方法来解决我原来的问题。