使用ExeCOMServer时,无法将类型为“…”的COM对象转换为接口类型“…”

我正在使用这个exe com服务器:

https://cfx.svn.codeplex.com/svn/Visual%20Studio%202008/CSExeCOMServer/ExeCOMServer.cs

  • 我的编程是一个com应用程序
  • 采用另一个com对象的我的com方法是void Init(AppsScriptRunningContext rc);
  • 在这个方法中,我尝试读出一个属性并得到此错误

无法将“AppsScriptLib.AppsScriptRunningContextClass”类型的COM对象强制转换为接口类型“AppsScriptLib.IAppsScriptRunningContext”。 此操作失败,因为对于具有IID“{4D2E5723-87C2-49C1-AA28-ED2D88275100}”的接口的COM组件的QueryInterface调用由于以下错误而失败:不支持此类接口(HRESULTexception:0x80004002(E_NOINTERFACE))

如果我的应用程序不是com服务器而是普通的com应用程序,则没有错误。 这就是为什么我认为错误是由exe com服务器产生的。

https://cfx.svn.codeplex.com/svn/Visual%20Studio%202008/CSExeCOMServer/ExeCOMServer.cs

问候,克里斯

这是一个非常令人遗憾的代码示例,与它成功的可能性非常接近于零。 它是MSDN论坛支持小组的产品,他们的工作未在Microsoft进行同行评审。 一位团队成员后来承认这不是正确的方法。

该代码的一个问题是它完全忽略了注册服务.RegisterTypeForComClients()方法的MSDN文档中的备注:

请注意,不支持使用平台调用来调用非托管CoRegisterClassObject和CoDisconnectObject方法以注册和取消注册COM对象。

不幸的是,没有解释为什么它不受支持。 关键问题是COM接口总是需要在进程外激活情况下进行封送。 这是通过在客户端创建代理来完成的,该代理是一个接口实例,它具有与原始接口完全相同的方法,但其实现的方法通过RPC将方法的参数发送给另一个进程。 在服务器端,存根执行相同但相反的角色,使用方法参数构建堆栈帧并进行实际的方法调用。

在.NET中创建代理和存根非常简单,reflection使其变得简单。 由内置于框架中的Remoting管道完成。 然而,它在COM中并不容易,它没有任何类似于reflection的东西。 它有两种基本的完成方式,首先是用IDL语言编写COM接口定义并用midl.exe编译它。 这可以自动生成执行编组的C源代码,您可以从中构建DLL。 然后需要在HKCR \ Interface注册表项中正确注册该DLL,以便COM可以在需要封送接口时查找并加载DLL。 如果您的接口派生自IDispatch并将其自身限制为OLE自动化兼容的参数类型,则可以使用第二种方法。 然后,您可以生成类型库并使用标准编组器。 这需要注册类型库,以及HKCR \ Interface中的相应键,以便COM了解它。

这是.NET进程外服务器中不会​​发生的部分。 您没有midl.exe来帮助您生成代理/存根DLL,并且您没有获得使用标准编组器的注册帮助。 这是错误信息的真正含义,E_NOINTERFACE在这里真的意味着它找不到任何方法来编组接口。 是的,糟糕的错误消息。

.NET中正式支持的创建进程外COM服务器的方法是将其注册到COM +。 使用System.EnterpriseServices.ServicedComponent类作为基类。 MSDN库文章在这里 。

我得到了一个建议,在主线程中进行更改,这对我有所帮助!

在主线程中查找(主要在“Program.cs”中)[STAThread]行并将其更改为[MTAThread]。