これを行うのは、不可能ではないにしても難しいでしょう。プロセス外の COM コンポーネント (つまり、ActiveX EXE) は、 CreateObjectを呼び出したプロセスではなく、常に COM サービス コントロール マネージャーによって開始されます。これが、ActiveX EXE の親プロセスがsvchost.exeである理由です。
したがって、 CreateObjectを呼び出すプロセスと作成されるプロセスの間に直接の親子関係はありません。2 つのプロセス間でメソッド呼び出しを実際にやり取りするリモート プロシージャ コール (RPC) 層のみが、関連するプロセスの ID を認識しますが、RPC メカニズムは COM サブシステムに対して透過的になるように特別に設計されており、私が知っているこの情報にアクセスする簡単な方法。
ただし、VB6 アプリケーションを変更する場合は、孤立したプロセスの問題を処理するかなりハックな方法があります。
監視サービスに、実行中のすべての Bartender EXE を定期的に終了させます (1 日に 1 回、またはサーバーの速度が低下しすぎるのを防ぐために頻繁に行う必要があります)。
Bartender 機能のラッパー DLL を作成し、生の Bartender オブジェクトを直接インスタンス化する代わりに、VB6 クラスでこのラッパー ライブラリを使用します。このライブラリには、Bartender オブジェクトを作成し、このオブジェクトに委譲するメソッドを持つラッパー クラスが含まれます。各ラッパー メソッドは、エラー 462 (「リモート サーバー マシンが存在しないか、使用できません」) をキャッチし、これが発生した場合は Bartender オブジェクトを再作成してから、メソッドを再試行する必要があります。
例 (私は実際に Bartender のドキュメントを見ていないので、これは単にアイデアを示しているだけです):
'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
ここでの考え方は、どの Bartender プロセスがまだ VB6 アプリケーションのインスタンスに接続されているかを確実に判断できないため、実行中のすべての Bartender プロセスを定期的に強制終了しても、アプリケーションは引き続き適切に実行できる (ほとんどの場合) ということです。これは、VB6 アプリケーションの実行中のインスタンスで使用されていた Bartender EXE を強制終了すると、アプリケーションは新しい Bartender インスタンスを作成し、通常どおり実行し続けるためです。
このソリューションは絶対に確実というわけではなく、多くのメソッドを使用している場合や、作成した Bartender インスタンスに新しいインスタンスの作成時に失われる可能性のある重要な内部状態がある場合、実装が難しい場合があります。
結局のところ、関連するすべてのアプリケーションを制御しないと、孤立した ActiveX EXE を検出するきれいな方法はありません (ActiveX EXE を制御する場合の一般的な解決策の 1 つは、ActiveX EXE を発生させることです)。 1 秒ごとにByRefパラメータを持つイベントを実行し、クライアントがパラメータの値を変更しない場合はイベント自体をシャットダウンします)。