通过C#的COM互操作提高正VB样式错误代码

我有一个在VB6中创建的基础库,它公开了一个在许多应用程序中使用的标准COM接口。 这也暴露了许多错误代码常量,与Err.Raise用于指示某些条件。

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

经过10年,我们正在创建实现相同接口集的C#对象,并希望以调用应用程序识别它们的方式抛出exception。

我只能找到两个相关的类, Win32ExceptionCOMException

抛出Win32Exception((int)IOErrors.IOErrorConnectionFailed, "Connect failed")正确传递消息,但忽略错误代码, Err.Number&H80004005

抛出COMException("Connect failed", IOErrors.IOErrorConnectionFailed)导致调用应用程序中没有错误被COMException("Connect failed", IOErrors.IOErrorConnectionFailed) ,大概是因为错误代码不是HRESULT而且是肯定的,这意味着成功。

TL; DR如何从C#中抛出exception,以便COM互操作将其转换为上面的一个已识别(正)错误代码?

“正”VB样式错误号被转换为HRESULT ,具有“FAILURE”严重性和FACILITY_CONTROL / 0xA ,即0x800AAFC9

您可以使用以下方法获得合适的HRESULT

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

然后可以使用普通的COMException或通过抛出自己的COMException子类将其提升回调用进程:

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