Search code examples
c#.neterror-handlingvb6com-interop

Raise positive VB style error codes via COM interop from C#


I have a base library created in VB6 that exposes a standard COM interface that is used in a number of applications. This also exposed a number of error code constants, used with Err.Raise to indicate certain conditions.

Public Enum IOErrors
  IOErrorBase = 45000
  IOErrorConnectionFailed
  IOErrorAuthFailed
  IOErrorNotConnected
  IOErrorInvalidPortDirection
  IOErrorGettingValue
  IOErrorNoValueYet
End Enum

Come on 10 years and we're creating C# objects implementing the same set of interfaces and want to throw exceptions in a way that the calling application will recognise them.

I can only find two relevant classes, Win32Exception and COMException.

Throwing Win32Exception((int)IOErrors.IOErrorConnectionFailed, "Connect failed") passes the message back correctly but the error code is ignored and Err.Number is &H80004005.

Throwing COMException("Connect failed", IOErrors.IOErrorConnectionFailed) results in no error being picked up in the calling application, presumably because the error code is not an HRESULT and is positive, meaning success.

TL;DR How can I throw an exception from C# such that COM interop will translate it into one of the recognised (positive) error codes above?


Solution

  • The "positive" VB style error numbers are translated to HRESULTs with a "FAILURE" severity and a facility of FACILITY_CONTROL/0xA, i.e. 0x800AAFC9.

    You can get a suitable HRESULT using:

    int HResult = (int)(0x800A0000 | (int)errorCode);
    

    This can then be raised back to the calling process using a plain COMException, or by throwing your own subclass of COMException:

    /// <summary>
    /// Exception that returns an ICIO error wrapped in an exception.
    /// </summary>
    internal class ICIOErrorException : COMException {
        internal ICIOErrorException(ICIO.IOErrors errorCode, string message)
            : base(message) {
            this.HResult = (int)(0x800A0000 | (int)errorCode);
        }
    }