Wyjątki (C++/CX)

Obsługa błędów w języku C++/CX jest oparta na wyjątkach. Na najbardziej podstawowym poziomie składniki środowisko wykonawcze systemu Windows zgłaszają błędy jako wartości HRESULT. W języku C++/CX te wartości są konwertowane na silnie typizowane wyjątki zawierające wartość HRESULT i opis ciągu, do którego można uzyskać dostęp programowo. Wyjątki są implementowane jako element ref class pochodzący z klasy Platform::Exception. Platform Przestrzeń nazw definiuje odrębne klasy wyjątków dla najbardziej typowych wartości HRESULT; wszystkie inne wartości są zgłaszane za pośrednictwem Platform::COMException klasy. Wszystkie klasy wyjątków mają pole Exception::HResult , którego można użyć do pobrania oryginalnego HRESULT. Możesz również sprawdzić informacje o stosie wywołań dla kodu użytkownika w debugerze, który może pomóc w określeniu oryginalnego źródła wyjątku, nawet jeśli pochodzi on z kodu napisanego w języku innym niż C++.

Wyjątki

W programie języka C++ można zgłosić i przechwycić wyjątek pochodzący z operacji środowisko wykonawcze systemu Windows, wyjątek pochodzący z std::exceptionklasy lub typu zdefiniowanego przez użytkownika. Należy zgłosić wyjątek środowisko wykonawcze systemu Windows tylko wtedy, gdy przekroczy granicę interfejsu binarnego aplikacji (ABI), na przykład gdy kod, który przechwytuje wyjątek, jest zapisywany w języku JavaScript. Gdy wyjątek inny niż środowisko wykonawcze systemu Windows C++ osiągnie granicę ABI, wyjątek jest tłumaczony na Platform::FailureException wyjątek, który reprezentuje E_FAIL HRESULT. Aby uzyskać więcej informacji na temat usługi ABI, zobacz Tworzenie składników środowisko wykonawcze systemu Windows w języku C++.

Można zadeklarować parametr Platform::Exception przy użyciu jednego z dwóch konstruktorów, które przyjmują parametr HRESULT lub HRESULT parametru i parametru Platform::String^, który można przekazać w usłudze ABI do dowolnej aplikacji środowisko wykonawcze systemu Windows, która go obsługuje. Możesz też zadeklarować wyjątek przy użyciu jednego z dwóch przeciążeń metody Exception::CreateException, które przyjmują parametr HRESULT lub parametr HRESULT i Platform::String^ parametr.

Wyjątki standardowe

Język C++/CX obsługuje zestaw standardowych wyjątków reprezentujących typowe błędy HRESULT. Każdy wyjątek standardowy pochodzi z klasy Platform::COMException, który z kolei pochodzi z klasy Platform::Exception. W przypadku zgłaszania wyjątku w granicach usługi ABI należy zgłosić jeden ze standardowych wyjątków.

Nie można utworzyć własnego typu wyjątku z klasy Platform::Exception. Aby zgłosić wyjątek niestandardowy, użyj zdefiniowanego przez użytkownika hrESULT do konstruowania COMException obiektu.

W poniższej tabeli wymieniono standardowe wyjątki.

