7

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

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

我不明白的另一件事是,Microsoft 代码质量规则规定永远不应该抛出异常,而应该总是派生类型。原因是不应该强迫任何人去捕捉Exception同样捕捉更多致命异常的将军OutOfMemoryException。另一条规则说,一个人永远不应该Exceptio在图书馆里抓到 n。如果我们被迫使用ExceptionWindows 应用商店应用程序或 WinRT 库,我们如何遵守这些政策?

顺便说一句:Clemens Vasters 在他的博客中展示了我们如何在避免捕获致命异常的同时捕获异常。我认为捕获Exception不再是糟糕的代码。

4

1 回答 1

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;
    }
}

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

或者,更通用的解决方案是编写一个函数或一组函数来处理Exception已知的 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# 中同样适用。

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

于 2012-09-25T18:06:20.440 回答