Можно ли отслеживать процессы, которые запускает другой процесс через WMI?
Вопрос
У меня есть установочный исполняемый файл, который мне нужно установить.Когда я запускаю его, он запускает msi для выполнения фактической установки, а затем немедленно умирает.Побочным эффектом этого является возврат управления обратно на любую консоль, с которой вы его вызываете, до завершения установки.В зависимости от того, на какой машине я его запускаю, это может занять от трех до десяти минут, поэтому перевод вызывающего скрипта в спящий режим нежелателен.Я бы запустил msi напрямую, но он жалуется на отсутствие компонентов.
У меня есть скрипт WSH, который использует WMI для запуска процесса, а затем следит, пока его pid больше не будет запущен.Есть ли какой-нибудь способ определить pid MSI, который выполняется исходным исполняемым файлом, а затем следить за завершением этого pid с помощью WMI?Связана ли вообще информация о процессе запуска с каким-либо процессом?
Решение
Поможет ли выполнение WMI-поиска процессов, которые имеют начальную настройку в качестве родительского процесса?Например, если я запускаю MSI из командной строки с идентификатором процесса 4000, я могу выполнить следующую командную строку, чтобы найти информацию о процессе msiexec:
c:\>wmic PROCESS WHERE ParentProcessId=4000 GET CommandLine, ProcessId
CommandLine ProcessId
"C:\Windows\System32\msiexec.exe" /i "C:\blahblahblah.msi" 2752
Это может быть одним из способов найти нужную вам информацию.Вот демонстрация поиска этой информации в vbs:
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set colProcesses = objWMIService.ExecQuery("select * from Win32_Process where ParentProcessId = 4000")
For Each objProcess in colProcesses
Wscript.Echo "Process ID: " & objProcess.ProcessId
Next
Я надеюсь, что это поможет.
Другие советы
Если вы используете язык .NET (вы можете сделать это в Win32, но гораздо проще в .NET), вы можете перечислить все процессы в системе (после вашего первоначального вызова Setup.exe завершается) и найдите все процессы, PID родительского элемента которых равен PID Setup.exe - и затем отслеживайте все эти процессы.Когда они завершатся - настройка завершена.Убедитесь, что они также больше не порождают дочерних процессов.
Это должно сработать.
$p1 = [diagnostics.process]::start($pathToExecutable) # this way we know the PID of the initial exe
$p2 = get-wmiobject win32_process -filter "ParentProcessId = $($p1.Id)" # using Jim Olsen's tip
(get-process -id $p2.ProcessId).WaitForExit() # voila--no messy sleeping
К сожалению, у объекта .NET нет свойства ParentProcessId, а у объекта WMI нет метода WaitForExit(), поэтому нам приходится переходить туда и обратно.
Спасибо Джеффри Сноверу (всегда) за эта статья.