Ausnahmen (C++/CX)

Die Fehlerbehandlung in C++/CX basiert auf Ausnahmen. Auf der grundlegendsten Ebene melden Windows-Runtime Komponenten Fehler als HRESULT-Werte. In C++/CX werden diese Werte in stark typierte Ausnahmen konvertiert, die einen HRESULT-Wert und eine Zeichenfolgenbeschreibung enthalten, auf die Sie programmgesteuert zugreifen können. Ausnahmen werden als ref class implementiert, die von Platform::Exceptionabgeleitet ist. Der Namespace Platform definiert verschiedene Ausnahmeklassen für die häufigsten HRESULT-Werte. Alle anderen Werte werden über die Klasse Platform::COMException gemeldet. Alle Ausnahmeklassen haben ein Feld Exception::HResult , das Sie verwenden können, um den ursprünglichen HRESULT-Wert abzurufen. Sie können auch Aufrufstapelinformationen für Benutzercode im Debugger untersuchen, mit der die ursprüngliche Quelle der Ausnahme angeheftet werden kann, auch wenn sie aus Code stammt, der in einer anderen Sprache als C++ geschrieben wurde.

Ausnahmen

In Ihrem C++-Programm können Sie eine Ausnahme auslösen und abfangen, die aus einem Windows-Runtime-Vorgang, einer Ausnahme stammt, die von std::exceptioneinem benutzerdefinierten Typ abgeleitet ist. Sie müssen eine Windows-Runtime Ausnahme nur auslösen, wenn sie die Grenze der Binären Schnittstelle (Application Binary Interface, ABI) überschreitet, z. B. wenn der Code, der Ihre Ausnahme abfangen, in JavaScript geschrieben wird. Wenn eine nicht Windows-Runtime C++-Ausnahme die ABI-Grenze erreicht, wird die Ausnahme in eine Platform::FailureException Ausnahme übersetzt, die ein E_FAIL HRESULT darstellt. Weitere Informationen zur ABI finden Sie unter Creating Windows Runtime Components in C++.

Sie können eine Platform::Exception deklarieren, indem Sie einen von zwei Konstruktoren verwenden, die entweder einen HRESULT-Parameter oder einen HRESULT-Parameter und einen Platform::String^-Parameter verwenden, der über die ABI an jede Windows-Runtime App übergeben werden kann, die sie behandelt. Alternativ dazu können Sie eine Ausnahme deklarieren, indem Sie eine von zwei Exception::CreateException -Methodenüberladungen verwenden, die entweder einen HRESULT-Parameter oder einen HRESULT-Parameter und einen Platform::String^ -Parameter akzeptieren.

Standardausnahmen

C++/CX unterstützt eine Reihe von Standard exceptions, die typische HRESULT-Fehler darstellen. Jede Standardausnahme wird von Platform::COMExceptionabgeleitet, die wiederum von Platform::Exceptionabgeleitet wird. Wenn Sie eine Ausnahme über die ABI-Grenze hinweg auslösen, müssen Sie eine der Standardausnahmen auslösen.

Sie können keinen eigenen Ausnahmetyp von Platform::Exceptionableiten. Verwenden Sie zum Auslösen einer benutzerdefinierten Ausnahme ein benutzerdefiniertes HRESULT, um ein COMException -Objekt zu erstellen.

In der folgenden Tabelle sind die Standardausnahmen aufgelistet.

