例外狀況 (C++/CX)

C++/CX 中的錯誤處理是以例外狀況為基礎。 在最基本的層級,Windows 執行階段元件會將錯誤報表為 HRESULT 值。 在 C++/CX 中,這些值會轉換成強型別例外狀況,其中包含 HRESULT 值,以及您可以以程式設計方式存取的字串描述。 例外狀況會實作為衍生自 ref classPlatform::ExceptionPlatform 命名空間會爲最常見的 HRESULT 值定義不同的例外狀況類別,其他所有的值則透過 Platform::COMException 類別來報告。 所有的例外狀況類別都會有可供您擷取原始 HRESULT 的 Exception::HResult 欄位。 您也可以檢查偵錯工具中使用者程式碼的呼叫堆疊資訊,以協助找出例外狀況的原始來源,即使它源自以 C++ 以外的語言撰寫的程式碼也一樣。

例外狀況

在您的 C++ 程式中,您可以擲回和攔截來自Windows 執行階段作業的例外狀況、衍生自 std::exception 的例外狀況或使用者定義型別。 只有當例外狀況跨越應用程式二進位介面 (ABI) 界限時,您才必須擲回Windows 執行階段例外狀況,例如,當攔截例外狀況的程式碼是以 JavaScript 撰寫時。 當非Windows 執行階段 C++ 例外狀況到達 ABI 界限時,例外狀況會轉譯為 Platform::FailureException 例外狀況,代表E_FAIL HRESULT。 如需 ABI 的詳細資訊,請參閱 Creating Windows Runtime Components in C++

您可以使用採用 HRESULT 參數或 HRESULT 參數和 Platform::String ^ 參數的兩個建構函式之一來宣告 Platform::Exception ,而這個建構函式可跨 ABI 傳遞至處理它的任何Windows 執行階段應用程式。 或者,您可以透過採用 HRESULT 參數或採用 HRESULT 參數和 參數的兩個 Exception::CreateException 方法 Platform::String^ 多載之一,來宣告例外狀況。

標準例外狀況

C++/CX 支援一組代表一般 HRESULT 錯誤的標準例外狀況。 每個標準例外狀況皆衍生自 Platform::COMException,而後者又衍生自 Platform::Exception。 當您擲回跨 ABI 界限的例外狀況時,您必須擲回其中一個標準例外狀況。

您無法從 Platform::Exception衍生您自己的例外狀況型別。 若要擲回自訂例外狀況,請透過使用者定義的 HRESULT 來建構 COMException 物件。

下表列出標準例外狀況。

名稱 基礎 HRESULT 描述
COMException 使用者定義的 HRESULT 在 COM 方法呼叫傳回無法辨認的 HRESULT 時擲回。
AccessDeniedException E_ACCESSDENIED 在存取資源或功能遭拒時擲回。
ChangedStateException E_CHANGED_STATE 在父集合變更後呼叫集合迭代器或集合檢視的方法時擲回,藉以讓該方法的結果失效。
ClassNotRegisteredException REGDB_E_CLASSNOTREG 在 COM 類別未登錄時擲回。
DisconnectedException RPC_E_DISCONNECTED 在物件與用戶端的連接中斷時擲回。
FailureException E_FAIL 在作業失敗時擲回。
InvalidArgumentException E_INVALIDARG 在其中一個提供給方法的引數無效時擲回。
InvalidCastException E_NOINTERFACE 在類型無法轉換成另一種類型時擲回。
NotImplementedException E_NOTIMPL 在介面方法未於類別上實作時擲回。
NullReferenceException E_POINTER 在嘗試解除 Null 物件的參考時擲回。
ObjectDisposedException RO_E_CLOSED 在已處置的物件上執行作業時擲回。
OperationCanceledException E_ABORT 在作業中止時擲回。
OutOfBoundsException E_BOUNDS 在作業嘗試存取有效範圍以外的資料時擲回。
OutOfMemoryException E_OUTOFMEMORY 在沒有足夠的記憶體可完成作業時擲回。
WrongThreadException RPC_E_WRONG_THREAD 在執行緒透過不屬於其 Apartment 之 Proxy 物件的介面指標進行呼叫時擲回。

