HRESULT Information in Managed Code

The interaction between managed code and COM can cause problems when HRESULT return values are encountered.

In a COM interface, an HRESULT return value can play these roles:

  • Deliver error information (for example, E_INVALIDARG).

  • Deliver status information about normal program behavior.

When COM calls into managed code, HRESULTs can cause these 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, for example, S_OK or S_FALSE, 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, examine the HRESULT value and throw an exception if required. The ErrorHandler class contains the ThrowOnFailure 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 that has a value less than zero. In cases where such HRESULTs are acceptable values and no exception should be thrown, the values of additional HRESULTS should be passed to ThrowOnFailure after the values are tested. If the HRESULT being tested matches any HRESULT values explicitly passed to ThrowOnFailure, no exception is thrown.

Note

The VSConstants class contains constants for common HRESULTS, for example, S_OK and E_NOTIMPL, and Visual Studio HRESULTS, for example, VS_E_INCOMPATIBLEDOCDATA and VS_E_UNSUPPORTEDFORMAT. VSConstants also provides the Succeeded and Failed 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.

Dim hr As Integer = MyInterface.MyFunction(cmdID)
ErrorHandler.ThrowOnFailure(hr, VSConstants.E_NOTIMPL)
int hr = MyInterface.MyFunction(cmdID);
ErrorHandler.ThrowOnFailure(hr, VSConstants.E_NOTIMPL);

If there are more than one acceptable return values, additional HRESULT values can just be appended to the list in the call to ThrowOnFailure.

Dim hr As Integer = MyInterface.MyFunction(cmdID)
ErrorHandler.ThrowOnFailure(hr, VSConstants.E_NOINTERFACE, VSConstants.E_NOTIMPL)
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 ArgumentNullException.

If you are not certain which exception to throw, but you know the HRESULT you want to return to COM, you can use the ThrowExceptionForHR method to throw an appropriate exception. This works even with a nonstandard error, for example, 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.

Note

Exceptions compromise performance and are intended to indicate abnormal program conditions. Conditions that occur often should be handled inline, instead of a thrown exception.

See Also

Tasks

How to: Map HRESULTs and Exceptions

Concepts

Building COM Components for Interoperation

Other Resources

Managed VSPackages

Interoperating with Unmanaged Code

Managed VSPackages