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

时间:2012-09-25 15:39:28

标签: exception-handling windows-runtime hresult

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

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

我不明白的另一件事是Microsoft代码质量规则规定一个人永远不应该抛出Exception但总是派生类型。原因是不应该强迫任何人抓住一般Exception来抓住更多致命的例外,例如OutOfMemoryException。另一个规则是,永远不应该在库中捕获Exceptio n。如果我们被迫在Windows应用商店应用或WinRT库中捕获Exception,我们如何才能遵循这些政策?

顺便说一下:Clemens Vasters shows in his blog how we can catch Exception while avoiding to catch fatal exception。我认为捕捉Exception不再是坏代码。

1 个答案:

答案 0 :(得分:4)

可以捕获Exception,通过打开HRESULT处理特定错误,并在错误“意外”时重新抛出Exception。例如,

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的Exception并重新抛出更具体的异常。例如,

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

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

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