2017-09-22 5 views
4

私はVB6で書かれたコンポーネントをVB.NETで書かれた新しいコンポーネントに置き換えたいと思っています。新しいコンポーネントは、これらが置き換えられるまで、他のVB6アプリケーションと連携する必要があります。文字列配列をパラメータとして受け取る関数に問題があります。COMを介してVB6から.NETに初期化されていない配列を渡す方法は?

私は、問題を再現するために、この機能が含まれているVB6のクラスを使用しています:

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

私は成功した「こんにちは、World」を表示する、次のようにテストプログラム(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アプリケーションを変更することはできませんが、VB6 ActiveXコンポーネントを.NETで記述されたクラスに置き換えます。新しいクラスは次のようになります。

<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が発生します。

エラーを第2パラメータ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

私はこれに似た解決策を望んでいます。残念ながら、私はそれを働かせることはできません。 'ByRef arr2 As Array'では、「無効なプロシージャコールまたは引数(エラー5)」および「 ByRef arr2 As Array'と同じ例外が発生します。私は最後のものが働くことを期待した。 ByRefやByValも違いはありません。私はOleWooからの出力で質問を更新しました。 – BenZinra

+0

解決策を探している間、必要に応じて配列を受け取る予想されるシグネチャでVB6でDLLを作成し、.NETで実際の実装を呼び出します。しかし、私は、マーシャルが空の配列をマーシャリングできないことに驚いています - 少なくとも「Nothing」。 – GSerg

答えて

1

私は、これは.NET Frameworkのバグであると信じています。

VB6アプリケーションにデバッガを添付しました。これは、クラッシュの時点のスタックトレースです: Stack trace with DispatchInfo::IsVariantByrefStaticArray at the top

これは、その位置で逆アセンブルコードです: Disassembled code showing a pointer being dereferenced at offset 2

機能DispatchInfo::IsVariantByrefStaticArrayです。 (*V_ARRAYREF(pOle))の結果を逆参照し、NULLかどうかをチェックしません。メンバfFeaturesがオフセット2にあるため、アドレス0x00000002のアクセス違反が発生します。

私はこれが私が遭遇した問題だと信じています。私は元の問題を解決する別の方法を見つけなければならないと思います。

関連する問題