我有一个 Win32/MFC 应用程序,它依赖于我多年前使用 C++/ATL 创建的两个独立的 STA COM DLL 服务器。这些是具有多个接口的大型 DLL 服务器,并且也成功地用于其他上下文和客户端程序。几年前,我必须创建这些 32 位服务器的 64 位版本,而我的 32 位 MFC 应用程序需要能够使用 32 位或 64 位版本的 DLL COM 服务器(选择一个复选框)。
因为 32 位进程无法在进程中加载 64 位 COM 服务器 DLL,所以我通过让 MFC 应用程序通过替换在系统代理 (DLLHOST.EXE) 中创建 64 位服务器来解决此问题
CoCreateInstance(..., CLSCTX_INPROC_SERVER, ...)
和
CoCreateInstance(..., CLSCTX_LOCAL_SERVER | CLSCTX_ACTIVATE_64_BIT_SERVER, ...)
需要进行一些更新,例如添加一个接口以将环境变量复制到服务器进程并设置服务器/代理的工作目录(代理从 SYSTEM32 开始),但其他接口都是可远程的。这一切似乎都很完美,我现在可以通过拨动开关从 32 位应用程序互换使用 32 位和 64 位服务器。
但是,有一个问题我无法解决:当客户端释放最后一个 interface 时,让代理快速终止。在 MFC 客户端释放所有远程接口后,代理会挂起 3-5 秒——大概是一种优化,希望客户端能回来。如果 MFC 应用程序在这 3-5 秒内使用CoCreateInstance()重新启动服务器,它会重新连接到相同的“脏”代理。服务器代码不可串行重用(它封装了数千行带有大量静态变量的遗留 ANSI“C”代码),因此重新连接到同一个实例是不可能的。
几年前,我通过让启动界面返回一个 COM 错误代码来解决这个问题,指示服务器正在等待回收(比崩溃好)。但是,当最终用户按下 MFC 应用程序中的工具栏按钮时,服务器会启动,因此这意味着用户会收到类似“等待几秒钟并重试”的消息。这行得通,但不好的部分是每次新的启动尝试都会重置 3-5 秒计数器,以防止代理退出。不耐烦的用户正在抱怨。我将添加这一切都在过程中完美地CoFreeUnusedLibraries()
工作,并按预期工作。
我已经尝试了很多东西——ExitProcess()
除了在服务器中编码之外的所有东西,这似乎不合适。似乎没有办法告诉代理程序应用程序已完成,不应等待更多连接。MS 文档声称在 AppID 中省略RunAs属性可能会有所帮助(我将其设置为"Interactive User")但它没有。它还提到REGCLS_SINGLUSE
但随后说“在为 DLL 服务器注册代理时不要设置 REGCLS_SINGLUSE 或 REGCLS_MULTIPLEUSE”和“REGCLS_SINGLUSE 和 REGCLS_MULTIPLEUSE 不应用于加载到代理中的 DLL 服务器。” 而且我无法控制代理的内容'
看起来 COM+ 可能会对回收提供一些控制,因为它似乎有一个RecycleActivationLimit选项,我可以将其设置为 0,但我不知道将其转换为 COM+ 服务器需要什么。
另一种可能性是编写自定义代理。
如果没有简单的答案,我可能会只使用灰色按钮,直到服务器消失 - 但由于我无法在不延长其生命周期的情况下探测服务器,我想我可以添加一个共享互斥体并等待它消失。啊。
RecycleActivationLimit 是否可用于常规 COM 应用程序?欢迎任何其他建议。