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::COMException 从
Platform::Exception
派生。 当跨 ABI 边界引发异常时,必须引发一个标准异常。
不能从
Platform::Exception
派生您自己的异常类型。 若要引发自定义异常,请使用用户定义的 HRESULT 构造
COMException
对象。
下表列出了标准异常。
基础 HRESULT
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();
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::Core::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.
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
子句。
C++/CX 语言参考
命名空间参考