Exceptions (C++/CX)

La gestion des erreurs en C++/CX est basée sur des exceptions. Au niveau le plus fondamental, les composants Windows Runtime signalent des erreurs en tant que valeurs HRESULT. Dans C++/CX, ces valeurs sont converties en exceptions fortement typées qui contiennent une valeur HRESULT et une description de chaîne auxquelles vous pouvez accéder par programmation. Les exceptions sont implémentées sous forme de ref class qui dérive de Platform::Exception. L'espace de noms Platform définit des classes d'exception distinctes pour les valeurs HRESULT les plus courantes. Toutes les autres valeurs sont indiquées via la classe Platform::COMException . Toutes les classes d'exceptions ont un champ de Exception::HResult qui peut être utilisé pour récupérer le HRESULT d'origine. Vous pouvez également examiner les informations de pile des appels pour le code utilisateur dans le débogueur qui peut aider à identifier la source d’origine de l’exception, même si elle provient du code écrit dans une langue autre que C++.

Exceptions

Dans votre programme C++, vous pouvez lever et intercepter une exception provenant d’une opération Windows Runtime, d’une exception dérivée de std::exception, ou d’un type défini par l’utilisateur. Vous devez lever une exception Windows Runtime uniquement lorsqu’elle traversera la limite de l’interface binaire d’application (ABI), par exemple lorsque le code qui intercepte votre exception est écrit en JavaScript. Lorsqu’une exception C++ non-Windows Runtime atteint la limite ABI, l’exception est traduite en exception Platform::FailureException , qui représente une E_FAIL HRESULT. Pour plus d'informations sur l'ABI, consultez Creating Windows Runtime Components in C++.

Vous pouvez déclarer une plateforme ::Exception à l’aide de l’un des deux constructeurs qui prennent un paramètre HRESULT, ou un paramètre HRESULT et un paramètre Platform ::String^ qui peuvent être transmis dans l’ABI à n’importe quelle application Windows Runtime qui la gère. Vous pouvez aussi déclarer une exception à l'aide de l'une des deux surcharges de méthode Exception::CreateException qui acceptent un paramètre HRESULT ou un paramètre HRESULT et un paramètre Platform::String^ .

Exceptions standard

C++/CX prend en charge un ensemble d’exceptions standard qui représentent des erreurs HRESULT classiques. Chaque exception standard dérive de Platform::COMException, qui dérive à son tour de Platform::Exception. Lorsque vous levez une exception à travers la limite ABI, vous devez lever l'une des exceptions standard.

Vous ne pouvez pas dériver votre propre type d'exception de Platform::Exception. Pour lever une exception personnalisée, utilisez un HRESULT défini par l'utilisateur pour construire un objet COMException .

Le tableau ci-dessous répertorie les exceptions standard.

Nom HRESULT sous-jacent Description
COMException hresult défini par l’utilisateur Levée lorsqu'un HRESULT non reconnu est retourné d'un appel de méthode COM.
AccessDeniedException E_ACCESSDENIED Levée lorsque l'accès est refusé à une ressource ou à une fonctionnalité.
ChangedStateException E_CHANGED_STATE Levée lorsque les méthodes d'un itérateur de collection ou d'une vue de collection sont appelées après la modification d'une collection parente, invalidant ainsi les résultats de la méthode.
ClassNotRegisteredException REGDB_E_CLASSNOTREG Levée lorsqu'une classe COM n'a pas été inscrite.
DisconnectedException RPC_E_DISCONNECTED Levée lorsqu'un objet est déconnecté de ses clients.
FailureException E_FAIL Levée lorsqu'une opération échoue.
InvalidArgumentException E_INVALIDARG Levée lorsque l'un des arguments fournis à une méthode n'est pas valide.
InvalidCastException E_NOINTERFACE Levée lorsqu'un type ne peut pas être casté en un autre type.
NotImplementedException E_NOTIMPL Levée si une méthode d'interface n'a pas été implémentée pour une classe.
NullReferenceException E_POINTER Levée lors d'une tentative de suppression de la référence à une référence d'objet null.
ObjectDisposedException RO_E_CLOSED Levée lorsqu'une opération est exécutée sur un objet supprimé.
OperationCanceledException E_ABORT Levée lorsqu'une opération est abandonnée.
OutOfBoundsException E_BOUNDS Levée lorsqu'une opération tente d'accéder aux données en dehors de la plage valide.
OutOfMemoryException E_OUTOFMEMORY Levée en cas de mémoire insuffisante pour terminer l'opération.
WrongThreadException RPC_E_WRONG_THREAD Levée lorsqu'un thread effectue un appel via un pointeur d'interface qui concerne un objet proxy qui n'appartient pas à l'apartment du thread.

Propriétés HRESULT et Message

Toutes les exceptions ont une propriété HRESULT et une propriété Message . La propriété Exception::HResult obtient la valeur HRESULT numérique sous-jacente de l'exception. La propriété Exception::Message obtient la chaîne fournie par le système qui décrit l'exception. Dans Windows 8, le message est disponible uniquement dans le débogueur et est en lecture seule. Cela signifie que vous ne pouvez pas le modifier quand vous levez de nouveau l'exception. Dans Windows 8.1, vous pouvez accéder à la chaîne de message par programmation et fournir un nouveau message si vous levez de nouveau l'exception. Des informations plus riches relatives aux piles des appels sont également disponibles dans le débogueur, notamment les piles des appels correspondant aux appels de méthode asynchrones.

Exemples

Cet exemple montre comment lever une exception Windows Runtime pour les opérations synchrones :

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

L'exemple ci-dessous montre comment intercepter l'exception.

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

Pour intercepter les exceptions levées pendant une opération asynchrone, utilisez la classe de tâches et ajoutez une continuation de gestion des erreurs. La continuation de gestion des erreurs marshale les exceptions levées sur d'autres threads vers le thread appelant afin de gérer toutes les exceptions éventuelles en un seul point de votre code. Pour plus d’informations sur la programmation asynchrone, consultez Programmation asynchrone en C++.

Événement UnhandledErrorDetected

Dans Windows 8.1, vous pouvez vous abonner à l’événement statique Windows ::ApplicationModel ::CoreApplication ::UnhandledErrorDetected , qui permet d’accéder à des erreurs non gérées qui sont sur le point de supprimer le processus. Indépendamment de l’origine de l’erreur, il atteint ce gestionnaire en tant qu’objet Windows::ApplicationModel::Core::UnhandledError passé avec les arguments d’événement. Lorsque vous appelez Propagate sur l'objet, il crée et lève une exception Platform::*Exception dont le type correspond au code d'erreur. Dans les blocs catch, vous pouvez enregistrer l'état utilisateur, le cas échéant. Vous pouvez ensuite permettre au processus de se terminer en appelant throw, ou vous pouvez faire en sorte de restaurer le programme à un état connu. L'exemple suivant illustre le modèle de base :

Dans app.xaml.h :

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

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

Notes

C++/CX n’utilise pas la finally clause.

Voir aussi

Informations de référence sur le langage C++/CX
Référence aux espaces de noms