Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Обработка ошибок в C++/CX основана на исключениях. На самом базовом уровне среда выполнения Windows компоненты сообщают об ошибках в виде значений HRESULT. В C++/CX эти значения преобразуются в строго типизированные исключения, содержащие значение HRESULT и строковое описание, к которым можно получить доступ программным способом. Исключения реализованы как классы ref class , производные от класса Platform::Exception. В пространстве имен Platform определены отдельные классы исключений для наиболее часто встречающихся значений HRESULT. Все остальные значения передаются через класс Platform::COMException . Все классы исключений имеют Exception::HResult , которое можно использовать для получения исходного значения HRESULT. Вы также можете проверить сведения о стеке вызовов для пользовательского кода в отладчике, который может помочь определить исходный источник исключения, даже если он был создан в коде, написанном на языке, отличном от C++.
Исключения
В программе C++ можно создавать и перехватывать исключение, полученное из операции среда выполнения Windows, исключение, которое является производным от std::exceptionпользователя или определяемого пользователем типа. Необходимо создать исключение среда выполнения Windows только в том случае, если он пересекает границу двоичного интерфейса приложения (ABI), например, если код, перехватывающий исключение, записывается в JavaScript. Если исключение, отличное от среда выполнения Windows C++, достигает границы ABI, исключение преобразуется в Platform::FailureException исключение, представляющее E_FAIL HRESULT. Дополнительные сведения об интерфейсе ABI см. в разделе Creating Windows Runtime Components in C++.
Вы можете объявить platform::Exception с помощью одного из двух конструкторов, которые принимают либо параметр HRESULT, либо параметр HRESULT и параметр Platform::String^, который можно передать через ABI любому приложению среда выполнения Windows, которое обрабатывает его. Либо можно объявить исключение, воспользовавшись одним из двух перегрузок метода Exception::CreateException , которые могут принимать параметр HRESULT или параметры HRESULT и Platform::String^ .
Стандартные исключения
C++/CX поддерживает набор стандартных исключений, представляющих типичные ошибки HRESULT. Каждое стандартное исключение наследуется от класса Platform::COMException, который, в свою очередь, наследуется от Platform::Exception. Если вы вызываете исключение через границы интерфейса ABI, оно должно быть одним из стандартных исключений.
Делать собственные типы исключений производными от класса Platform::Exceptionне допускается. Чтобы создать пользовательское исключение, используйте определяемое пользователем значение HRESULT для создания объекта COMException .
В следующей таблице перечислены стандартные исключения.
| Имя. | Значение HRESULT | Description |
|---|---|---|
| COMException | Определяемое пользователем значение hresult | Возникает при возвращении неизвестного значения HRESULT после вызова метода COM. |
| AccessDeniedException | E_ACCESSDENIED | Возникает при запрете доступа к ресурсу или функции. |
| ChangedStateException | E_CHANGED_STATE | Возникает, если метод итератора коллекции или представления коллекции вызван после изменения родительской коллекции, что делает результаты метода недействительными. |
| ClassNotRegisteredException | REGDB_E_CLASSNOTREG | Возникает, если COM-класс не зарегистрирован. |
| DisconnectedException | RPC_E_DISCONNECTED | Возникает, если объект отключен от своих клиентов. |
| FailureException | E_FAIL | Возникает, если операция завершается неудачно. |
| InvalidArgumentException | E_INVALIDARG | Вызывается, если один из передаваемых методу аргументов является недопустимым. |
| InvalidCastException | E_NOINTERFACE | Возникает, если тип не удается привести к другому типу. |
| NotImplementedException | E_NOTIMPL | Возникает, если метод интерфейса не реализован в классе. |
| NullReferenceException | E_POINTER | Возникает при попытке разыменовать ссылку на объект NULL. |
| ObjectDisposedException | RO_E_CLOSED | Вызывается при выполнении операции над ликвидированным объектом. |
| OperationCanceledException | E_ABORT | Возникает при отмене операции. |
| OutOfBoundsException | E_BOUNDS | Возникает, когда операция пытается получить доступ к данным за пределами допустимого диапазона. |
| OutOfMemoryException | E_OUTOFMEMORY | Возникает, если недостаточно памяти для выполнения операции. |
| WrongThreadException | RPC_E_WRONG_THREAD | Вызывается, если поток выполняет вызов посредством указателя на интерфейс для прокси-объекта, который не принадлежит к подразделению потока. |
Свойства HResult и Message
Все исключения имеют свойство HResult и свойство Message . Свойство Exception::HResult получает базовое числовое значение HRESULT соответствующего исключения. Свойство Exception::Message получает предоставленную системой строку с описанием исключения. В Windows 8 сообщение доступно только в отладчике и доступно только для чтения. Это означает, что его невозможно изменить после повторного создания исключения. В Windows 8.1 к строке сообщения можно получить доступ программным образом и предоставить новое сообщение, если необходимо заново создать исключение. В отладчике доступны более подробные данные стеков вызовов, включая данные об асинхронных вызовах методов.
Примеры
В этом примере показано, как создать исключение среда выполнения Windows для синхронных операций:
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);
}
В следующем пример показано, как перехватить исключение.
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());
//...
}
Чтобы перехватывать исключения, создаваемые во время асинхронной операции, используйте класс задач и добавьте продолжение обработки ошибок. Продолжение обработки ошибок маршалирует исключения, вызванные в других потоках, обратно вызывающему потоку, что позволяет обрабатывать все возможные исключения в одной структурной единице кода. Дополнительные сведения см. в статье Асинхронное программирование в C++.
Событие UnhandledErrorDetected
В Windows 8.1 вы можете подписаться на статическое событие Windows::ApplicationModel::CoreApplication::UnhandledErrorDetected статического события, которое обеспечивает доступ к необработанным ошибкам, которые собираются сократить процесс. Независимо от того, где возникла ошибка, она достигнет этого обработчика в виде объекта Windows::ApplicationModel::Core::UnhandledError , который передается с аргументами события. При вызове метода Propagate для объекта он создает исключение Platform::*Exception типа, соответствующего коду ошибки. В блоках catch можно при необходимости сохранить состояние пользователя, а затем либо разрешить завершение процесса путем вызова throw, либо каким-либо образом вернуть программу в известное состояние. В следующем примере демонстрируется использование основного подхода:
В app.xaml.h:
void OnUnhandledException(Platform::Object^ sender, Windows::ApplicationModel::Core::UnhandledErrorDetectedEventArgs^ e);
В 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
}
}
Замечания
C++/CX не использует finally предложение.