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