0

.Net メソッドから呼び出す必要がある VB6 COM コンポーネントがあります。リフレクションを使用して COM オブジェクトのインスタンスを作成し、次の方法でアクティブにします。

f_oType = Type.GetTypeFromProgID(MyProgId);
f_oInstance = Activator.CreateInstance(f_oType);

インスタンス化する必要がある型の ProgId はさまざまであるため、tlbimp を使用して COM DLL に対してライブラリを作成するのではなく、GetTypeFromProgID を使用する必要があります。次に、Type.InvokeMember を使用して、次のようにコードで COM メソッドを呼び出します。

f_oType.InvokeMember("Process", BindingFlags.InvokeMethod, null, f_oInstance, new object[] { param1, param2, param3, param4 });

発生した TargetInvocationException をすべてキャッチしてログに記録し、TargetInvocationException.InnerException フィールドから詳細なエラーの説明を取得できます。ただし、COM コンポーネントが Error.Raise を使用してエラー番号を生成することはわかっており、呼び出し元の .Net アプリケーションで何らかの方法でこれを取得する必要があります。

この問題は、TargetInvocationException が通常の COMException である場合に予想されるエラー番号を含まないことに起因しているようです。

.Net コードの COM オブジェクトからエラー番号を取得するにはどうすればよいですか?

また

COM コンポーネントが失敗したときに、TargetInvocationException ではなく COMException (エラー番号を含む) を引き起こす方法で、これと同じ呼び出しを行うことはできますか?

また、ターゲット プラットフォームは .Net 2.0 であり、VB6 のソース コードにアクセスできますが、VB6 から発生したエラー メッセージを変更してテキストの一部としてエラー コードを含めることは、ちょっとしたハックだと考えています。

4

3 に答える 3

2

@sharvell の catch コードの更新を提供したいだけです。InnerException が COMException であることが確実でない限り、最初に安全にテストすることをお勧めします。そうしないと、例外ハンドラーに例外が発生します。おっと!

catch(TargetInvocationException ex)
{
    if( ex.InnerException != null && ex.InnerException is COMException )
    {
        COMException ce = (COMException)ex.InnerException;
        // do something with ce - e.g. logging the error
    }
    // else InnerException not set, or it's not a COMException
}
于 2008-09-30T23:50:52.987 に答える
2

COMException を処理し、その例外オブジェクトの ErrorCode プロパティを使用します。通常、Visual Basic DLL でカスタム エラーをスローすると、次のエラーが発生します: Err.Raise vbObjectError + 88, "Project1.Class1.Test3()", "Forced error test"

この場合、実際のエラー番号を取得するには、例外 ErrorCode から vbobjecterror (-2147221504) を減算する必要があります。そうでない場合は、ErrorCode 値を使用します。

VB dll コードの例: (Project1.Class1 から)

公開サブテスト3()

MsgBox "this is a test 3"
Err.Raise vbObjectError + 88, "Project1.Class1.Test3()", "Forced error test"

サブ終了

C# 消費処理コードの例:

    private void button1_Click(object sender, EventArgs e)
    {
        try
        {
            var p = new Class1();
            p.Test3();
        }
        catch (COMException ex)
        {
            int errorNumber = (ex.ErrorCode - (-2147221504));
            MessageBox.Show(errorNumber.ToString() + ": " + ex.Message);
        }
        catch(Exception ex)
        { MessageBox.Show(ex.Message); }
    }

先ほど完了したこのテストの ErrorCode は、予想どおり 88 を返します。

于 2008-09-30T23:06:54.107 に答える
2

私はあなたのコードをもう少し詳しく見て、リフレクションを使用して TargetInvocationException を処理し、COMException である内部例外を処理します... 以下のコード例 (これも実行してテストしました):

    private void button1_Click(object sender, EventArgs e)
    {
        try
        {
            var f_oType = Type.GetTypeFromProgID("Project1.Class1");
            var f_oInstance = Activator.CreateInstance(f_oType);
            f_oType.InvokeMember("Test3", BindingFlags.InvokeMethod, null, f_oInstance, new object[] {});
        }
        catch(TargetInvocationException ex)
        {
            //no need to subtract -2147221504 if non custom error etc
            int errorNumber = ((COMException)ex.InnerException).ErrorCode - (-2147221504);
            MessageBox.Show(errorNumber.ToString() + ": " + ex.InnerException.Message);
        }
        catch(Exception ex)
        { MessageBox.Show(ex.Message); }
    }
于 2008-09-30T23:35:52.803 に答える