Это будет трудно, если не невозможно, сделать. Внешние COM-компоненты (то есть EXE-файлы ActiveX) всегда запускаются диспетчером управления службами COM, а не процессом, который вызывает CreateObject . Вот почему родительский процесс для ActiveX EXE svchost.exe .
Следовательно, между процессом, вызывающим CreateObject , и процессом, который создается, нет прямой связи между родителями и детьми. Только уровень удаленного вызова процедур (RPC), который фактически передает вызовы методов назад и вперед между двумя процессами, знает идентификаторы вовлеченных процессов, но механизм RPC специально разработан, чтобы быть прозрачным для подсистемы COM, и нет простой способ получить доступ к информации, которую я знаю.
Однако, есть довольно хакерский способ справиться с проблемой потерянного процесса, если вы хотите изменить приложение VB6:
Служба монитора периодически прерывает все , на которых запущены Bartender EXE (один раз в день или, как это часто бывает, необходимо для предотвращения слишком сильного замедления работы сервера).
Напишите DLL-оболочку для функциональности Bartender, и пусть ваш класс VB6 использует эту библиотеку-оболочку вместо непосредственного создания необработанных объектов Bartender. Эта библиотека будет содержать класс-оболочку, которая создает объект 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, и ваше приложение по-прежнему сможет работать должным образом. (в большинстве случаев), потому что, если вы убьете EXE-файл Bartender, который использовался запущенным экземпляром вашего приложения VB6, ваше приложение создаст новый экземпляр Bartender и продолжит работать в обычном режиме.
Это решение определенно не защищено от ошибок, и его может быть сложно реализовать, если вы используете много методов или у созданного вами экземпляра Bartender есть важное внутреннее состояние, которое может быть потеряно при создании нового экземпляра.
Когда дело доходит до этого, нет чистого способа обнаружить осиротевшие EXE-файлы ActiveX, если вы не управляете всеми участвующими приложениями (одно общее решение, когда вы делаете , контролируете ActiveX EXE должен заставить ActiveX EXE вызывать событие с параметром ByRef каждую секунду или около того и отключать его, если клиент не изменяет значение параметра).