How to determine the association between a VB6 app and an exe instanced with CreateObject()

亡梦爱人 提交于 2019-12-11 03:23:49

问题


We need to figure out how a service can peek at a running VB6 app and/or its DCOM spawned exe and figure out which VB6 app goes with which DCOM exe. The VB6 app and the spawned exe are both on the same server.

We have a VB6 app that spawns an instance of Bartender (from Seagull Scientific) by way of a CreateObject() call. On a given server, we may have ten or twenty instances of our app, each represents a handheld RF gun client in a warehouse. 95% or more of these VB6 apps will have their own Bartender.

Due to circumstances beyond our control, randomly, one of our VB6 instances will be killed, just as if you killed it using Task Manager. This leaves it's Bartender still alive and consuming resources. After fifty or so have been killed over the course of a few hours or days, these orphaned Bartenders become enough of a resource hog to bring the server to its knees.

We are trying to develop a watcher service to detect which of the Bartenders are still connected, so this new service can kill the orphaned Bartenders. We are trying to accomplish this without changing our VB6 app, but we will modify our app if we have to.


回答1:


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.




回答2:


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).




回答3:


What we have decided to do is to have the client write a hint file each time the Client creates a Bartender. The client writes a tiny XML file in a common folder that says an XML equivalent of "I am PID number n. Between time x and time y, I created a Bartender." The times x and y are timestamps obtained immediately before and after the CreateObject call. We will have a monitor service that watches for new Clients, new Bartenders and hint files. By watching all these, we think we can create small groups or associations of clients and their associated bartenders. In any given group, when all the clients go away, any remaining Bartenders that were in that group can be KILLED!



来源:https://stackoverflow.com/questions/4430795/how-to-determine-the-association-between-a-vb6-app-and-an-exe-instanced-with-cre

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!