Nazwisko Podstawowy hrESULT opis
Comexception hresult zdefiniowany przez użytkownika Zgłaszany, gdy nierozpoznany HRESULT jest zwracany z wywołania metody COM.
Accessdeniedexception E_ACCESSDENIED Zgłaszany, gdy odmowa dostępu do zasobu lub funkcji.
ChangedStateException E_CHANGED_STATE Zgłaszany, gdy metody iteratora kolekcji lub widoku kolekcji są wywoływane po zmianie kolekcji nadrzędnej, co spowoduje unieważnienie wyników metody.
ClassNotRegisteredException REGDB_E_CLASSNOTREG Zgłaszany, gdy klasa COM nie została zarejestrowana.
DisconnectedException RPC_E_DISCONNECTED Zgłaszany, gdy obiekt jest odłączony od swoich klientów.
BłądException E_FAIL Zgłaszany, gdy operacja kończy się niepowodzeniem.
Invalidargumentexception E_INVALIDARG Zgłaszany, gdy jeden z argumentów podanych w metodzie jest nieprawidłowy.
InvalidCastException E_NOINTERFACE Zgłaszany, gdy nie można rzutować typu na inny typ.
Notimplementedexception E_NOTIMPL Zgłaszany, jeśli metoda interfejsu nie została zaimplementowana w klasie.
Nullreferenceexception E_POINTER Zgłaszany podczas próby odwołania do odwołania do obiektu o wartości null.
Objectdisposedexception RO_E_CLOSED Zgłaszany, gdy operacja jest wykonywana na usuniętym obiekcie.
Operationcanceledexception E_ABORT Zgłaszany po przerwaniu operacji.
OutOfBoundsException E_BOUNDS Zgłaszany, gdy operacja próbuje uzyskać dostęp do danych poza prawidłowym zakresem.
Outofmemoryexception E_OUTOFMEMORY Zgłaszany, gdy nie ma wystarczającej ilości pamięci do ukończenia operacji.
WrongThreadException RPC_E_WRONG_THREAD Zgłaszany, gdy wątek wywołuje się za pośrednictwem wskaźnika interfejsu, który jest przeznaczony dla obiektu proxy, który nie należy do mieszkania wątku.

Właściwości HResult i Message

Wszystkie wyjątki mają właściwość HResult i właściwość Message . Właściwość Exception::HResult pobiera podstawową wartość HRESULT wyjątku. Właściwość Exception::Message pobiera ciąg dostarczony przez system, który opisuje wyjątek. W systemie Windows 8 komunikat jest dostępny tylko w debugerze i jest tylko do odczytu. Oznacza to, że nie można go zmienić podczas ponownego wywróć wyjątku. W systemie Windows 8.1 można uzyskać dostęp do ciągu komunikatu programowo i podać nowy komunikat, jeśli ponownie wrócą wyjątek. Lepsze informacje o stosie wywołań są również dostępne w debugerze, w tym stosy wywołań metody asynchronicznej.

Przykłady

W tym przykładzie pokazano, jak zgłosić wyjątek środowisko wykonawcze systemu Windows dla operacji synchronicznych:

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);
}

W następnym przykładzie pokazano, jak przechwycić wyjątek.

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());
    //...
}

Aby przechwycić wyjątki zgłaszane podczas operacji asynchronicznej, użyj klasy zadań i dodaj kontynuację obsługi błędów. Wyjątki kontynuacji obsługiwane przez obsługę błędów, które są zgłaszane w innych wątkach z powrotem do wątku wywołującego, dzięki czemu można obsłużyć wszystkie potencjalne wyjątki tylko w jednym punkcie kodu. Aby uzyskać więcej informacji, zobacz Asynchroniczne programowanie w języku C++.

Nieobsługiwane zdarzenieErrorDetected

W systemie Windows 8.1 można subskrybować zdarzenie statyczne Windows::ApplicationModel::Core::CoreApplication::UnhandledErrorDetected , które zapewnia dostęp do nieobsługiwane błędy, które mają spowodować wyłączenie procesu. Niezależnie od tego, skąd pochodzi błąd, program obsługi jest osiągany jako obiekt Windows::ApplicationModel::Core::UnhandledError przekazany za pomocą args zdarzenia. Wywołanie Propagate obiektu powoduje utworzenie obiektu i zgłoszenie Platform::*Exception typu odpowiadającego kodowi błędu. W blokach catch można zapisać stan użytkownika w razie potrzeby, a następnie zezwolić na zakończenie procesu przez wywołanie throwmetody lub zrobić coś, aby program wrócił do znanego stanu. W poniższym przykładzie przedstawiono podstawowy wzorzec:

W pliku app.xaml.h:

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

W pliku 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
    }
}

Uwagi

Język C++/CX nie używa klauzuli finally .

Zobacz też

Dokumentacja języka C++/CX
Dokumentacja przestrzeni nazw