How to handle WinRT exceptions that result in Exception?

7

If a Windows runtime type raises a COM error .NET seems to wrap this error often (or always?) just into an Exception instance. The error message includes the COM HRESULT error code. When using the new Cryptographic API with AES-CBC for example a wrong buffer length results in an Exception with the message "The supplied user buffer is not valid for the requested operation. (Exception from HRESULT: 0x800706F8)".

Well, How are we supposed to handle those exceptions? Should we read the HRESULT code from the exception to get an idea what kind of exception that was? In classic .NET I would get a CryptographicException that I could use to distinguish cryptographic errors from other errors.

Another thing that I do not understand is that the Microsoft code quality rules state that one should never throw Exception but always derived types. The reason is that no one should be forced to catch the general Exception that catches more fatal exceptions like OutOfMemoryException as well. Another rule says that one should never, ever catch Exception in libraries. How could we follow these policies if we are forced to catch Exception in Windows Store apps or WinRT libraries?

By the way: Clemens Vasters shows in his blog how we can catch Exception while avoiding to catch fatal exception. I assume catching Exception is no longer bad code then.

exception-handling
windows-runtime
hresult
asked on Stack Overflow Sep 25, 2012 by Jürgen Bayer • edited May 6, 2015 by Camilo Martinez

1 Answer

4

It is possible to catch Exception, handle particular errors by switching on the HRESULT, and re-throwing the Exception if the error was "unexpected." For example,

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

(I would note that providing an invalid buffer sounds more like a logic error than a runtime error, so I wonder whether this particular exception should really be caught.)

Alternatively, a more general solution would be to write a function or set of functions that handle Exception for known HRESULTs and re-throws a more specific exception. For example,

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

Both of these approaches work equally well in both C++ and C#.

Note that it isn't necessarily the case that Exception is thrown directly by the platform or other components. At the Windows Runtime ABI layer, there are no exceptions: all errors are reported across the ABI boundary by HRESULT. The CLR translates a handful of known HRESULTs to more specific exception types, but it cannot perform a general translation.

answered on Stack Overflow Sep 25, 2012 by James McNellis

User contributions licensed under CC BY-SA 3.0