Name Zugrunde liegendes HRESULT Beschreibung
COMException Benutzerdefiniertes HRESULT Wird ausgelöst, wenn ein COM-Methodenaufruf ein unbekanntes HRESULT zurückgibt.
AccessDeniedException E_ACCESSDENIED Wird ausgelöst, wenn der Zugriff auf eine Ressource oder eine Funktion verweigert wird.
ChangedStateException E_CHANGED_STATE Wird ausgelöst, wenn Methoden eines Auflistungsiterators oder einer Auflistungsansicht aufgerufen werden, nachdem die übergeordnete Auflistung geändert wurde, wodurch die Ergebnisse der Methode ungültig wurden.
ClassNotRegisteredException REGDB_E_CLASSNOTREG Wird ausgelöst, wenn eine COM-Klasse nicht registriert wurde.
DisconnectedException RPC_E_DISCONNECTED Wird ausgelöst, wenn ein Objekt von den Clients getrennt wurde.
FailureException E_FAIL Wird ausgelöst, wenn ein Vorgang fehlschlägt.
InvalidArgumentException E_INVALIDARG Wird ausgelöst, wenn eines der Argumente für eine Methode ungültig ist.
InvalidCastException E_NOINTERFACE Wird ausgelöst, wenn ein Typ nicht in einen anderen Typ umgewandelt werden kann.
NotImplementedException E_NOTIMPL Wird ausgelöst, wenn eine Schnittstellenmethode nicht bei der Klasse implementiert wurde.
NullReferenceException E_POINTER Wird ausgelöst, wenn der Versuch gemacht wird, einen Verweis auf ein NULL-Objekt zu dereferenzieren.
ObjectDisposedException RO_E_CLOSED Wird ausgelöst, wenn ein Vorgang für ein verworfenes Objekt ausgeführt wird.
OperationCanceledException E_ABORT Wird nach dem Abbrechen eines Vorgangs ausgelöst.
OutOfBoundsException E_BOUNDS Wird ausgelöst, wenn ein Vorgang versucht, auf Daten außerhalb des gültigen Bereichs zuzugreifen.
OutOfMemoryException E_OUTOFMEMORY Wird ausgelöst, wenn nicht genügend Arbeitsspeicher vorhanden ist, um den Vorgang abzuschließen.
WrongThreadException RPC_E_WRONG_THREAD Wird ausgelöst, wenn ein Thread über einen Schnittstellenzeiger aufruft, der für ein Proxyobjekt ist, das nicht zum Apartment des Threads gehört.

HResult- und Meldungseigenschaften

Alle Ausnahmen verfügen über eine -HResult -Eigenschaft und eine -Meldungseigenschaft . Die Exception::HResult -Eigenschaft ruft den der Ausnahme zugrunde liegenden numerischen HRESULT-Wert ab. Die Exception::Message -Eigenschaft ruft die vom System bereitgestellte Zeichenfolge ab, die die Ausnahme beschreibt. In Windows 8 ist die Nachricht nur im Debugger verfügbar und schreibgeschützt. Dies bedeutet, dass Sie sie nicht ändern können, wenn Sie die Ausnahme erneut auslösen. In Windows 8.1 können Sie auf die Meldungszeichenfolge programmgesteuert zugreifen und eine neue Nachricht bereitstellen, wenn Sie die Ausnahme erneut auslösen. Bessere Aufruflisteninformationen einschließlich Aufruflisten für asynchrone Methodenaufrufe sind auch im Debugger verfügbar.

Beispiele

In diesem Beispiel wird gezeigt, wie eine Windows-Runtime Ausnahme für synchrone Vorgänge ausgelöst wird:

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

Im nächsten Beispiel wird gezeigt, wie die Ausnahme abgefangen wird.

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

Um Ausnahmen abzufangen, die während eines asynchronen Vorgangs ausgelöst werden, verwenden Sie die Aufgabenklasse, und fügen Sie eine Fortsetzung der Fehlerbehandlung hinzu. Die Fehlerbehandlungsfortsetzung marshallt Ausnahmen, die für andere Threads ausgelöst und zurück an den aufrufenden Thread gegeben werden, damit Sie alle potenziellen Ausnahmen an nur einem Punkt im Code behandeln können. Weitere Informationen finden Sie unter Asynchrone Programmierung in C++.

UnhandledErrorDetected-Ereignis

In Windows 8.1 können Sie das statische Ereignis "Windows::ApplicationModel::Core::CoreApplication::UnhandledErrorDetected" abonnieren, das Zugriff auf unbehandelte Fehler ermöglicht, die den Prozess heruntersetzen. Unabhängig davon, wodurch der Fehler verursacht wurde, erreicht er diesen Handler als Windows::ApplicationModel::Core::UnhandledError -Objekt, das mit den Ereignisargumenten übergeben wird. Wenn Sie Propagate für das Objekt aufrufen, wird eine Platform::*Exception des Typs, der dem Fehlercode entspricht, erstellt und ausgelöst. In catch-Blöcken können Sie bei Bedarf den Benutzerzustand speichern und dann zulassen, dass der Prozess beendet wird, indem Sie throwaufrufen. Sie können auch etwas unternehmen, um das Programm in einen bekannten Zustand zurückzuführen. Das grundlegende Muster wird im folgenden Beispiel veranschaulicht:

In "app.xaml.h":

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

In "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
    }
}

Hinweise

C++/CX verwendet die finally Klausel nicht.

Siehe auch

C++-/CX-Programmiersprachenreferenz
Referenz zu Namespaces