2017-09-22 16 views
4

VB6로 작성된 구성 요소를 VB.NET으로 작성된 새로운 구성 요소로 바꾸려고합니다. 새로운 구성 요소는 다른 VB6 응용 프로그램과도 교체해야만 작동합니다. 문자열 배열을 매개 변수로 사용하는 함수에 문제가 있습니다.COM을 통해 VB6에서 초기화되지 않은 배열을 .NET으로 전달하는 방법은 무엇입니까?

Public Function MyMethod(arr() As String, arr2() As String, Result$) As Integer  
    Result = Join(arr, ", ") 
    MyMethod = 0   
End Function 

내가 성공적으로 "안녕하세요, World"를 표시이 같은 테스트 프로그램 (VB6)에서 호출 할 수 있습니다

나는 문제를 복제하는 데이 기능을 포함하는 VB6 클래스를 사용하고 있습니다 :

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 응용 프로그램을 수정할 수 없습니다,하지만 난 .NET으로 작성된 클래스와 VB6 ActiveX 구성 요소를 교체합니다. 새로운 클래스는 다음과 같습니다

<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 클래스의 생성자에서 중단 점을 사용하여 실행 된 것을 확인했습니다.

테스트 응용 프로그램이 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 
); 
+1

는 https://stackoverflow.com/q/35190653/11683 및 https://stackoverflow.com/q/39351476/11683을 바탕으로, 나는'Array' 및 /로 선언하거나 마샬링 특성을 적용하려고 할 것입니다. – GSerg

+0

나는 이것과 비슷한 해결책을 찾고있다. 불행하게도 나는 그것을 작동시킬 수 없다. = VarEnum :'하는 ByRef arr2 Array'로와 나는 "잘못된 프로 시저 호출 또는 인수 (오류 5)"와' ByRef arr2 As Array'는 이전과 같은 예외를 발생시킵니다. 나는 마지막 사람이 일하기를 기대했다. ByRef 또는 ByVal도 아무런 차이가 없습니다. OleWoo의 결과물로 질문을 업데이트했습니다. – BenZinra

+0

솔루션을 찾고있는 동안 필요에 따라 redims 배열을받는 예상 서명으로 VB6에서 dll을 작성하고 .NET에서 실제 구현을 호출 할 수 있습니다. 그러나 마샬 러가 빈 배열을 마샬링 할 수 없다는 사실에 놀랐습니다. 최소한 Nothing으로 말입니다. – GSerg

답변

1

나는이 .NET Framework의 버그가 있다고 생각합니다.

VB6 응용 프로그램에 디버거를 연결했습니다. 기능 DispatchInfo::IsVariantByrefStaticArray입니다 Disassembled code showing a pointer being dereferenced at offset 2

: Stack trace with DispatchInfo::IsVariantByrefStaticArray at the top

이 그 위치에 디스 어셈블 된 코드는 다음과 같습니다이 충돌의 순간에 스택 추적입니다. NULL인지 확인하지 않고 (*V_ARRAYREF(pOle))의 결과를 역 참조합니다. 멤버 fFeatures은 오프셋 2에 있으며 주소 0x00000002에서 액세스 위반이 발생합니다.

나는 이것이 내가 우연히 만난 문제라고 생각한다. 나는 원래의 문제를 해결할 다른 방법을 찾아야 할 것이라고 생각한다.