Comment : mapper des HRESULT et des exceptions
Mise à jour : novembre 2007
Les méthodes COM signalent les erreurs en retournant des valeurs HRESULT ; les méthodes .NET les signalent en levant des exceptions. Le runtime gère la transition entre les deux. Chaque classe d'exception dans le .NET Framework est mappée à une valeur HRESULT.
Les classes d'exceptions définies par l'utilisateur peuvent spécifier la valeur HRESULT appropriée. Ces classes d'exceptions peuvent modifier dynamiquement la valeur HRESULT à retourner quand l'exception est générée par la définition du champ HResult sur l'objet exception. Des informations supplémentaires relatives à l'exception sont fournies par le biais de l'interface IErrorInfo, qui est implémentée sur l'objet .NET dans le processus non managé.
Si vous créez une classe qui étend System.Exception, vous devez définir le champ HRESULT pendant la construction. Sinon, la classe de base assigne la valeur HRESULT. Vous pouvez mapper de nouvelles classes d'exceptions à un HRESULT existant en fournissant la valeur dans le constructeur de l'exception.
Notez que l'exécution ignorera parfois un HRESULT si le thread comporte un IErrorInfo. Ce comportement peut se présenter si HRESULT et IErrorInfo ne représentent pas la même erreur.
Pour créer une classe d'exception et la mapper à un HRESULT
Utilisez le code suivant pour créer une classe d'exception appelée NoAccessException et la mapper à E_ACCESSDENIED du HRESULT.
Class NoAccessException : public ApplicationException { NoAccessException () { HResult = E_ACCESSDENIED; } } CMyClass::MethodThatThrows { throw new NoAccessException(); }
Vous pouvez rencontrer un programme (écrit dans n'importe quel langage de programmation) qui utilise à la fois un code managé et un code non managé en même temps. Par exemple, le marshaleur personnalisé dans l'exemple de code suivant utilise la méthode Marshal.ThrowExceptionForHR(int HResult) pour lever une exception avec une valeur HRESULT spécifique. La méthode consulte HRESULT et génère le type d'exception approprié. Par exemple, dans le fragment de code suivant, HRESULT génère ArgumentException.
CMyClass::MethodThatThrows
{
Marshal.ThrowExceptionForHR(COR_E_ARGUMENT);
}
Le tableau suivant fournit le mappage complet à partir de chaque HRESULT vers sa classe d'exception comparable dans le .NET Framework.
HRESULT |
Exception .NET |
---|---|
MSEE_E_APPDOMAINUNLOADED |
AppDomainUnloadedException |
COR_E_APPLICATION |
ApplicationException |
COR_E_ARGUMENT ou E_INVALIDARG |
ArgumentException |
COR_E_ARGUMENTOUTOFRANGE |
ArgumentOutOfRangeException |
COR_E_ARITHMETIC ou ERROR_ARITHMETIC_OVERFLOW |
ArithmeticException |
COR_E_ARRAYTYPEMISMATCH |
ArrayTypeMismatchException |
COR_E_BADIMAGEFORMAT ou ERROR_BAD_FORMAT |
BadImageFormatException |
COR_E_COMEMULATE_ERROR |
COMEmulateException |
COR_E_CONTEXTMARSHAL |
ContextMarshalException |
COR_E_CORE |
CoreException |
NTE_FAIL |
CryptographicException |
COR_E_DIRECTORYNOTFOUND ou ERROR_PATH_NOT_FOUND |
DirectoryNotFoundException |
COR_E_DIVIDEBYZERO |
DivideByZeroException |
COR_E_DUPLICATEWAITOBJECT |
DuplicateWaitObjectException |
COR_E_ENDOFSTREAM |
EndOfStreamException |
COR_E_TYPELOAD |
EntryPointNotFoundException |
COR_E_EXCEPTION |
Exception |
COR_E_EXECUTIONENGINE |
ExecutionEngineException |
COR_E_FIELDACCESS |
FieldAccessException |
COR_E_FILENOTFOUND ou ERROR_FILE_NOT_FOUND |
FileNotFoundException |
COR_E_FORMAT |
FormatException |
COR_E_INDEXOUTOFRANGE |
IndexOutOfRangeException |
COR_E_INVALIDCAST ou E_NOINTERFACE |
InvalidCastException |
COR_E_INVALIDCOMOBJECT |
InvalidComObjectException |
COR_E_INVALIDFILTERCRITERIA |
InvalidFilterCriteriaException |
COR_E_INVALIDOLEVARIANTTYPE |
InvalidOleVariantTypeException |
COR_E_INVALIDOPERATION |
InvalidOperationException |
COR_E_IO |
IOException |
COR_E_MEMBERACCESS |
AccessException |
COR_E_METHODACCESS |
MethodAccessException |
COR_E_MISSINGFIELD |
MissingFieldException |
COR_E_MISSINGMANIFESTRESOURCE |
MissingManifestResourceException |
COR_E_MISSINGMEMBER |
MissingMemberException |
COR_E_MISSINGMETHOD |
MissingMethodException |
COR_E_MULTICASTNOTSUPPORTED |
MulticastNotSupportedException |
COR_E_NOTFINITENUMBER |
NotFiniteNumberException |
E_NOTIMPL |
NotImplementedException |
COR_E_NOTSUPPORTED |
NotSupportedException |
COR_E_NULLREFERENCE ou E_POINTER |
NullReferenceException |
COR_E_OUTOFMEMORY ou E_OUTOFMEMORY |
OutOfMemoryException |
COR_E_OVERFLOW |
OverflowException |
COR_E_PATHTOOLONG ou ERROR_FILENAME_EXCED_RANGE |
PathTooLongException |
COR_E_RANK |
RankException |
COR_E_REFLECTIONTYPELOAD |
ReflectionTypeLoadException |
COR_E_REMOTING |
RemotingException |
COR_E_SAFEARRAYTYPEMISMATCH |
SafeArrayTypeMismatchException |
COR_E_SECURITY |
SecurityException |
COR_E_SERIALIZATION |
SerializationException |
COR_E_STACKOVERFLOW ou ERROR_STACK_OVERFLOW |
StackOverflowException |
COR_E_SYNCHRONIZATIONLOCK |
SynchronizationLockException |
COR_E_SYSTEM |
SystemException |
COR_E_TARGET |
TargetException |
COR_E_TARGETINVOCATION |
TargetInvocationException |
COR_E_TARGETPARAMCOUNT |
TargetParameterCountException |
COR_E_THREADABORTED |
ThreadAbortException |
COR_E_THREADINTERRUPTED |
ThreadInterruptedException |
COR_E_THREADSTATE |
ThreadStateException |
COR_E_THREADSTOP |
ThreadStopException |
COR_E_TYPELOAD |
TypeLoadException |
COR_E_TYPEINITIALIZATION |
TypeInitializationException |
COR_E_VERIFICATION |
VerificationException |
COR_E_WEAKREFERENCE |
WeakReferenceException |
COR_E_VTABLECALLSNOTSUPPORTED |
VTableCallsNotSupportedException |
Tous les autres HRESULT |
COMException |
Pour extraire des informations d'erreur étendues, le client managé doit examiner les champs de l'objet exception généré. Pour que l'objet exception fournisse des informations utiles sur une erreur, l'objet COM doit implémenter l'interface IErrorInfo. Le runtime utilise les informations fournies par IErrorInfo pour initialiser l'objet exception.
Si l'objet COM ne prend pas en charge IErrorInfo, le runtime initialise un objet exception avec les valeurs par défaut. Le tableau suivant répertorie chaque champ associé à un objet exception et identifie la source des informations par défaut lorsque l'objet COM prend en charge IErrorInfo.
Notez que l'exécution ignorera parfois un HRESULT si le thread comporte un IErrorInfo. Ce comportement peut se présenter si HRESULT et IErrorInfo ne représentent pas la même erreur.
Champ d'exception |
Source d'informations à partir de COM |
---|---|
ErrorCode |
HRESULT retourné à l'issue de l'appel. |
HelpLink |
Si IErrorInfo->HelpContext est différent de zéro, la chaîne est formée par la concaténation de IErrorInfo->GetHelpFile, « # » et IErrorInfo->GetHelpContext. Sinon, la chaîne est retournée à partir de IErrorInfo->GetHelpFile. |
InnerException |
Toujours une référence null (Nothing en Visual Basic). |
Message |
Chaîne retournée à partir de IErrorInfo->GetDescription. |
Source |
Chaîne retournée à partir de IErrorInfo->GetSource. |
StackTrace |
Trace de la pile. |
TargetSite |
Nom de la méthode ayant retourné le HRESULT qui a échoué. |
Les champs d'exception, tels que Message, Source et StackTrace ne sont pas disponibles pour StackOverflowException.