2009-09-15 10 views
24

J'espère que quelqu'un peut m'aider. J'ai une exception spécifique de COM que j'ai besoin d'attraper et d'essayer de faire quelque chose d'autre, tous les autres devraient être ignorés. Mon message d'erreur à l'exception est:Attraper COMException spécifique Code d'erreur

System.Runtime.InteropServices.COMException (0x800A03EC): Microsoft Office Excel ne peut pas accéder au fichier 'C: \ test.xls'. Il y a plusieurs raisons possibles:

Ma première tentative a été

try 
{ 
// something 
} 
catch (COMException ce) 
{ 
    if (ce.ErrorCode == 0x800A03EC) 
    { 
     // try something else 
    } 
} 

Cependant je lu un avertissement du compilateur:

Avertissement 22 Comparaison intégrale constante est inutile; la constante est en dehors de la plage de type « int » ..... ExcelReader.cs 629 21

Maintenant, je sais que le 0x800A03EC est le HResult et je l'ai juste regardé sur MSDN et lire:

HRESULT est une valeur de 32 bits, divisé en trois domaines différents: un code de sévérité , un code d'établissement, et un code d'erreur . Le code de gravité indique si la valeur de retour représente une information, un avertissement ou une erreur . Le code d'installation identifie la zone du système responsable de l'erreur .

Donc, ma question ultime, est comment puis-je m'assurer que je piège cette exception spécifique? Ou comment puis-je obtenir le code d'erreur de HResult?

Merci d'avance.

+0

Juste pour ajouter une note. Il n'est pas très facile de reproduire cette exception car j'ai besoin d'une configuration très spécifique pour cela, mais je pensais que demander ici pourrait être plus rapide :) – Ian

Répondre

36

Le ErrorCode doit être un entier non signé; vous pouvez effectuer la comparaison comme suit:

try { 
    // something 
} catch (COMException ce) { 
    if ((uint)ce.ErrorCode == 0x800A03EC) { 
     // try something else 
    } 
} 
+0

donc, à partir du code C#, il n'y a pas moyen de faire quelque chose comme ' using WinErrorsOrWhatever' puis 'if ((uint) ce.ErrorCode == E_UNEXPECTED_OR_WHATEVER)'? – rturrado

+15

Ce qui précède fonctionne, mais seulement lorsqu'il est compilé dans un contexte 'non vérifié '. Sinon, le "ce.ErrorCode" négatif ne se convertira pas heureusement en un "uint" positif. C'est en fait plus agréable de convertir l'autre côté du symbole '==', et de dire 'if (ce.ErrorCode == non coché ((int) 0x800A03EC)) {...}'. Voir [un exemple sur MSDN] (http://msdn.microsoft.com/en-us/library/system.exception.hresult.aspx). –

+0

Est-ce un bug de framework alors? Est-ce que Exception.HResult doit être défini comme un uint? – Tristan

0

En fait, je réussi à le faire fonctionner sur le système que je avais besoin et trouvé le code d'erreur était -2146807284. En regardant cela, si je convertis le 0x800A03EC en binaire, alors le traiter comme complément de 2, alors vous pouvez calculer la valeur.

+3

Oui, l'alternative est de convertir le HRESULT en un entier signé, mais peut-être laisser le code hexadécimal le rend plus lisible (et plus facile à google). –

10

Une valeur HRESULT a 32 bits divisés en trois champs: un code de gravité, un code d'installation et un code d'erreur. Le code de gravité indique si la valeur de retour représente une information, un avertissement ou une erreur. Le code d'établissement identifie la zone du système responsable de l'erreur. Le code d'erreur est un nombre unique affecté à représenter l'exception. Chaque exception est mappée à un HRESULT distinct. Extrait de: http://en.wikipedia.org/wiki/HRESULT

D'après ce que je crois, la première moitié des bits HRESULT peut varier en fonction du système/processus qui fait l'exception. La seconde moitié contient le type d'erreur.

code

devrait ressembler à:

try { 
    // something 
} catch (COMException ce) { 
    if ((uint)ce.ErrorCode & 0x0000FFFF == 0x800A03EC) { 
     // try something else 
    } 
} 

REMARQUE: s'il vous plaît garder à l'esprit que je ne suis pas un gars .NET, donc lassons d'erreurs de syntaxe dans le code ci-dessus.

+1

+1: Merci pour la ventilation détaillée. C'est quelque chose d'il y a quelque temps, mais utile pour quelqu'un d'autre qui est intéressé. – Ian

+7

À quoi correspond le '& 0x0000FFFF'? Il va 'supprimer' (mettre à 0) la moitié gauche de l'uint, donc il ne peut jamais être '== 0x800A03EC', non? –