1

Тема: VBS: Ожидание события с отсчетом времени

Здравствуйте, уважаемые коллеги.
Хочу поделиться реализацией ожидания события используя синхронный и асинхронный режим подписки на события.
Решал с целью запуска процесса на удаленной машине и последующего ожидания завершения его выполнения.
Если с ожиданием события "до упора" все более-менее просто:


Const Process = "notepad.exe"

Set objWMI = GetObject("winmgmts:\\.\Root\CIMV2")

ret = objWMI.Get("Win32_Process").Create(Process, , , intProcessID)
If ret <> 0 Then
	MsgBox "Не удалось создать процесс " & Process
	WScript.Quit
End If
	
Call ProcessFinished(intProcessID)

MsgBox "Процесс " & Process & " завершен"

'функция ожидания завершения процесса "до упора"
Function ProcessFinished(intProcessID)
	Dim colProcesses, objProcess	
	Set colProcesses = objWMI.ExecNotificationQuery( _
			"SELECT * FROM __InstanceDeletionEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_Process'" & _
			" AND TargetInstance.ProcessID = '" & intProcessID & "'") 	
	Do
		Set objProcess = colProcesses.NextEvent		
			ProcessFinished = True
			Exit Function		
	Loop	
End Function

То с ожиданием, например, в течение определенного количества времени (я бы предпочел именно этот вариант), на мой взгляд, поинтереснее:


Const Process = "notepad.exe"

Set objWMI = GetObject("winmgmts:\\.\Root\CIMV2")

ret = objWMI.Get("Win32_Process").Create(Process, , , intProcessID)
If ret <> 0 Then
	MsgBox "Не удалось создать процесс " & Process
	WScript.Quit
End If

Dim objSink, bFinish

If ProcessFinishedA(intProcessID, 5) Then
	MsgBox "Процесс " & Process & " завершен"
Else
	MsgBox "Процесс " & Process & " не завершен"
End If

'функция ожидания завершения процесса в течение определенного количеста секунд
Function ProcessFinishedA(intProcessID, intSec)
	Set objSink = WScript.CreateObject("WbemScripting.SWbemSink","SINK_")
	objWMI.ExecNotificationQueryAsync objSink, _
			"SELECT * FROM __InstanceDeletionEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_Process'" & _
			" AND TargetInstance.ProcessID = '" & intProcessID & "'"	
	Do 
		If bFinish Then
			ProcessFinishedA = True
			Exit Function
		End If		
		If i = intSec Then Exit Function		
		i = i + 1		
		WScript.Sleep(1000)		
	Loop
End Function

Sub SINK_OnObjectReady(objObject, objAsyncContext)    
	bFinish = True
End Sub

Возможно кому-нибудь пригодится.