异常处理 – 如何处理导致异常的WinRT异常?

如果Windows运行时类型引发COM错误.NET似乎经常(或总是?)将此错误包装到Exception实例中.错误消息包含COM HRESULT错误代码.例如,当使用带有AES-CBC的新Cryptographic API时,错误的缓冲区长度会导致异常,并显示消息“提供的用户缓冲区对请求的操作无效.(HRESULT异常:0x800706F8)”.

那么,我们应该如何处理这些例外?我们是否应该从异常中读取HRESULT代码以了解哪种异常是什么?在经典的.NET中,我会得到一个CryptographicException,我可以使用它来区分加密错误和其他错误.

我不明白的另一件事是Microsoft代码质量规则规定一个人永远不应该抛出Exception但总是派生类型.原因是没有人应该被强制捕获一般的Exception,它会捕获更多致命的异常,比如OutOfMemoryException.另一条规则说,永远不应该在图书馆中捕获异常.如果我们被迫在Windows应用商店应用或WinRT库中捕获异常,我们如何才能遵循这些策略?

顺便说一句:Clemens Vasters shows in his blog how we can catch Exception while avoiding to catch fatal exception.我假设捕获异常不再是坏代码.

最佳答案
可以捕获异常,通过打开HRESULT来处理特定错误,并在错误“意外”时重新抛出异常.例如,

try
{
    // ...
}
catch (Exception ex)
{
    switch (ex->HResult)
    {
    case E_INVALID_USER_BUFFER: // 0x800706f8
        // handle invalid buffer case...
        break;
    default:
        // Unexpected exception; re-throw:
        throw;
    }
}

(我会注意到,提供无效的缓冲区听起来更像是一个逻辑错误,而不是运行时错误,所以我想知道是否应该抓住这个特殊的异常.)

或者,更通用的解决方案是编写一个函数或一组函数来处理已知HRESULT的异常并重新抛出更具体的异常.例如,

static void HandleKnownExceptions(Action f)
{
    try
    {
        f();
    }
    catch (Exception ex)
    {
        // Detect expected HRESULTs and throw the more-specific exception
        // type for each.
    }
}

这两种方法在C和C#中同样有效.

请注意,不一定是平台或其他组件直接抛出异常的情况.在Windows运行时ABI层,没有例外:HRESULT在ABI边界上报告所有错误. CLR将少数已知的HRESULT转换为更具体的异常类型,但它无法执行常规转换.

转载注明原文:异常处理 – 如何处理导致异常的WinRT异常? - 代码日志