【发布时间】:2019-07-26 16:16:13
【问题描述】:
TL;DR - 如何防止-Embedding 启动CLSCTX_LOCAL_SERVER 服务器?最好让客户立即得到一个像样的错误代码。
背景
我们有一个本机 C++ 交互式桌面应用程序,它与另一个本机 C++ 交互式桌面应用程序中的 COM 对象进行交互。
基本上,COM 被用作进程间通信机制。
现在,当“服务器”应用程序在用户进入正确状态后以交互方式启动时,它将准备 COM 接口:CoRegisterClassObject 等。
当客户端应用程序被使用,然后它是 CoCreateInstance 的 coclass 时,它将与已经运行的其他桌面应用程序通信,这是预期的。
但是,当“服务器”应用程序没有运行时,启动客户端会以交互方式启动服务器应用程序,这不是我们想要的,因为它需要相当多的处理和设置,然后客户端才能与它进行有意义的通信。
问题
因此,更有意义的是让客户端在服务器未运行的情况下仅出错,而不是让 COM 基础架构启动一个无论如何都无法有意义地为请求提供服务的交互式应用程序。
我们玩弄了以下想法:
- 每次关闭服务器时取消注册。
- 这似乎行不通,因为我们需要管理权限来注册/取消注册服务器。
- 在客户端使用
CLSCTX_DISABLE_AAA标志。- 这似乎行得通,如果客户端指定了这个并且服务器没有运行,它将得到
0x80070005 ERROR_ACCESS_DENIED,但我们不确定这是否是正确的方法。
- 这似乎行得通,如果客户端指定了这个并且服务器没有运行,它将得到
- 提前检查服务器应用程序以检测
-Embedding开关并立即退出应用程序。- 客户端应用程序将运行超时(约 2 分钟),这对用户不是很友好。
-
来自 cmets 不要将信息写入注册表 -
CoRegisterClassObjectshould be enough。- 目前,我有:
HKCR\AppID (...)-
HKCR\CLSID\{...}加上子键ProgID,VersionIndependentProgID,LocalServer32,Typelib
- 客户端当前从 VersionIndependentProgID 解析 CLSID
- 所以我想知道注册表的哪些部分是真正可选的。
- 目前,我有:
是否有任何“标准”方法来阻止对给定的已注册 COM 类激活 COM 本地服务器可执行文件?
【问题讨论】:
-
COM 注册不需要管理员权限,但您必须在 HKCU 而不是 HKLM 下注册所有内容(这在您的上下文中似乎是有意义的)。否则你不必使用 CoCreateInstance 来获取引用,你可以使用运行对象表,从客户端检查你的服务器是否在其中注册了一些东西并调用 IRunningObjectTable::GetObject
-
当检测到 -Embedding 参数时,您可以尝试立即发出 CoRegisterClassObject 调用然后退出。客户端将在没有超时的情况下获得 CO_E_SERVER_EXEC_FAILURE……是的,这很难看。
-
对于 inproc com 对象,您不需要将它们放在注册表中 - 您可以在运行时注册它们的类工厂。我想知道这是否可以通过注册代理对象来应用于进程外 COM 对象...
-
CoRegisterClassObject 只是将您的对象发布到 COM(作为 oop 服务器),它对 ROT 没有任何作用。调用 CoRegisterClassObject 后,必须从服务器调用 IRunningObjectTable::Register,从客户端调用 IRunningObjectTable::GetObject。
-
只是不要在注册表中注册您的对象 clsid。如果服务器还没有调用
CoRegisterClassObject客户端得到错误REGDB_E_CLASSNOTREG,否则调用CoRegisterClassObject是enouth
标签: windows winapi visual-c++ com