来自同一用户帐户的 LocalServer32 EXE 的 COM 激活是不是共享现有进程?

Posted

技术标签:

【中文标题】来自同一用户帐户的 LocalServer32 EXE 的 COM 激活是不是共享现有进程?【英文标题】:Does COM activation of LocalServer32 EXE from the same user account share an existing process or not?来自同一用户帐户的 LocalServer32 EXE 的 COM 激活是否共享现有进程? 【发布时间】:2011-07-03 09:03:27 【问题描述】:

当客户端应用程序调用 c_com_ptr::CreateInstance(使用 ATL 包装器)时,我启动了 COM 服务器 LocalServer32 EXE。

在 Windows 7 上,当在同一用户帐户下运行的第二个客户端应用程序也调用 c_com_ptr::CreateInstance 时,将启动在同一用户帐户下运行的 EXE 的第二个副本。我前世的印象是,第二个客户会分享第一个 EXE。

LocalServer32 进程是否共享?什么时候,什么时候不?谷歌搜索答案会给我一个巨大的噪声信号比,我找不到答案。

我的 CLSID 注册表项的 LocalServer32 值给出了 EXE 路径、ProgID、可编程(空字符串)、TypeLib (GUID) 和 VersionIndependentProgId。我有一个 AppID 密钥。

我确实想将 EXE 作为服务运行,而且我不介意进程不共享。我只想知道规则,以便知道会发生什么(在 Windows Server 2003 及更高版本上)。

编辑:按照下面 Chris 的回答,我检查了我的服务器中的 CoRegisterClassObject 调用。我正在使用 ATL,并且我覆盖了 MyServer::RegisterClassObjects 以挂钩到 CAtlExeModuleT::RegisterClassObjects 的调用链,并看到 ATL 正在使用 CLSCTX_LOCAL_SERVER 和 REGCLS_MULTIPLEUSE。

将其更改为 CLSCTX_LOCAL_SERVER 和 REGCLS_SINGLEUSE 会导致启动更多进程,具体取决于客户端创建的 COM 对象的数量,正如预期的那样。

仍然,回到 REGCLS_MULTIPLEUSE,我得到每个 COM 客户端进程一个 COM 服务器进程,每个服务器进程都包含其客户端的所有 COM 对象,如预期的那样,除非两个 COM 客户端在同一个用户帐户下运行,他们每个人都有自己的服务器,这不是我理解的 REGCLS_MULTIPLEUSE。

可能不同之处在于客户端本身实际上是 Windows 服务吗? (它们是。)当作为用户帐户运行的 Windows 服务进程在 REGCLS_MULTIPLEUSE 下创建 COM 对象时,是否会以不同的方式处理,从而导致观察到的行为?为什么我得到多个进程? (澄清一下,我确实希望我的 COM 服务器作为 Windows 服务运行,但使用它的客户端确实作为 Windows 服务运行。)

此外,将客户端作为本地系统或网络服务运行,REGCLS_MULTIPLEUSE 按我的预期工作:只启动一个 COM 服务器 EXE 进程。当 COM 客户端是在用户帐户下运行的 Windows 服务时,会启动多个进程。

【问题讨论】:

【参考方案1】:

进程外激活请求的路由由向 COM 服务控制管理器注册类对象控制。如果 SCM 有一个可用的已注册类对象,则该对象将用于为请求提供服务。如果没有,它将启动 COM 服务器的一个 exe 进程实例来获取一个。因此,多个激活请求是否路由到单个 COM 服务器 exe 进程至少取决于以下因素(我不确定这是否是完整列表):

COM 服务器在调用 CoRegisterClassObject 向 SCM 注册时指定的激活标志可能会导致未来的激活请求导致启动新的 exe 进程实例,最简单和最常见的情况是使用标志 REGCLS_SINGLEUSE,它允许注册的类对象仅用于单个激活。 根据类的注册方式,来自不同安全上下文的激活请求可能由不同的 COM 服务器 exe 实例提供服务(这似乎不适用于您的场景,因为您的客户端应用程序在相同的安全上下文下运行)。

【讨论】:

您的回答使我调查了 CoRegisterClassObject 参数,但我仍然不理解观察到的行为——我正在使用 REGCLS_MULTIPLEUSE。在上面的问题中查看我的编辑。 @Jim:我现在知识有限,但我有一种预感,COM SCM 维护的类对象表的范围是登录会话,并且 SCM 只会重用同一会话中的类对象。如果您的客户端都是在单独的会话中运行的所有服务,那么即使使用 REGCLS_MULTIPLEUSE 并且使用相同的帐户身份运行,它们也会获得自己的类对象实例(从而获得自己的服务器进程)。无论如何,你可以测试一个假设。 这是有道理的。我会自己再看一点,但我很高兴将其标记为答案。谢谢。

以上是关于来自同一用户帐户的 LocalServer32 EXE 的 COM 激活是不是共享现有进程?的主要内容,如果未能解决你的问题,请参考以下文章

如何在使用 Spring Boot 的 JWT 令牌时禁用同一用户帐户的多个登录

FireBaseUI Auth - 如何知道帐户是来自新注册用户还是现有用户?

为啥 IIS 似乎将来自 AppPool 的一个请求的 WindowsIdentity 提升到我的用户帐户?

如何阻止用户从同一帐户但不同的选项卡登录两次

在同一个 AD 用户帐户下运行的不同应用程序池 - 如何在任务管理器中区分?

如何使用 win32 api 获取域用户帐户列表?