2008-09-30 18 views
0

J'ai un composant COM VB6 que j'ai besoin d'appeler avec ma méthode .Net. J'utilise la réflexion pour créer une instance de l'objet COM et l'activer de la manière suivante:Récupération du numéro d'erreur d'origine à partir d'une méthode COM appelée par réflexion

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

-je utiliser plutôt GetTypeFromProgID que d'utiliser tlbimp pour créer une bibliothèque contre la DLL COM comme ProgId du type I besoin d'instancier peut varier. J'utilise ensuite Type.InvokeMember pour appeler la méthode COM dans mon code comme:

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

J'attrape tout a soulevé TargetInvocationException pour l'exploitation forestière et peut obtenir la description détaillée des erreurs du champ TargetInvocationException.InnerException. Cependant, je sais que le composant COM utilise Error.Raise pour générer un numéro d'erreur et je dois en quelque sorte me procurer dans mon application .Net appelant.

Le problème semble provenir de l'TargetInvocationException ne contenant pas le numéro d'erreur que je pense si elle était une COMException normale si:

Comment puis-je obtenir le numéro d'erreur dans l'objet COM dans mon. Code net?

ou

Puis-je faire ce même appel d'une manière qui causerait un COMException (contenant le numéro d'erreur) plutôt que d'un TargetInvocationException lorsque le composant COM échoue?

S'il vous plaît noter également que la plate-forme cible est .Net 2.0 et j'ai accès au code source VB6 mais considérerait modifier le message d'erreur élevé de VB6 pour contenir le code d'erreur dans le cadre du texte à une un peu d'un hack.

Répondre

2

J'ai regardé votre code un peu plus près et avec réflexion vous gérez TargetInvocationException et travaillez avec l'exception interne qui est une exception COMException ...Exemple de code ci-dessous (j'ai couru et testé cela aussi):

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

Ce obtenu. A été lancé au début car l'InnerException ne revenait pas en tant que COMException, cependant l'enquête a montré que le composant COM soulevait l'erreur de manière incorrecte. Fixé cela et cela fonctionne un régal – Wolfwyrd

2

Vous allez gérer COMException et utiliser la propriété ErrorCode de cet objet d'exception. Normalement dans les DLL de base visuelles si vous lancez des erreurs personnalisées vous soulèveriez l'erreur avec: Err.Raise vbObjectError + 88, "Project1.Class1.Test3()", "Test d'erreur forcé"

Si c'est le cas vous devrez soustraire vbobjecterror (-2147221504) du ErrorCode d'exception pour obtenir le numéro d'erreur réel. Si ce n'est pas juste, utilisez la valeur ErrorCode.

Exemple VB code dll: (de Project1.Class1)

Public Sub Test3()

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

End Sub

Exemple C# code de manipulation de consommation:

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

Le ErrorCode dans ce test que je viens de terminer renvoie 88 comme prévu.

+0

Comme indiqué dans la question initiale, le code coutume jeter un COMException, il jette un TargetInvocationException qui ne marche pas avoir un numéro d'erreur – Wolfwyrd

2

veulent juste offrir une mise à jour du code de capture de @ sharvell. Sauf si vous êtes absolument certain que InnerException est une exception COMException, il est préférable de la tester en toute sécurité. Sinon, vous aurez une exception dans votre gestionnaire d'exceptions. Oups!

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 
}