HRESULT Information in Managed Code
The interaction between managed code and COM can present issues when dealing with HRESULT return values.
In a COM interface, an HRESULT return value can play two roles:
To deliver error information (for example,).
To deliver status information about normal program behavior.
When COM calls into managed code, HRESULTs can cause two problems:
COM functions that return HRESULT values less than zero (failure codes) generate exceptions.
COM methods that regularly return two or more different success codes, such asor , cannot be distinguished.
Because many of the Visual Studio SDK COM functions either return HRESULT values less than zero or return different success codes, the Visual Studio SDK interop assemblies have been written so that the method signatures are preserved. All Visual Studio SDK interop methods are of int type. HRESULT values are passed through the interop layer without alteration and without generating exceptions.
Because a COM function returns an HRESULT to the managed method that calls it, the calling method must check the HRESULT and throw exceptions as necessary.
Handling HRESULTs Returned to Managed Code from COM
When you call a COM interface from managed code, you should examine the HRESULT value and throw an exception if necessary. Theclass contains the method, which throws a COM exception, depending on the value of the HRESULT passed to it.
By default, ThrowOnFailure throws an exception whenever it is passed an HRESULT with a value less than zero. In cases where one or more such HRESULTs are acceptable values and no exception should be thrown, the values of additional HRESULTS should be passed toafter the values are tested. If the HRESULT being tested matches any HRESULT values explicitly passed to ThrowOnFailure, no exception is thrown.
Theclass contains constants for common HRESULTS, such as S_OK and , and Visual Studio HRESULTS, such as and . VSConstants also provides the and methods, which correspond to the Succeeded method and Failed macros in COM.
For example, consider the following function call, in which E_NOTIMPL is an acceptable return value but any other HRESULT less than zero represents an error:
int hr = MyInterface.MyFunction(cmdID); ErrorHandler.ThrowOnFailure(hr, VSConstants.E_NOTIMPL);
If there is more than one acceptable return value, additional HRESULT values can simply be appended to the list in the call to ThrowOnFailure:
int hr = MyInterface.MyFunction(cmdID); ErrorHandler.ThrowOnFailure(hr, VSConstants.E_NOINTERFACE, VSConstants.E_NOTIMPL);
Returning HRESULTS to COM from Managed Code
If no exception occurs, managed code returns S_OK to the COM function that called it. COM interop supports common exceptions that are strongly typed in managed code. For example, a method that receives an unacceptable null argument throws an.
If you are not certain which exception to throw, but you know the HRESULT you would like to return to COM, you can use themethod to throw an appropriate exception. This works even with a nonstandard error, such as VS_E_INCOMPATIBLEDOCDATA. ThrowExceptionForHR attempts to map the HRESULT passed to it to a strongly typed exception. If it cannot, it throws a generic COM exception instead. The ultimate result is that the HRESULT you pass to ThrowExceptionForHR from managed code is returned to the COM function that called it.
Exceptions compromise performance and are intended to indicate abnormal program conditions. Conditions that occur often should be handled inline, rather than with a thrown exception.