Excepciones (C++/CX)
El control de errores de (C++/CX) se basa en excepciones. En el nivel más fundamental, los componentes de Windows Runtime informan errores como valores HRESULT. En C++/CX estos valores se convierten en excepciones fuertemente tipadas que contienen un valor HRESULT y una descripción de cadena a la que se puede tener acceso mediante programación. Las excepciones se implementan como un objeto ref class
que deriva de Platform::Exception
. El espacio de nombres Platform
define clases de excepción distintas para los valores HRESULT más comunes; todos los demás valores se notifican mediante la clase Platform::COMException
. Todas las clases de excepción tienen un campo Exception::HResult que puedes utilizar para recuperar el HRESULT original. También se puede buscar en la información de la pila de llamadas código de usuario en el depurador, que puede ayudarle a identificar el origen de la excepción, incluso si se originó en el código escrito en un lenguaje distinto de C++.
Excepciones
En el programa de C++, se puede producir y detectar una excepción que proceda de una operación de Windows Runtime, una excepción que se derive de std::exception
o un tipo definido por el usuario. Se tiene que producir una excepción de Windows Runtime solo cuando se cruce el límite de la interfaz binaria de aplicación (ABI); por ejemplo, cuando el código que detecta tu excepción se escriba en JavaScript. Cuando una excepción de C++ que no es de Windows Runtime alcanza el límite de la ABI, la excepción se traduce a una excepción Platform::FailureException
, que representa un HRESULT E_FAIL. Para obtener más información acerca de la ABI, consulta Creating Windows Runtime Components in C++.
Se puede declarar una excepción Platform::Exception al usar uno de los dos constructores que toman un parámetro HRESULT o un parámetro HRESULT y un parámetro Platform::String^ que se pueden pasar a través de la ABI a cualquier aplicación de Windows Runtime que los controle. O bien puedes declarar una excepción utilizando una de las dos sobrecargas del método Exception::CreateException que toman un parámetro HRESULT, o un parámetro HRESULT y un parámetro Platform::String^
.
Excepciones estándar
C++/CX admite un conjunto de excepciones estándar que representan errores típicos de HRESULT. Cada excepción estándar deriva de Platform::COMException, que a su vez deriva de Platform::Exception
. Cuando produces una excepción en el límite de ABI, debes producir una de las excepciones estándar.
No puedes derivar tu propio tipo de excepción de Platform::Exception
. Para producir una excepción personalizada, debes utilizar un HRESULT definido por el usuario para construir un objeto COMException
.
En la tabla siguiente se enumeran las excepciones estándar.
Nombre | HRESULT subyacente | Descripción |
---|---|---|
COMException | hresult definido por el usuario | Se produce cuando se devuelve un HRESULT no reconocido de una llamada al método COM. |
AccessDeniedException | E_ACCESSDENIED | Se produce cuando se deniega el acceso a un recurso o a una característica. |
ChangedStateException | E_CHANGED_STATE | Se produce cuando los métodos de un iterador de colección o de una vista de colección se invocan después de que la colección principal haya cambiado, invalidando de este modo los resultados del método. |
ClassNotRegisteredException | REGDB_E_CLASSNOTREG | Se produce cuando una clase COM no se ha registrado. |
DisconnectedException | RPC_E_DISCONNECTED | Se produce cuando un objeto se desconecta de sus clientes. |
FailureException | E_FAIL | Se produce cuando una operación no es correcta. |
InvalidArgumentException | E_INVALIDARG | Se produce cuando uno de los argumentos que se proporcionan a un método no es válido. |
InvalidCastException | E_NOINTERFACE | Se produce cuando un tipo no puede convertirse a otro tipo. |
NotImplementedException | E_NOTIMPL | Se produce si un método de interfaz no se ha implementado en una clase. |
NullReferenceException | E_POINTER | Se produce cuando se intenta desreferenciar una referencia de un objeto null. |
ObjectDisposedException | RO_E_CLOSED | Se produce cuando se realiza una operación en un objeto desechado. |
OperationCanceledException | E_ABORT | Se produce cuando se anula una operación. |
OutOfBoundsException | E_BOUNDS | Se produce cuando una operación intenta tener acceso a datos que están fuera del intervalo válido. |
OutOfMemoryException | E_OUTOFMEMORY | Se produce cuando la memoria es insuficiente para completar la operación. |
WrongThreadException | RPC_E_WRONG_THREAD | Se produce cuando un subproceso llama mediante un puntero de interfaz que es para un objeto proxy que no pertenece al contenedor del subproceso. |
Propiedades HResult y Message
Todas las excepciones tienen una propiedad HResult y una propiedad Message . La propiedad Exception::HResult obtiene el valor HRESULT numérico subyacente de la excepción. La propiedad Exception::Message obtiene la cadena proporcionada por el sistema que describe la excepción. En Windows 8, el mensaje solo está disponible en el depurador y es de solo lectura. Esto significa que no puedes cambiarlo cuando vuelvas a producir la excepción. En Windows 8.1, puedes tener acceso a la cadena de mensaje mediante programación y proporcionar un nuevo mensaje si vuelves a producir la excepción. En el depurador hay disponible una mejor información de la pila de llamadas, incluidas pilas de llamadas para llamadas de método asincrónico.
Ejemplos
En este ejemplo se muestra cómo producir una excepción de Windows Runtime para operaciones sincrónicas:
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);
}
En el ejemplo siguiente se muestra cómo detectar la excepción.
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());
//...
}
Para detectar las excepciones que se producen durante una operación asincrónica, se debe usar la clase de tarea y agregar una continuación de control de errores. La continuación de control de errores vuelve a calcular las referencias de las excepciones que se producen en otros subprocesos al subproceso que realiza la llamada para poder controlar todas las excepciones posibles en solo un punto de tu código. Para más información, vea Programación asincrónica en C++.
Evento UnhandledErrorDetected
En Windows 8.1 se puede suscribir al evento estático Windows::ApplicationModel::Core::CoreApplication::UnhandledErrorDetected, que proporciona acceso a errores no controlados que están a punto de impedir que el proceso se realice correctamente. Independientemente de dónde se originó el error, llega a este controlador como un objeto Windows::ApplicationModel::Core::UnhandledError que se pasa con los argumentos del evento. Cuando llamas a Propagate
en el objeto, se crea y se produce una excepción Platform::*Exception
del tipo correspondiente al código de error. En los bloques catch, puedes guardar el estado del usuario si es necesario y, a continuación, permitir que termine el proceso llamando a throw
o realizar alguna acción para devolver el programa a un estado conocido. En el ejemplo siguiente se muestra el patrón básico:
En app.xaml.h:
void OnUnhandledException(Platform::Object^ sender, Windows::ApplicationModel::Core::UnhandledErrorDetectedEventArgs^ e);
En 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
}
}
Comentarios
C++/CX no utiliza la cláusula finally
.
Consulte también
Referencia del lenguaje C++/CX
Referencia de espacios de nombres