我有两个应用程序,我都写过。 AppA是使用MFC用C ++编写的。在启动期间,它会注册一个CSingleDocTemplate并创建一个文档。该文档提供了一个COM接口,并在ROT中注册自己:
LPUNKNOWN punk = GetInterface(&IID_Welder); // doesn't AddRef ::RegisterActiveObject(punk, CLSID_Interface, ACTIVEOBJECT_WEAK, &m_dwRegister);
AppA在销毁时撤销ROT中的条目:
if (m_dwRegister) ::RevokeActiveObject(m_dwRegister, NULL);
只有在AppA终止时才会调用析构函数。
AppB是用C#编写的,是AppA提供的界面的客户端:
private void Connect() { welderInterface = (Welder.Interface)Marshal.GetActiveObject("Welder.Interface"); Marshal.GetIUnknownForObject(welderInterface); // AddRef's it ... }(为清晰起见,省略了错误处理)private void Disconnect() { if (welderInterface != null) { Marshal.ReleaseComObject(welderInterface); welderInterface = null; } }
在AppA启动后AppB首次运行时,一切正常; AppB可以根据需要经常调用Connect
和Disconnect
,并使用它们之间的接口。但是,如果AppB终止并再次运行(AppA仍在运行),则该接口不再可用 - Marshal.GetActiveObject
将从MK_E_UNAVAILABLE
引发异常。使界面再次可用的唯一方法是重新启动AppA - 这不是一个可接受的解决方案!
有人可以建议我如何解决这个问题吗?
答案 0 :(得分:4)
::RegisterActiveObject(punk, CLSID_Interface, ACTIVEOBJECT_WEAK, &m_dwRegister);
ACTIVEOBJECT_WEAK是你的问题。来自RegisterActiveObject文档:
弱注册会保留指向运行对象表中对象的指针,但不会增加引用计数。因此,当与弱注册对象的最后一个外部连接消失时,OLE释放对象的存根,并且对象本身不再可用。
这正是您计划中发生的事情。用ACTIVEOBJECT_STRONG解决问题。
答案 1 :(得分:0)
我发现了问题。当AppB断开连接时,接口被删除,即使实现它的MFC文档仍然存在。我在MFC代码中深入钻研,但没有找到任何东西,但它必须在那里发生。
我添加了文件构造函数中的接口,并在析构函数中释放了它,问题就解决了。