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