问题
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 Exceptio
n 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.
回答1:
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.
来源:https://stackoverflow.com/questions/12586416/how-to-handle-winrt-exceptions-that-result-in-exception