COM接口从ROT中消失
Posted
技术标签:
【中文标题】COM接口从ROT中消失【英文标题】:COM interface disappears from ROT 【发布时间】:2010-08-02 11:18:48 【问题描述】:我有两个应用程序,两个都是我写的。 AppA 是使用 MFC 用 C++ 编写的。在启动期间,它注册一个 CSingleDocTemplate 并创建一个文档。该文档提供了一个COM接口并在ROT中注册了自己:
LPUNKNOWN punk = GetInterface(&IID_Welder); // 不添加引用 ::RegisterActiveObject(朋克,CLSID_Interface,ACTIVEOBJECT_WEAK,&m_dwRegister);
AppA在销毁时撤销ROT中的条目:
if (m_dwRegister) ::RevokeActiveObject(m_dwRegister, NULL);
析构函数仅在 AppA 终止时调用。
AppB是用C#编写的,是AppA提供的接口的客户端:
私人无效连接() welderInterface = (Welder.Interface)Marshal.GetActiveObject("Welder.Interface"); Marshal.GetIUnknownForObject(welderInterface); // AddRef 是它...(为清楚起见省略了错误处理)私人无效断开连接() 如果(焊接接口!= null) Marshal.ReleaseComObject(welderInterface); 焊机接口=空;
在 AppA 启动后 AppB 第一次运行时一切正常; AppB 可以随时调用Connect
和Disconnect
,并使用它们之间的接口。但是,如果 AppB 终止并再次运行(AppA 仍在运行),则接口不再可用 - Marshal.GetActiveObject
会从 MK_E_UNAVAILABLE
引发异常。使界面再次可用的唯一方法是重新启动 AppA - 这不是一个可接受的解决方案!
请有人建议我如何解决这个问题?
【问题讨论】:
只是一个建议,但您是否尝试过使用 GetRunningObjectTable 和 CreateBindCtx 来访问 ROT 并获取您的 COM 接口。这种方法有同样的问题吗? 不,我没有尝试过,但我没有理由认为它会有所不同。我认为问题出在 MFC 代码的某个地方(或我使用它的方式)。如果有时间我可以试试。我相信我将不得不 p/Invoke 这些功能。我说的对吗? 是的,使用 GetRunningObjectTable 将涉及 P/Invoke。请参阅以下相关示例:***.com/questions/3268483/… 这里有一篇文章展示了如何去做codeproject.com/KB/cs/automatingvisualstudio.aspx 【参考方案1】: ::RegisterActiveObject(punk, CLSID_Interface, ACTIVEOBJECT_WEAK, &m_dwRegister);
ACTIVEOBJECT_WEAK 是您的问题。来自 RegisterActiveObject 文档:
弱注册在运行对象表中保留一个指向对象的指针,但不增加引用计数。因此,当与弱注册对象的最后一个外部连接消失时,OLE 会释放该对象的存根,并且该对象本身不再可用。
这正是您的程序中正在发生的事情。用 ACTIVEOBJECT_STRONG 轻松解决问题。
【讨论】:
【参考方案2】:我发现了问题。当 AppB 断开连接时,该接口被删除,即使实现它的 MFC 文档仍然存在。我对 MFC 代码进行了相当深入的研究,但没有发现任何东西,但它一定是在某个地方发生的。
我在 doc 构造函数中添加了接口并在析构函数中释放了它,问题就解决了。
【讨论】:
以上是关于COM接口从ROT中消失的主要内容,如果未能解决你的问题,请参考以下文章