首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >通过COM包装从托管代码调用COM可见托管组件

通过COM包装从托管代码调用COM可见托管组件
EN

Stack Overflow用户
提问于 2010-06-26 00:09:17
回答 2查看 2.4K关注 0票数 16

我有一个第三方组件,比如说FIPreviewHandler来处理预览,它实现了IPreviewHandler。FIPreviewHandler作为托管组件实现,并通过互操作的方式使用IPreviewHandler接口和相关接口。使用regasm.exe将FIPreviewHandler注册为COM。

我有一个客户端应用程序,它也是托管的。我想在我的应用程序中创建一个FIPreviewHandler实例作为COM组件。

我有一个定义IPreviewHandler和相关接口的互操作程序集。

当我使用Activator.CreateInstance()在GetTypeByCLSID()返回的类型上创建FIPreviewHandler的实例时,它为FIPreviewHandler返回了正确的CLSID,它返回一个托管实例,因为它有可用的实际程序集,并跳过COM。当我尝试将此实例QI/强制转换为任何接口时,例如IPreviewHandler,它返回null,因为它是作为托管对象加载的,虽然由FIPreviewHandler实现的IPreviewHandler接口与我在互操作中拥有的接口相同,但它位于不同的命名空间/程序集中,因此返回null。如果它向我返回一个COM实例/RCW (System.__ComObject),它将不会考虑命名空间,并且会转换良好,并返回一个有效实例。

FIPreviewHandler是一个32位组件,在64位的Win7机器上,如果我将我的客户端应用程序编译为"Any CPU",Activator.CreateInstance()会返回一个COM实例/RCW (System.__ComObject),因为它找不到64位的FIPreviewHandler实现,因此返回一个代理。在这种情况下,我的应用程序工作得很好。但当我为x86编译它时,它得到32位实现,并返回实际托管类的托管实例,而不是COM实例,因此失败。

我不能使用在FIPreviewHandler的程序集中定义的接口,因为我必须为IPreviewHandler编写一个通用客户端,并且我的应用程序可以与实现IPreviewHandler的任何组件一起工作,这对于作为COM对象访问FIPreviewHandler的基于C++的客户端非常有效,但是对于托管客户端是失败的。

我希望我说的有道理,我真的很感激任何帮助。

EN

回答 2

Stack Overflow用户

发布于 2011-04-24 20:12:42

我的经验是,微软是故意这样做的。他们不希望您的两个托管代码程序集通过COM进行通信。如果您尝试在项目中添加支持COM作为COM引用的程序集,则会出现同样的错误。

如果COM接口是获得所需功能的唯一方法,则非托管包装应该可以做到这一点。用C++或VB6 (或任何对COM友好的非托管语言)编写一个新的COM服务器,它包装了您的第三方托管COM服务器。然后,将此新包装DLL作为COM服务器添加到托管代码项目中。

票数 1
EN

Stack Overflow用户

发布于 2011-04-27 09:12:46

使用PInvoke调用COM函数CoCreateInstance(Ex),并将互操作程序集中定义的CLSID和IPreviewHandler的IID传递给它。这样,.NET就没有机会进行干预了。

你说你有一个互操作程序集。如果这是由第三方程序集的作者分发的PIA,这是最好的,但如果您必须自己构建它,也没问题。(PIA不必在GAC中注册,尽管它们通常是注册的。)您可以通过在IL反汇编程序中加载互操作程序集并查找类的System.Runtime.InteropServices.GuidAttribute属性来获取CLSID。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3119596

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档