1

Тема: WSH: управление запущенным скриптом.

Управление работой запущенного скрипта.

Option Explicit

Dim strAction
Dim boolTerminateRequest
Dim intIntervalRequest

Dim strComputer

Dim objSWbemServices
Dim objSWbemSink_Win32_Process
Dim strPartWQL4ThisScript

Dim objNamedArgs

Set objNamedArgs = WScript.Arguments.Named

If objNamedArgs.Exists("Start") Then
    strAction = "Start"
Else
    If objNamedArgs.Exists("Stop") Then
        strAction = "Stop"
    Else
        WScript.Echo _
            "Использование:" & vbCrLf & _
            "" & vbCrLf & _
            WScript.ScriptName & " </Start | /Stop>" & vbCrLf & _
            "" & vbCrLf & _
            "/Start : Запуск скрипта на исполнение." & vbCrLf & _
            "/Stop  : Останов запущенного скрипта."
        Set objNamedArgs = Nothing
        
        WScript.Quit 254
    End If
End If

strComputer = "."
strPartWQL4ThisScript = _
    "SELECT Name, CommandLine FROM Win32_Process WHERE " & _
    "Name LIKE '%[cw]script.exe' AND " & _
    "CommandLine LIKE '%[cw]script%" & WScript.ScriptName

intIntervalRequest = 1
Set objSWbemServices = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

Select Case strAction
    Case "Start"
        WScript.Sleep 500
        
        If objSWbemServices.ExecQuery(strPartWQL4ThisScript & "% /start%'").Count = 1 Then
            ' Здесь основная часть скрипта для исполнения
            '--------------------------------------------------------------------------
            WScript.Echo "Запускаем скрипт..."
            
            boolTerminateRequest = False
            
            Set objSWbemSink_Win32_Process = WScript.CreateObject("WbemScripting.SWbemSink", "SWbemSink_Win32_Process_")
            
            objSWbemServices.ExecNotificationQueryAsync objSWbemSink_Win32_Process, _
                "SELECT * FROM __InstanceCreationEvent WITHIN " & CStr(intIntervalRequest) & " WHERE " & _
                "TargetInstance ISA 'Win32_Process' AND " & _
                "TargetInstance.Name LIKE '[cw]script.exe' AND " & _
                "TargetInstance.CommandLine LIKE '%[cw]script%" & WScript.ScriptName & "% /stop%'"
                
            Do
                ' Делаем какую-либо периодическую работу.
                ' Например, такую высокоинтеллектуальную, как вывод текущего времени
                ' плюс пауза для имитации многотрудной деятельности скрипта, :)
                WScript.Echo Time
                WScript.Sleep 10 * 1000
            Loop Until boolTerminateRequest
            
            WScript.Echo "Завершение работы скрипта..."
            
            objSWbemSink_Win32_Process.Cancel
            Set objSWbemSink_Win32_Process = Nothing
            Set objSWbemServices = Nothing
            '--------------------------------------------------------------------------
        Else
            Set objSWbemServices = Nothing
            QuitInfo "Скрипт уже запущен.", 1, 5
        End If
    Case "Stop"
        If objSWbemServices.ExecQuery(strPartWQL4ThisScript & "% /start%'").Count = 1 Then
            ' Здесь основная часть скрипта для завершения
            '--------------------------------------------------------------------------
            WScript.Echo "Найден запущенный экземпляр скрипта."
            WScript.Echo "Делаем паузу в " & CStr(intIntervalRequest * 2) & " секунд, чтобы он успел перехватить событие."
            
            WScript.Sleep intIntervalRequest * 1000 * 2
            '--------------------------------------------------------------------------
        Else
            Set objSWbemServices = Nothing
            QuitInfo "Не найдено запущенных экземпляров скрипта.", 1, 0
        End If
End Select

WScript.Quit 0
'==========================================================================

'==========================================================================
Sub SWbemSink_Win32_Process_OnObjectReady(objLatestEvent, objSWbemAsyncContext)
    If InStr(LCase(objLatestEvent.TargetInstance.CommandLine), "/stop") <> 0 Then
        WScript.Echo "Получено событие на останов скрипта."
        WScript.Echo "Исполнение скрипта будет завершено в конце текущего прохода цикла."
        
        boolTerminateRequest = True
    End If
End Sub
'==========================================================================

Сохраните скрипт на жёсткий диск. Запустите два командных процессора cmd.exe. В одном окне запустите скрипт на исполнение:

cscript.exe //nologo <путь\имя скрипта.vbs> /Start

В другом окне запустите его же для остановки первого экземпляра запущенного скрипта:

cscript.exe //nologo <путь\имя скрипта.vbs> /Stop

Способ основан на появившемся в WMI, начиная с Windows XP (и выше), свойстве CommandLine класса Win32_Process. При запуске скрипт подписывается на отслеживание событий создания процессов с именем cscript.exe/wscript.exe, содержащих в командной строке текст «cscript»/«wscript», имя файла скрипта, ключ «/Stop».