6

我有一个需要密切关注的进程外 COM 服务器。该服务器作为服务运行,并且在内部是单例的。为简单起见,我称他为 BossCom。

我有另一个进程外 COM 服务器,它是一个工作者。为了系统的稳定性,它是一个一次性服务器(这意味着如果你创建 2 个 WorkerCom,则有 2 个 WorkerCom.exe 正在运行)。为简单起见,我称他为 WorkerCom。

WorkerCom 可以由任何东西启动,即使有人通过带有正确命令行参数的命令行运行它,它也可以由它自己启动。

BossCom 的总体目标是了解周围的 WorkerCom,知道他们在做什么,并能够给他们下达命令(暂停、停止、加速等)。

我最初的想法是,每当 WorkerCom 启动时,他都会 CoCreateInstance 一个 BossCom 并调用 BossCom->RegisterWorker(IUnknown me)。然后当 WorkerCom 即将关闭时,他会调用 BossCom->UnregisterWorker(IUnknown me)。BossCom 可以为 IWorkerCom 查询接口 IUnknown 并能够发出命令。

如果所有这些 com 对象都在同一个进程中,那将非常有用,但事实并非如此。我考虑过使用 GlobalInterfaceTable,但它只是在单个进程的意义上是全局的。

我花了几天时间研究这个并且不知所措。也许我是隧道式的。

如何将 com 对象的引用从 Worker 编组到 Boss?

哦,而且,不管怎样,BossCom 是用 C# 编写的,而 WorkerCom 是用 ATL C++ 编写的,但我会采用用 VB、Scala、Lisp 或任何东西编写的解决方案。我想我可以翻译核心思想。:-)

4

5 回答 5

2

您应该看一下Monikers,它们用于识别 COM 对象实例,即使在不同的机器上也是如此。

于 2011-01-14T14:47:57.320 回答
2

根据评论,这确实是开箱即用的。还有一个额外的细节使它起作用。

最初,当我查看处理复制接口的 C# 接口时,参数类型是 IntPtr。嗯,一个 IntPtr 只是一个 long 所以它按原样传输值,因此不起作用。

关键是在参数上设置 MarshalAs 属性。所以我的 RegisterWorker 方法如下所示:

    public void RegisterWorker(
        [In, MarshalAs(UnmanagedType.IUnknown)] object ptr
        )
    {
        IWorkerCom worker = (IWorkerCom) ptr;
        Workers.Add(worker);
    }

太神奇了。

于 2011-01-14T18:07:26.683 回答
1

我最近不得不做类似的事情,发现使用共享内存对我来说效果很好。BossCom 可以创建和拥有共享内存,工人可以通过在共享内存中创建条目来注册。这是我正在谈论的内容的MSDN 链接。请记住使用互斥锁来同步对内存的访问...

于 2011-01-14T14:26:15.127 回答
1

您在 C# 中创建可编组接口的能力有点受限。没有简单的方法来设置代理。ATL中没有这个问题,在IDL中声明一个回调接口。并通过 RegisterWorker() 调用传递一个实例指针。服务器应该存储它,直到它收到取消注册调用。使用该回调接口生成通知。

于 2011-01-14T14:46:19.870 回答
1

您还应该查看 ROT(运行对象表),它可能是解决此问题的不同方法。

http://msdn.microsoft.com/en-us/library/windows/desktop/ms695276(v=vs.85).aspx

http://www.codeproject.com/KB/COM/ROTStuff.aspx

于 2011-10-28T16:38:06.260 回答