HResult 屬性與 Message 屬性

所有例外狀況都有 HResult 屬性和 Message 屬性。 Exception::HResult 屬性會取得例外狀況的基礎數值 HRESULT 值。 Exception::Message 屬性會取得系統提供用以說明例外狀況的字串。 在 Windows 8 中,訊息只能在偵錯工具中使用,而且是唯讀的。 這表示當您重新擲回例外狀況時,無法加以變更。 在 Windows 8.1 中,如果重新擲回例外狀況,可以透過程式設計方式存取訊息字串並提供新的訊息。 偵錯工具中也提供更好的呼叫堆疊資訊,包括非同步方法呼叫的呼叫堆疊。

範例

此範例示範如何擲回同步作業的Windows 執行階段例外狀況:

String^ Class1::MyMethod(String^ argument)
{
    
    if (argument->Length() == 0) 
    { 
        auto e = ref new Exception(-1, "I'm Zork bringing you this message from across the ABI.");
        //throw ref new InvalidArgumentException();
        throw e;
    }
    
    return MyMethodInternal(argument);
}

下一個範例說明如何攔截例外狀況。

void Class2::ProcessString(String^ input)
{
    String^ result = nullptr;    
    auto obj = ref new Class1();

    try 
    {
        result = obj->MyMethod(input);
    }

    catch (/*InvalidArgument*/Exception^ e)
    {
        // Handle the exception in a way that's appropriate 
        // for your particular scenario. Assume
        // here that this string enables graceful
        // recover-and-continue. Why not?
        result = ref new String(L"forty two");
        
        // You can use Exception data for logging purposes.
        Windows::Globalization::Calendar calendar;
        LogMyErrors(calendar.GetDateTime(), e->HResult, e->Message);
    }

    // Execution continues here in both cases.
    //#include <string>
    std::wstring ws(result->Data());
    //...
}

若要攔截非同步作業期間擲回的例外狀況,請使用工作類別並新增錯誤處理接續。 錯誤處理接續工作會將其他執行緒上擲回的例外狀況封送回呼叫端執行緒,讓您在程式碼中的單一位置上即可處理所有可能的例外狀況。 如需詳細資訊,請參閱 使用 C++ 進行非同步程式設計

UnhandledErrorDetected 事件

在 Windows 8.1 中,您可以訂閱 Windows::ApplicationModel::Core::CoreApplication::UnhandledErrorDetected 靜態事件,以存取即將關閉進程的未處理錯誤。 不論錯誤源自何處,它都會以透過事件引數傳入的 Windows::ApplicationModel::Core::UnhandledError 物件形式,到達這個處理常式。 當您針對物件呼叫 Propagate 時,它會建立及擲回對應至錯誤代碼類型的 Platform::*Exception 。 在 Catch 區塊,您可以視需要儲存使用者狀態,然後透過呼叫 throw允許處理序結束,或是執行某個動作,讓程式回到已知狀態。 下列範例示範基本模式:

在 app.xaml.h 中:

void OnUnhandledException(Platform::Object^ sender, Windows::ApplicationModel::Core::UnhandledErrorDetectedEventArgs^ e);

在 app.xaml.cpp 中:

// Subscribe to the event, for example in the app class constructor:
Windows::ApplicationModel::Core::CoreApplication::UnhandledErrorDetected += ref new EventHandler<UnhandledErrorDetectedEventArgs^>(this, &App::OnUnhandledException);

// Event handler implementation:
void App::OnUnhandledException(Platform::Object^ sender, Windows::ApplicationModel::Core::UnhandledErrorDetectedEventArgs^ e)
{
    auto err = e->UnhandledError;

    if (!err->Handled) //Propagate has not been called on it yet.
{
    try
    {
        err->Propagate();
    }
    // Catch any specific exception types if you know how to handle them
    catch (AccessDeniedException^ ex)
    {
        // TODO: Log error and either take action to recover
        // or else re-throw exception to continue fail-fast
    }
}

備註

C++/CX 不使用 finally 子句。

另請參閱

C++/CX 語言參考
命名空間參考