作法:對應 HRESULT 和例外狀況

COM 方法是藉由傳回 HRESULT 來報告錯誤;.NET 方法則是藉由擲回例外狀況來報告錯誤。 執行階段則負責處理兩者之間的轉換。 .NET Framework 的每一個例外狀況類別都會對應到一個 HRESULT。

使用者定義的例外狀況類別可以指定任何適當的 HRESULT。 當藉由設定例外狀況物件上的 HResult 欄位而產生例外狀況時,這些例外狀況類別可以動態地變更要傳回的 HRESULT。 例外狀況的其他資訊會透過 IErrorInfo 介面提供給用戶端,該介面是在非受控處理序中的 .NET 物件上實作。

如果您建立了擴充 System.Exception 的類別,則必須在建構期間設定 HRESULT 欄位。 否則,基底類別會指派 HRESULT 值。 您可以在例外狀況的建構函式中提供值,將新的例外狀況類別對應到現有的 HRESULT。

請注意,執行階段有時候會忽略 HRESULT,以應付萬一執行緒上存在 IErrorInfo 的情況。 如果 HRESULTIErrorInfo 並不代表相同的錯誤,就可能會發生這種行為。

建立新的例外狀況類別並將其對應到 HRESULT

  1. 使用下列程式碼來建立稱為 NoAccessException 的新例外狀況類別,並將其對應到 HRESULT E_ACCESSDENIED

    Class NoAccessException : public ApplicationException
    {
        NoAccessException () {
        HResult = E_ACCESSDENIED;
    }
    }
    CMyClass::MethodThatThrows
    {
    throw new NoAccessException();
    }
    

您也許會遇到同時使用 Managed 和 Unmanaged 程式碼的程式 (以任何程式語言所撰寫)。 例如,下列程式碼範例中的自訂封送處理器是使用 Marshal.ThrowExceptionForHR(int HResult) 方法來擲回具有特定 HRESULT 值的例外狀況。 此方法會查詢 HRESULT 並產生適當的例外狀況,類型。 例如,下列程式碼片段中的 HRESULT 會產生 ArgumentException

CMyClass::MethodThatThrows
{
    Marshal.ThrowExceptionForHR(COR_E_ARGUMENT);
}

下表提供 HRESULT 與其在 .NET 中相當之例外狀況類別的常見對應。 沒有明確對應的 HRESULT 值會對應至 COMException。 您可以在 dotnet/runtime 存放庫中找到完整的最新對應。

HRESULT .NET 例外狀況
COR_E_APPLICATION ApplicationException
COR_E_ARGUMENTE_INVALIDARG ArgumentException
COR_E_ARGUMENTOUTOFRANGE ArgumentOutOfRangeException
COR_E_ARITHMETIC or ERROR_ARITHMETIC_OVERFLOW ArithmeticException
COR_E_ARRAYTYPEMISMATCH ArrayTypeMismatchException
COR_E_BADIMAGEFORMAT or ERROR_BAD_FORMAT BadImageFormatException
COR_E_DIRECTORYNOTFOUND or ERROR_PATH_NOT_FOUND DirectoryNotFoundException
COR_E_DIVIDEBYZERO DivideByZeroException
COR_E_DUPLICATEWAITOBJECT DuplicateWaitObjectException
COR_E_ENDOFSTREAM EndOfStreamException
COR_E_ENTRYPOINTNOTFOUND EntryPointNotFoundException
COR_E_EXCEPTION Exception
COR_E_EXECUTIONENGINE ExecutionEngineException
COR_E_FIELDACCESS FieldAccessException
COR_E_FILENOTFOUND or ERROR_FILE_NOT_FOUND FileNotFoundException
COR_E_FORMAT FormatException
COR_E_INDEXOUTOFRANGE IndexOutOfRangeException
COR_E_INVALIDCAST or E_NOINTERFACE InvalidCastException
COR_E_INVALIDFILTERCRITERIA InvalidFilterCriteriaException
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_NOTFINITENUMBER NotFiniteNumberException
E_NOTIMPL NotImplementedException
COR_E_NOTSUPPORTED NotSupportedException
COR_E_NULLREFERENCE orE_POINTER NullReferenceException
COR_E_OUTOFMEMORY or

E_OUTOFMEMORY
OutOfMemoryException
COR_E_OVERFLOW OverflowException
COR_E_PATHTOOLONG or ERROR_FILENAME_EXCED_RANGE PathTooLongException
COR_E_RANK RankException
COR_E_REFLECTIONTYPELOAD ReflectionTypeLoadException
COR_E_SECURITY SecurityException
COR_E_SERIALIZATION SerializationException
COR_E_STACKOVERFLOW orERROR_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_THREADINTERRUPTED ThreadInterruptedException
COR_E_THREADSTATE ThreadStateException
COR_E_TYPELOAD TypeLoadException
COR_E_TYPEINITIALIZATION TypeInitializationException
COR_E_VERIFICATION VerificationException

若要擷取擴充錯誤資訊,Managed 用戶端必須檢查所產生之例外狀況物件的欄位。 若要讓例外狀況物件提供有關錯誤的有用資訊,COM 物件必須實作 IErrorInfo 介面。 執行階段會使用 IErrorInfo 提供的資訊來初始化例外狀況物件。

如果 COM 物件不支援 IErrorInfo,執行階段會使用預設值來初始化例外狀況物件。 下表列出與例外狀況物件建立關聯的每一個欄位,並且指出當 COM 物件支援 IErrorInfo 時的預設資訊來源。

請注意,執行階段有時候會忽略 HRESULT,以應付萬一執行緒上存在 IErrorInfo 的情況。 如果 HRESULTIErrorInfo 並不代表相同的錯誤,就可能會發生這種行為。

例外狀況欄位 來自 COM 的資訊來源
ErrorCode 從呼叫傳回的 HRESULT。
HelpLink 如果 IErrorInfo->HelpContext 為非零,會透過串連 IErrorInfo->GetHelpFile、「#」和 IErrorInfo->GetHelpContext 來形成字串。 否則,會從 IErrorInfo->GetHelpFile 傳回字串。
InnerException 一律為 null 參考 (在 Visual Basic 中為 Nothing)。
Message IErrorInfo->GetDescription 傳回的字串。
Source IErrorInfo->GetSource 傳回的字串。
StackTrace 堆疊追蹤。
TargetSite 傳回失敗 HRESULT 之方法的名稱。

無法使用 StackOverflowException 的例外狀況欄位,例如 MessageSourceStackTrace

另請參閱