Abrufen der ursprüngliche Fehlernummer von einer COM-Methode durch Reflexion genannt

StackOverflow https://stackoverflow.com/questions/153438

  •  03-07-2019
  •  | 
  •  

Frage

Ich habe eine VB6 COM-Komponente, die ich von meiner .NET-Methode aufrufen müssen. Ich Reflexion eine Instanz des COM-Objekts erstellen und aktivieren Sie es auf folgende Weise:

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

Ich brauche GetTypeFromProgID zu verwenden, anstatt mit tlbimp Bibliothek gegen den COM-DLL als ProgId des Typs variiert instanziiert kann ich brauche zu erstellen. Ich habe dann Type.InvokeMember verwenden, um die COM-Methode in meinem Code zu nennen wie:

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

Ich fange jede für die Protokollierung TargetInvocationException des angehoben und die detaillierte Fehlerbeschreibung aus dem TargetInvocationException.InnerException Feld bekommen. Ich weiß jedoch, dass die COM-Komponente verwendet Error.Raise eine Fehlernummer zu erzeugen, und ich muß irgendwie halten, dies in meiner Aufruf NetcAnwendung erhalten.

Das Problem scheint von den TargetInvocationException Einhalt zu gebieten nicht die Fehlernummer enthält, wie ich erwarten würde, wenn es eine normale COMException ist so:

Wie kann ich die Fehlernummer aus dem COM-Objekt in meinem .Net-Code?

oder

Kann ich den gleichen Anruf in einer Art und Weise zu machen, die eine COMException (mit der Fehlernummer) eher als ein TargetInvocationException verursachen würden, wenn die COM-Komponente ausfällt?

Bitte beachten Sie auch, dass die Zielplattform .Net 2.0 und ich habe zu tun Zugriff auf den Code VB6 Quelle, sondern betrachten würde die Fehlermeldung von VB6 angehoben Änderung des Fehlercode enthält als Teil des Textes ein bisschen eine zu sein hacken.

War es hilfreich?

Lösung

Ich schaute auf Ihren Code ein wenig näher und mit Reflexion behandeln Sie TargetInvocationException und mit der inneren Ausnahme arbeiten, die ein COMException ist ... Codebeispiel unten (Ich lief und getestet dies auch):

    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); }
    }

Andere Tipps

Sie werden COMException handhaben und die Error-Code Eigenschaft dieser Ausnahme-Objekt verwenden. Normalerweise in Visual Basic DLLs, wenn Sie benutzerdefinierte Fehler werfen würden Sie den Fehler aus mit: Err.Raise vbObjectError + 88 "Project1.Class1.Test3 ()", "Zwangsfehlertest"

Wenn dies der Fall ist, müssen Sie vbObjectError (-2147221504) subtrahieren von Ausnahmen die tatsächliche Fehlernummer erhalten Errorcode. Wenn nicht nur den Error-Code-Wert verwendet werden.

Beispiel VB DLL-Code: (von Project1.Class1)

Public Sub Test3 ()

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

End Sub

Beispiel C # Verbrauch Behandlungscode:

    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); }
    }

Der Error-Code in diesem Test, den ich 88 gerade abgeschlossen kehrt wie erwartet.

Ich will nur ein Update anbieten zu @ sharvell Fang-Code. Es sei denn, Sie absolut sicher sind, Innerexception ein COMException ist, ist es besser, es sicher zuerst zu testen. Andernfalls erhalten Sie eine Ausnahme in der Exception-Handler haben. Whoops!

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
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top