Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle WinRT exceptions that result in Exception?

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.

like image 522
Jürgen Bayer Avatar asked Sep 25 '12 15:09

Jürgen Bayer


1 Answers

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.

like image 65
James McNellis Avatar answered Sep 27 '22 18:09

James McNellis