COM接口从ROT中消失

时间:2010-08-02 11:18:49

标签: c# .net visual-c++ mfc

我有两个应用程序,我都写过。 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可以根据需要经常调用ConnectDisconnect,并使用它们之间的接口。但是,如果AppB终止并再次运行(AppA仍在运行),则该接口不再可用 - Marshal.GetActiveObject将从MK_E_UNAVAILABLE引发异常。使界面再次可用的唯一方法是重新启动AppA - 这不是一个可接受的解决方案!

有人可以建议我如何解决这个问题吗?

2 个答案:

答案 0 :(得分:4)

 ::RegisterActiveObject(punk, CLSID_Interface, ACTIVEOBJECT_WEAK, &m_dwRegister);

ACTIVEOBJECT_WEAK是你的问题。来自RegisterActiveObject文档:

弱注册会保留指向运行对象表中对象的指针,但不会增加引用计数。因此,当与弱注册对象的最后一个外部连接消失时,OLE释放对象的存根,并且对象本身不再可用。

这正是您计划中发生的事情。用ACTIVEOBJECT_STRONG解决问题。

答案 1 :(得分:0)

我发现了问题。当AppB断开连接时,接口被删除,即使实现它的MFC文档仍然存在。我在MFC代码中深入钻研,但没有找到任何东西,但它必须在那里发生。

我添加了文件构造函数中的接口,并在析构函数中释放了它,问题就解决了。