2

我们需要弄清楚服务如何查看正在运行的 VB6 应用程序和/或其 DCOM 生成的 exe,并弄清楚哪个 VB6 应用程序与哪个 DCOM exe 一起使用。VB6 应用程序和生成的 exe 都在同一台服务器上。

我们有一个 VB6 应用程序,它通过 CreateObject() 调用生成一个 Bartender 实例(来自 Seagull Scientific)。在给定的服务器上,我们可能有十个或二十个应用程序实例,每个实例代表仓库中的手持式射频枪客户端。这些 VB6 应用程序中的 95% 或更多都将拥有自己的调酒师。

由于我们无法控制的情况,我们的一个 VB6 实例将被随机杀死,就像您使用任务管理器杀死它一样。这使得它的调酒师仍然活着并消耗资源。在几个小时或几天的时间里杀死了大约 50 人后,这些孤儿调酒师就成为了一个足以让服务器屈服的资源猪。

我们正在尝试开发一个观察者服务来检测哪些调酒师仍然连接,所以这个新服务可以杀死孤立的调酒师。我们试图在不更改我们的 VB6 应用程序的情况下完成此操作,但如果需要,我们将修改我们的应用程序。

4

3 回答 3

0

This is going to be hard, if not impossible, to do. Out-of-process COM components (i.e. ActiveX EXE's) are always started by the COM Service Control Manager, not by the process that called CreateObject. This is why the parent process for the ActiveX EXE is svchost.exe.

Therefore, there is no direct parent-child relationship between the process that calls CreateObject and the process that gets created. Only the remote procedure call (RPC) layer that actually passes method calls back and forth between the two processes knows the identities of the processes involved, but the RPC mechanism is specifically designed to be transparent to the COM subsystem, and there isn't an easy way to get access to this information that I know of.

However, there is a pretty hackish way to handle the orphaned process problem if you are willing to change the VB6 application:

  1. Have your monitor service periodically terminate all running Bartender EXE's (once a day or however often is necessary to prevent the server from slowing down too much).

  2. Write a wrapper DLL for the Bartender functionality, and have your VB6 class use this wrapper library instead of directly instantiating raw Bartender objects. This library would contain a wrapper class that creates a Bartender object, and that has methods that delegate to this object. Each wrapper method should catch error 462 ("The remote server machine does not exist or is unavailable"), recreate the Bartender object if this occurs, and then retry the method.

For example (I haven't actually looked at the Bartender documentation, so this is just demonstrating the idea):

'BartenderWrapper.cls

Private m_bartender As Object

Private Sub Class_Initialize()
   Set m_bartender = CreateObject("Bartender.Application")    
End Sub

Public Sub PrintLabel(Byval sLabelData As String)

    On Error Goto ErrorHandler

    m_bartender.PrintLabel sLabelData

    Exit Sub

ErrorHandler:

    If IsRpcError(Err) Then
       Set m_bartender = CreateObject("Bartender.Application")
       Resume
    End If

    Err.Raise Err.Number, Err.Source, Err.Description

End Sub

Private Function IsRpcError(Byval e As ErrObject) As Boolean
    IsRpcError = (e.Number = 462)
End Function

The idea here is that since you can't reliably determine which Bartender processes are still connected to an instance of your VB6 application, you can kill all of the running Bartender processes periodically, and your application will still be able to run properly (in most cases), because if you kill a Bartender EXE that was being used by a running instance of your VB6 application, your application will create a new Bartender instance and continue running normally.

This solution definitely isn't fool-proof, and may be hard to implement if you are using a lot of methods or the Bartender instance you create has important internal state that could be lost when creating a new instance.

When it comes down to it, there isn't a clean way to detect orphaned ActiveX EXE's if you don't control all of the applications that are involved (one common solution when you do control the ActiveX EXE is to have the ActiveX EXE raise an event with a ByRef parameter every second or so, and have it shut itself down if the client doesn't change the value of the parameter).

于 2010-12-20T04:28:02.100 回答
0

I think this routine, aptly named Who's Your Daddy, might be of use to you. It figures out who spawned the process. It probably won't solve your entire problem, but it's a start.

于 2010-12-14T02:25:42.330 回答
0

我们决定做的是让客户端在每次客户端创建调酒师时编写一个提示文件。客户端在一个公用文件夹中写入一个很小的 ​​XML 文件,该文件表示“我是 PID 号 n。在时间 x 和时间 y 之间,我创建了一个调酒师”。时间 x 和 y 是在 CreateObject 调用之前和之后立即获得的时间戳。我们将有一个监控服务来监视新客户、新调酒师和提示文件。通过观察所有这些,我们认为我们可以创建客户及其相关调酒师的小组或协会。在任何给定的组中,当所有客户离开时,该组中的任何剩余调酒师都可以被杀死!

于 2011-03-16T16:21:45.833 回答