我目前正在升级到一个广泛使用COM / MFC /(谁知道有多少其他技术)的项目。作为升级的一部分,我们尝试将尽可能多的功能移植到托管C#代码中,但遗憾的是有些东西无法移动(原因我不会进入)。其中一个问题是严重滥用COM的代码段,并返回HRESULT中的指针,这些指针稍后会被转换为各种其他COM接口实现对象。我已经尝试了以下代码将HRESULT转换为指针,然后我可以从中获取接口:
MyComInterfaceInCS myObj = null;
try
{
world.GetTD_MyComInterfaceInCS();
}
catch (COMException comException)
{
int pointerValue = Marshal.GetHRForException(comException);
IntPtr myObjPointer = new IntPtr(pointerValue);
myObj = (MyComInterfaceInCS) Marshal.GetObjectForIUnknown(myObjPointer);
}
.... 但是,没有抛出COM异常,我猜它是因为指针不是负值,因此从技术上来说不是COM错误。有没有办法在对象上配置COM以在任何事件上抛出COM异常但是S_OK(0)?
答案 0 :(得分:5)
两个想法:
修改
另一种选择是在C#中声明COM接口,使得每个方法的签名返回一个HRESULT并使用[out retval]作为返回值。这将使您获得并检查所有方法调用的HRESULT,而不仅仅是抛出COMException的方法。
默认情况下,COM interop typeimport“修复”方法签名,以便在管理端删除HRESULT返回,并且interop层抛出E_FAIL等异常,基本上丢弃S_OK,S_FALSE等。
This article有一些解释,PreserveSig attriubte文档有一些额外的细节。
这可能需要您手动声明所有COM接口而不是使用tlbimp,但您可以使用tlbimp来保留COM方法的签名。
这样你就可以完全保留在C#中了,但是你可以选择使用托管C ++,因为它更容易以非标准的方式与COM进行交互。