【问题标题】:How do I identify if a client of a Microsoft COM-Server is out-of-process or within the process?如何识别 Microsoft COM-Server 的客户端是在进程外还是在进程内?
【发布时间】:2016-01-19 07:52:28
【问题描述】:

我对 Microsoft COM 技术不是很熟悉。简而言之,我有一个在可执行文件foo.exe 中实现的Microsoft Out-of-process COM Server。环境是 C++ 和 Microsoft 基础类框架 (MFC)。

有一个客户端bar.exe 通过Microsoft COM 技术使用foo.exe 中的功能。在 foo.exe 中涉及一些动态链接库,它们也使用 COM 服务器 foo.exe 提供的功能(例如 fooBar.dll)。

到目前为止一切顺利。我正在寻找一种方法来确定 COM 服务器 foo.exe 的客户端是否在其他进程中,甚至与 foo.exe 位于同一进程中,例如上例中的 fooBar.dll。有没有人知道这样的方法?

编辑: 换句话说:显然 COM 服务器 foo.exe 可以充当进程内或进程外 COM 服务器。加上 Hans Passant 的评论和提议通过GetModuleHandle 解决调用 DLL 的 Joe Willcoxson 的回答,以确定 COM 服务器当前是否充当进程内服务器,以防我得到句柄并进入当我没有将句柄作为进程外服务器时的情况。因此,当 COM 服务器知道众所周知的 DLL 在同一进程中使用该服务器的功能时,我们可以说 COM 服务器此时充当进程内服务器,而在其他情况下充当进程外服务器。 -进程服务器。我是否误解了某些事情,或者这些考虑是否正确?

目前我的调查暂且不提,所以我希望社区中有一位了解手推车如何运行的 Microsoft COM 专家。

非常感谢您的帮助!

【问题讨论】:

  • 拥有一个有效的接口指针,你不应该打扰谁来实现它,尤其是在进程外服务器的情况下,你不直接与服务器通信,而是与代理通信。也就是说,没有标准方法,但您可以查询一些已知无法跨进程边界编组的接口,如果您得到指针,您就知道服务器在进程中。
  • 这个问题没有意义,进程内/进程外的术语仅适用于服务器。客户端代码始终存在于自己的进程中。
  • 你是说服务器(而不是客户端)加载一个 DLL,然后转身并调用同一服务器上的方法?无论如何,你为什么关心谁在调用这个方法?您要解决什么实际问题?
  • @Hans Passant:我已经具体化了这个问题:我仍在寻找一种方法来确定 COM 服务器 foo.exe 的客户端是否在另一个进程中,甚至在同一个进程中进程为 foo.exe,如上例中的 fooBar.dll。
  • @Igor Tandetnik:是的,服务器加载了一个 DLL,然后转身并调用同一服务器上的方法。我试图解决的问题是,当客户端在其他进程中运行时忽略弹出的消息框。如果客户端在与 foo.exe 相同的进程中运行,我希望允许弹出消息框。

标签: com interop com-interop com-server


【解决方案1】:

如果你已经有了一个 COM 指针,我不确定你会怎么做。但是,创建对象时有一种方法。

CoCreateInstance() 函数接受标志 CLSCTX_INPROC_SERVER, CLSCTX_INPROC_HANDLER, CLSCTX_LOCAL_SERVER, CLSCTX_REMOTE_SERVER

通常,当您使用 ATL 之类的东西时,默认参数是组合标志,它只返回可用的任何内容。您可以单独尝试这些标志,然后查看是否使用特定标志创建了对象。

如果对象实际上是 OLE 对象/服务器,我应该补充一点。如果是这种情况,那么您可以查询 IViewObject。如果它在进程中,它将没有该接口。如果它不在进程中,那么它就会有接口。

另外一件事,如果对象实现了IRunnableObject,而你没有做任何事情来专门将它置于运行状态,那么进程内对象很可能处于运行状态,而进程外对象则不会处于运行状态。

一个非常简单的 hack 可能是使用 DLL 的名称调用 GetModuleHandle()。如果它返回一个句柄,那么它是在进程中。这不是通用的解决方案,它需要您事先知道 DLL 的名称。

【讨论】:

  • 感谢您的回答。你让我进一步考虑我附加到问题中的内容。请参阅编辑部分。
【解决方案2】:

在 COM 服务器 foo.exe 中,您可以执行以下操作。

CTheApp::InitInstance()
{
    [...]
    bool runAsOutOfProcessServer = false;
    CCommandLineInfo commandInfo;
    ParseCommandLine(commandInfo);
    if(commandInfo.m_bRunEmbedded || commandInfo.m_bRunAutomated)
    { 
           runAsOutOfProcessServer = true;
    }
    [...]

    if(runAsOUtOfProcessServer)
       AfxMessageBox("Out of Process Invocation");
}

显然CCommandLineInfo 中有两个成员,这表明该进程作为 OLE 自动化服务器启动或启动以编辑嵌入的 OLE 项。使用ParseCommandLine,您可以通过引用局部变量commandInfo 来获取信息。然后可以查看m_bRunEmbeddedm_bRunAutomated成员是否设置,判断foo.exe内的COM Server是否启动。然后最后只有局部变量runAsOutOfProcessServer为真时才能弹出消息框。

【讨论】:

    猜你喜欢
    • 2018-11-06
    • 2023-04-10
    • 2011-08-13
    • 2012-06-01
    • 1970-01-01
    • 2018-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多