如何:映射 HRESULT 和异常
COM 方法通过返回 HRESULT 来报告错误;.NET 方法则通过引发异常来报告错误。 运行时将处理这两者之间的转换。 .NET Framework 中的每个异常类都会映射到一个 HRESULT。
用户定义的异常类可以指定任何适当的 HRESULT。 当通过设置异常对象的 HResult 字段来生成异常时,这些异常类可以动态地更改所返回的 HRESULT。 有关异常的其他信息通过 IErrorInfo 接口提供给客户端,该接口于非托管进程中在 .NET 对象上实现。
如果创建了扩展 System.Exception 的类,则必须在构造过程中设置 HRESULT 字段。 否则,基类将分配 HRESULT 值。 通过在异常的构造函数中提供 HRESULT 值,可以将新的异常类映射到现有的 HRESULT。
注意,当线程上存在 IErrorInfo 时,运行时有时会忽略 HRESULT。 该行为可能发生在 HRESULT 和 IErrorInfo 不表示相同错误的情况下。
新建异常类并将其映射到 HRESULT
使用以下代码新建一个名为 NoAccessException 的异常类并将它映射到 HRESULT E_ACCESSDENIED。
Class NoAccessException : public ApplicationException { NoAccessException () { HResult = E_ACCESSDENIED; } } CMyClass::MethodThatThrows { throw new NoAccessException(); }
您可能遇到过同时使用托管和非托管代码的程序(以任何编程语言编写)。 例如,下面的代码示例中的自定义封送拆收器使用 Marshal.ThrowExceptionForHR(int HResult) 方法来引发具有特定 HRESULT 值的异常。 该方法将查找此 HRESULT 并生成相应的异常类型。 例如,下面的代码片段中的 HRESULT 将生成 ArgumentException。
CMyClass::MethodThatThrows
{
Marshal.ThrowExceptionForHR(COR_E_ARGUMENT);
}
下表提供了从每个 HRESULT 到它在 .NET Framework 中的可比异常类的完整关系映射。
HRESULT |
.NET 异常 |
---|---|
MSEE_E_APPDOMAINUNLOADED |
AppDomainUnloadedException |
COR_E_APPLICATION |
ApplicationException |
COR_E_ARGUMENT 或 E_INVALIDARG |
ArgumentException |
COR_E_ARGUMENTOUTOFRANGE |
ArgumentOutOfRangeException |
COR_E_ARITHMETIC 或 ERROR_ARITHMETIC_OVERFLOW |
ArithmeticException |
COR_E_ARRAYTYPEMISMATCH |
ArrayTypeMismatchException |
COR_E_BADIMAGEFORMAT 或 ERROR_BAD_FORMAT |
BadImageFormatException |
COR_E_COMEMULATE_ERROR |
COMEmulateException |
COR_E_CONTEXTMARSHAL |
ContextMarshalException |
COR_E_CORE |
CoreException |
NTE_FAIL |
CryptographicException |
COR_E_DIRECTORYNOTFOUND 或 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 或 ERROR_FILE_NOT_FOUND |
FileNotFoundException |
COR_E_FORMAT |
FormatException |
COR_E_INDEXOUTOFRANGE |
IndexOutOfRangeException |
COR_E_INVALIDCAST 或 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 或 E_POINTER |
NullReferenceException |
COR_E_OUTOFMEMORY 或 E_OUTOFMEMORY |
OutOfMemoryException |
COR_E_OVERFLOW |
OverflowException |
COR_E_PATHTOOLONG 或 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 或 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 |
其他所有 HRESULT |
COMException |
要检索扩展的错误信息,托管客户端必须检查已生成的异常对象的字段。 要让异常对象提供有关错误的有用信息,COM 对象必须实现 IErrorInfo 接口。 运行时使用 IErrorInfo 所提供的信息来初始化异常对象。
如果 COM 对象不支持 IErrorInfo,运行时将用默认值初始化异常对象。 下表列出了与异常对象相关联的每个字段,并说明了当 COM 对象支持 IErrorInfo 时的默认信息源。
注意,当线程上存在 IErrorInfo 时,运行时有时会忽略 HRESULT。 该行为可能发生在 HRESULT 和 IErrorInfo 不表示相同错误的情况下。
异常字段 |
COM 信息源 |
---|---|
ErrorCode |
调用返回的 HRESULT。 |
HelpLink |
如果 IErrorInfo->HelpContext 不为零,字符串将通过串联 IErrorInfo->GetHelpFile 和“#”和 IErrorInfo->GetHelpContext 来形成。 否则,字符串将从 IErrorInfo->GetHelpFile 返回。 |
InnerException |
始终为 null 引用(在 Visual Basic 中为 Nothing)。 |
消息 |
IErrorInfo->GetDescription 返回的字符串。 |
源 |
IErrorInfo->GetSource 返回的字符串。 |
StackTrace |
堆栈跟踪。 |
TargetSite |
返回失败 HRESULT 的方法的名称。 |
Message、Source 和 StackTrace 等异常字段不可用于 StackOverflowException。