如何强制进程外 COM 服务器进行进程隔离?
我正在编写托管代码,该代码必须与在进程外运行的供应商的 COM 自动化服务器进行交互。 我发现如果有多个客户端连接到该服务器,该服务器就会变得不稳定。 例如,如果进程 A 中的托管代码和进程 B 中的托管代码都连接到该 COM 服务器,则将为 COM 服务器启动单个进程,并且其行为不太可靠。 我希望有一种方法可以为每个客户端-服务器连接强制执行单独的进程。 理想情况下,我希望最终得到:
托管进程 A 在进程 C1
中与 COM 服务器通信 托管进程 B 在进程 C2 中与 COM 服务器通信
我想到的一个想法是,如果我使用不同的安全身份运行进程 A 和进程 B,则可能会导致 COM 基础结构创建单独的服务器进程。 然而,我宁愿不走那条路。 托管进程 A 和托管进程 B 实际上是 Windows 服务。 我使用身份本地系统运行它们(因为我需要它们能够与桌面交互,并且对于不作为本地系统运行的服务,您无法选中服务小程序上的“与桌面交互”框系统)。 我需要与桌面交互的原因是这个 COM 服务器偶尔会在屏幕上弹出一个对话框,如果服务本身无法与桌面交互,那么 COM 服务器将无法显示该对话框(我相信这是显示在隐藏的 WinStation 上)。
I'm writing managed code that has to interact with a vendor's COM automation server that runs out of process. I have found that this server becomes unstable if more than one client connects to it. For example, if I have managed code in process A and managed code in process B both connecting to this COM server, a single process will be spun up for the COM server and it's behavior is less than reliable. I'm hoping there's a way to force a separate process for each client - server connection. Ideally, I'd like to end up with:
Managed Process A talking to COM Server in process C1
Managed Process B talking to COM Server in process C2
One thought that came to mind was that if I ran process A and process B with different security identities, that that might cause the COM infrastructure to create separate server processes. I'd rather not go down that road, however. Managed Process A and Managed Process B are actually Windows Services. And I'm running them with identity Local System (because I need them to be able to interact with the desktop, and you can't check the "Interact with Desktop" box on the services applet for services that don't run as Local System). And the reason I need to interact with desktop is that this COM server occasionally throws up a dialog box on the screen and if the service itself cannot interact with the desktop then the COM server is spawns can't display the dialog (I believe it is displayed on a hidden WinStation).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
将组件注册到 COM+,这会为您设置一个隔离层。
使用:控制面板->管理工具
或者cmd/执行DCOMCNFG
组件服务->计算机->我的电脑->COM+应用程序,右键单击,新建应用程序,下一步,创建一个空应用程序,输入应用程序名称“COM+ your.dll”,下一步,选择本地服务,下一步,下一步,下一步,完成。
在创建的新项目中,展开组件,右键单击新组件,下一步,选择安装新组件,选择您的组件。
单击组件属性,选项卡身份,选择系统帐户。
有关调用中的错误,请参阅之后的事件。
Place the component registered at COM+, this put an isolation layer at your.
Use : Control Panel->Administrative Tools
or cmd/execute DCOMCNFG
Component Services->Computers->My Computer->COM+ Application, right click, new application, next, Create an empty application, enter app name “COM+ your.dll”, next, select Local Service, next, next, next, finish.
In new item made, expand, at Components, right click, new component, next, select Install new component, select your component.
Click Component properties, tab Identity, select System Account.
For errors in calls see Event after.
我已经有一段时间没有做过这件事了,所以我的记忆已经模糊了。
如果您使用DCOM配置工具将OOP COM服务器配置为DCOM服务器,我相信您可以指定隔离级别。 几年前,我使用了一个非线程安全的进程内 DLL,需要从 IIS 以线程安全的方式访问它,它很有魅力。
请让我知道这对你有没有用 :)
It's been a while since I've done this, so my memory is hazy.
If you configure the OOP COM server as a DCOM server using the DCOM config tool, I believe you can specify the isolation level. I did this years ago with a non-threadsafe in-process DLL that needed to be accessed in a threadsafe fashion from IIS and it worked a charm.
Let me know if it works for you :)
最好的选择是让供应商修复该组件。 毕竟,如果它无法处理多个客户端,则可能潜伏着其他错误。 如果你做不到这一点,还有其他一些事情可以尝试。
对于进程内 COM 对象,我有机会手动加载 dll 并直接访问接口,而无需通过 COM。
我自己还没有使用进程外 COM 完成此操作,但您可以尝试一些方法。 最终,库只是一个接收调用函数的消息的进程。
您也许可以为每个客户端手动启动进程的新副本,然后向其发送消息。 您可能会遇到一些问题。 例如,该进程可能会检查它是否已经在运行并拒绝启动或以其他方式不满意。
如果您知道客户端数量的上限,则可以考虑的另一种方法是制作原始 .exe 文件的多个副本,然后使用二进制修补程序(类似于 Microsoft Research 的 detours 库)来覆盖 COM注册函数并将每个副本注册为单独的 COM 对象。
Your best bet would be to get the vendor to fix the component. After all, if it won't handle multiple clients, there could be other bugs lurking. If you can't do this, there are some other things to try.
With in-process COM objects I've had occassion to manually load the dll and access the interfaces directly without going through COM.
I haven't done this myself with out-of-process COM, but there are some things you could try. Ultimately the library is just a process sitting there receiving messages which invoke functions.
You might be able to manually start the a new copy of the process for each client and then send it messages. You may run into some hiccups with this. For example, the process may check to see if it's already running and refuse to start or otherwise be unhappy.
If you have a known upper limit on the number of clients, another approach you could consider would be to make multiple copies of the original .exe file and then use binary patching (something similar to the detours library from Microsoft Research) to override the COM registration functions and register each copy as a separate COM object.