从c#中定义的COM类返回成功代码
本文关键字:返回 成功 代码 COM 定义 | 更新日期: 2023-09-27 18:17:45
当你在c#中定义一个COM类时,你通常有这样的签名:
void Login(string user,string password)
自动COM互操作包装意味着当从c++调用时:
- 抛出异常被转换为失败
HRESULT
- 不返回任何值转换为返回
S_OK
但是,如果您想返回S_OK
以外的成功代码,该怎么办?例如S_FALSE
或一些自定义的"成功,但是……"值?
注意:我正在用c#定义类,想知道如何控制COM互操作的功能。没有在c#中实现基于IDL中已有接口的类
HRESULT
通常是一个只有错误码的基准。它很少被用来表达成功;S_FALSE
是唯一定义良好的例外。在S_FALSE
的情况下,它通常只在结果类型为COM布尔值(VARIANT_BOOL
)时使用,当返回(输出)为VARIANT_FALSE
时将HRESULT
映射为S_FALSE
(当VARIANT_TRUE
时将S_OK
)。
维基百科还讨论了HRESULT
对于COM和。net/COM边界错误的情况;
在。net框架中,当从本机代码转换为托管代码时,HRESULT/IErrorInfo错误代码被转换为CLR异常;当从托管到本机COM代码转换时,CLR异常被转换为HRESULT/IErrorInfo错误代码。
虽然不是决定性的,但它确实强化了HRESULT
通常被视为错误代码的事实。访问IErrorInfo
可能会提供一些更多的数据,但我不确定它会像你期望的或希望的那样。
这篇MSDN文章提供了更多关于如何映射COM错误和异常的信息,同样支持错误代码;
COM方法通过返回HRESULTs报告错误;. net方法通过抛出异常来报告它们。运行时处理两者之间的转换。. net框架中的每个异常类都映射到一个HRESULT。
支持"成功码"您可以使用额外的[out]
参数。如果代码不在您的控制范围内,您可以编写一个瘦COM对象来为您映射它,然后在。net对象中使用它。
PreserveSigAttribute
, ,但据我所知,它不会将错误转换为异常,因此您需要自己做(建议进行测试以验证这一点)。用[PreserveSig]
注释该方法应该可以达到目的。
必须在方法声明中使用[PreserveSig]
属性。也就是说,它保留了方法签名,并防止类型库导出器重写方法签名以使其与COM兼容。返回类型必须为int
,以便与HRESULT兼容。
你的例子很简单:
void Login(string user, string password);
就变成:
[PreserveSig]
int Login(string user, string password);
当它是一个非void返回类型的方法时,它就更复杂了。然后必须按照类型库导出器的方式重写它。将其作为ref
关键字的额外参数添加。所以:
bool Login(string user, string password);
就变成:
[PreserveSig]
int Login(string user, string password, ref bool success);
请记住,S_FALSE的值是1,而不是0。