Eccezioni (C++/CX)

La gestione degli errori in C++/CX si basa sulle eccezioni. Al livello più fondamentale, i componenti Windows Runtime segnalano errori come valori HRESULT. In C++/CX questi valori vengono convertiti in eccezioni fortemente tipite che contengono un valore HRESULT e una descrizione stringa a cui è possibile accedere a livello di codice. Le eccezioni vengono implementate come oggetto ref class che deriva da Platform::Exception. Lo spazio dei nomi Platform definisce le classi distinte di eccezioni per i valori HRESULT più comuni; tutti gli altri valori sono segnalati tramite la classe Platform::COMException . Tutte le classi di eccezioni presentano un campo Exception::HResult che puoi utilizzare per recuperare il valore HRESULT originale. È anche possibile esaminare le informazioni sullo stack di chiamate per il codice utente nel debugger che consente di individuare l'origine originale dell'eccezione, anche se ha avuto origine nel codice scritto in un linguaggio diverso da C++.

Eccezioni

Nel programma C++ puoi generare e intercettare un'eccezione proveniente da un'operazione di Windows Runtime, un'eccezione derivata da std::exceptiono da un tipo definito dall'utente. È necessario generare un'eccezione di Windows Runtime solo quando supera il limite dell'interfaccia binaria dell'applicazione ( ABI), ad esempio quando il codice che intercetta l'eccezione viene scritto in JavaScript. Quando un'eccezione C++ non Windows Runtime raggiunge il limite ABI, l'eccezione viene convertita in un'eccezione Platform::FailureException , che rappresenta un E_FAIL HRESULT. Per ulteriori informazioni su ABI, vedi Creating Windows Runtime Components in C++.

Puoi dichiarare un oggetto Platform::Exception usando uno dei due costruttori che accettano un parametro HRESULT o un parametro HRESULT e un parametro Platform::String^ che possono essere passati attraverso l'ABI a qualsiasi app di Windows Runtime che la gestisce. In alternativa, puoi dichiarare un'eccezione usando uno di due overload del metodo Exception::CreateException che accettano un parametro HRESULT o un parametro HRESULT e un parametro Platform::String^ .

Eccezioni standard

C++/CX supporta un set di eccezioni standard che rappresentano errori HRESULT tipici. Ogni eccezione standard deriva da Platform::COMException, che a sua volta deriva da Platform::Exception. Quando generi un'eccezione che supera il limite dell'ABI, l'eccezione deve essere di tipo standard.

Non puoi derivare un tipo di eccezione personale da Platform::Exception. Per generare un'eccezione personalizzata, utilizza un valore HRESULT definito dall'utente per creare un oggetto COMException .

Nella tabella seguente sono elencate le eccezioni standard.

Nome HRESULT sottostante Descrizione
COMException HRESULT definito dall'utente Generata quando viene restituito un HRESULT non riconosciuto da una chiamata a un metodo COM.
AccessDeniedException E_ACCESSDENIED Generata quando viene negato l'accesso a una risorsa o a una funzionalità.
ChangedStateException E_CHANGED_STATE Generata quando i metodi di un iteratore di raccolta o di una visualizzazione di raccolta vengono chiamati dopo che la raccolta padre è stata modificata, invalidando così i risultati del metodo.
ClassNotRegisteredException REGDB_E_CLASSNOTREG Generata quando una classe COM non è stata registrata.
DisconnectedException RPC_E_DISCONNECTED Generata quando un oggetto viene disconnesso dai relativi client.
FailureException E_FAIL Generata quando un'operazione non viene completata correttamente.
InvalidArgumentException E_INVALIDARG Generata quando uno degli argomenti forniti a un metodo non è valido.
InvalidCastException E_NOINTERFACE Generata quando non è possibile eseguire il cast di un tipo a un altro tipo.
NotImplementedException E_NOTIMPL Generata se un metodo di interfaccia non è stato implementato in una classe.
NullReferenceException E_POINTER Generata quando viene effettuato un tentativo di dereferenziare un riferimento di oggetto null.
ObjectDisposedException RO_E_CLOSED Generata quando viene eseguita un'operazione su un oggetto eliminato.
OperationCanceledException E_ABORT Generata quando un'operazione viene interrotta.
OutOfBoundsException E_BOUNDS Generata quando un'operazione tenta di accedere a dati memorizzati al di fuori dell'intervallo valido.
OutOfMemoryException E_OUTOFMEMORY Generata quando la memoria disponibile non è sufficiente per completare l'operazione.
WrongThreadException RPC_E_WRONG_THREAD Generata quando un thread esegue una chiamata tramite un puntatore a interfaccia che è per un oggetto proxy che non appartiene all'apartment del thread.

Proprietà Message e HResult

Tutte le eccezioni presentano una proprietà HResult e una proprietà Message . La proprietà Exception::HResult ottiene il valore HRESULT numerico sottostante dell'eccezione. La proprietà Exception::Message ottiene la stringa fornita dal sistema che descrive l'eccezione. In Windows 8 il messaggio è disponibile solo nel debugger ed è di sola lettura. Ciò significa che non puoi modificarlo quando generi di nuovo l'eccezione. In Windows 8.1 puoi accedere alla stringa di messaggio a livello di codice e fornire un nuovo messaggio se generi di nuovo l'eccezione. Migliori informazioni sullo stack di chiamate sono inoltre disponibili nel debugger, inclusi gli stack di chiamate per le chiamate asincrone.

Esempi

Questo esempio illustra come generare un'eccezione di Windows Runtime per le operazioni sincrone:

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

Nell'esempio riportato di seguito viene illustrato come intercettare l'eccezione.

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

Per intercettare le eccezioni generate durante un'operazione asincrona, usare la classe task e aggiungere una continuazione di gestione degli errori. La continuazione di gestione degli errori effettua il marshalling delle eccezioni generate in altri thread nel thread chiamante affinché tu possa gestire tutte le potenziali eccezioni da un unico punto nel codice. Per altre informazioni, vedere Programmazione asincrona in C++.

Evento UnhandledErrorDetected

In Windows 8.1 puoi sottoscrivere l'evento statico Windows::ApplicationModel::Core::CoreApplication::UnhandledErrorDetected , che fornisce l'accesso a errori non gestiti che stanno per arrestare il processo. Indipendentemente dall'origine, l'errore raggiunge il gestore come oggetto Windows::ApplicationModel::Core::UnhandledError passato con gli argomenti dell'evento. Quando chiami Propagate sull'oggetto, crea e genera un'eccezione Platform::*Exception del tipo corrispondente al codice di errore. Nei blocchi catch puoi salvare lo stato utente, se necessario, quindi consentire il termine del processo chiamando throwoppure ripristinare uno stato noto del programma. 'esempio seguente mostra il modello di base:

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

Osservazioni:

C++/CX non usa la finally clausola .

Vedi anche

Riferimenti al linguaggio C++/CX
Riferimenti a spazi dei nomi