在C#中定义COM类时,通常会有如下签名:
void Login(string user,string password)
自动COM互操作包装器意味着从C ++调用时:
HRESULT
S_OK
但是,如果您想要返回S_OK
以外的成功代码,该怎么办?例如S_FALSE
或某些习惯"成功,但......"值?
注意:我在C#中定义了类,并想知道如何控制COM互操作的功能。不基于IDL中的现有接口在C#中实现类。
答案 0 :(得分:3)
HRESULT
通常只是一个错误代码数据。它很少用于传达成功; S_FALSE
是唯一明确定义的例外。在S_FALSE
的情况下,它通常仅在结果类型为COM布尔值(VARIANT_BOOL
)时使用,并且HRESULT
在返回时返回(S_FALSE
)VARIANT_FALSE
(S_OK
时为VARIANT_TRUE
。
维基百科还讨论了HRESULT
的COM错误和.Net / COM边界(from here);
在.NET Framework中,当从本机代码转换为托管代码时,HRESULT / IErrorInfo错误代码将转换为CLR异常;从托管COM转换为本机COM代码时,CLR异常转换为HRESULT / IErrorInfo错误代码。
虽然没有定论,但肯定会重新强调HRESULT
通常被视为错误代码的事实。访问IErrorInfo
可能会提供更多数据,但我不确定它是否符合您的预期或期望。
This MSDN article确实提供了有关如何映射COM错误和异常的更多信息,再次支持错误代码;
COM方法通过返回HRESULT报告错误; .NET方法通过抛出异常来报告它们。运行时处理两者之间的转换。 .NET Framework中的每个异常类都映射到HRESULT。
支持"成功代码"您可以使用其他[out]
参数。如果代码在您的控件之外,您可以编写一个瘦COM对象来为您映射,然后在.Net对象中使用它。
或者,您可以使用PreserveSigAttribute
,但据我所知,它不会将错误转换为异常,因此您需要自己执行此操作(验证此操作的测试)建议)。用[PreserveSig]
注释方法应该可以解决问题。
答案 1 :(得分:2)
您必须在方法声明中使用[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。