vbscript 使用 PID WMIService 终止进程
vbscript kill a process with a PID WMIService
我有一个文件夹,里面装满了几个 vbscript(比如 10 个),这些 vbscript 必须按顺序 运行,而不是 运行 通过单击每个 vbscript,我想自动执行此过程。下面是我的 master.vbs 脚本,其中 运行 将那个文件夹中的每个 vbscript 一个接一个地添加。
strComputer = "."
Set objFSO = CreateObject("Scripting.FileSystemObject")
currentdirectory = objFSO.GetAbsolutePathName(".")
filedirectory = currentdirectory
Set objFolder = objFSO.GetFolder(filedirectory)
Dim filestring
Set colFiles = objFolder.Files
For Each objFile in colFiles
'Wscript.Echo objFile.Name
filestring = filestring & objFile.Name & ","
Next
'filestring = filestring.Trim().Substring(0, filestring.Length - 1)
filestring = Left(filestring,Len(filestring)-1)
Dim files
files = Split(filestring,",")
For Each f In files
'WScript.Echo f
chk = Split(f,".")
If chk(UBound(chk)) = "vbs" then
pat = filedirectory & "\" & f
Set objWMIService = GetObject("winmgmts:\" & strComputer & "\root\cimv2:Win32_Process")
proc = "cmd.exe /c"& Chr(32) &"cscript.exe " & Chr(32) & chr(34) & pat & Chr(34)
objWMIService.Create proc , null, null, intProcessID
Set objWMIService = GetObject("winmgmts:\" & strComputer & "\root\cimv2")
Set colMonitoredProcesses = objWMIService.ExecNotificationQuery _
("Select * From __InstanceDeletionEvent Within 1 Where TargetInstance ISA 'Win32_Process'")
Do Until i = 1
Set objLatestProcess = colMonitoredProcesses.NextEvent
If objLatestProcess.TargetInstance.ProcessID = intProcessID Then
i = 1
End If
Loop
'Wscript.Echo "Process has been terminated."
End If
Next
我在这里遇到的问题是脚本 运行 完美地通过了,因为进程名称对于所有脚本 (cscript) 都是相同的 它不会在启动之前等待进程终止另一个 .
我知道我的代码只需要进行细微的调整,但我不确定如何去做。
有人可以指出我在这里做错了什么吗?..
Option Explicit
' Styles for the window of the started process
Const SW_NORMAL = 1
Const SW_HIDE = 0
' Wait or not for the started process to end
Const RUN_WAIT = True
' Access to the shell
Dim shell
Set shell = WScript.CreateObject("WScript.Shell")
Dim oFile
With WScript.CreateObject("Scripting.FileSystemObject")
' Enumerate files in current active directory
For Each oFile In .GetFolder( shell.CurrentDirectory ).Files
' If it is a VBS script
If LCase(.GetExtensionName( oFile.Name )) = "vbs" Then
' But not the current script
If oFile.Path <> WScript.ScriptFullName Then
' Execute it and wait for the process to end
shell.Run "cscript.exe """ & oFile.Path & """", SW_NORMAL, RUN_WAIT
End If
End If
Next
End With
对于 WMI 解决方案,
Option Explicit
' Determine current directory for file retrieval
Dim currentDirectory
currentDirectory = WScript.CreateObject("WScript.Shell").CurrentDirectory
Dim oFile
With WScript.CreateObject("Scripting.FileSystemObject")
' For each file in the current directory
For Each oFile In .GetFolder( currentDirectory ).Files
' If it is a VBS file
If LCase(.GetExtensionName( oFile.Name )) = "vbs" Then
' But not the current script
If oFile.Path <> WScript.ScriptFullName Then
' Execute it via WMI
WMIExecute "cscript.exe """ & oFile.Path & """"
End If
End If
Next
End With
Sub WMIExecute( command )
' Styles for the window of the started process
Const SW_NORMAL = 1
Const SW_HIDE = 0
' Get a reference to WMI
Dim wmi
Set wmi = GetObject("winmgmts:{impersonationLevel=impersonate}!\.\root\cimv2")
' Configure how the process will be started
Dim processConfig
Set processConfig = wmi.Get("Win32_ProcessStartup").SpawnInstance_
processConfig.ShowWindow = SW_NORMAL
' Prepare a monitor to wait for process termination
Dim monitor
Set monitor = wmi.ExecNotificationQuery ( _
"Select * From __InstanceDeletionEvent Within 1 " & _
" Where TargetInstance ISA 'Win32_Process'" _
)
' Start the indicated process
Dim processID, retCode
retCode = wmi.Get("Win32_Process").Create( command, Null, processConfig, processID )
' The process is started if the return code is 0, else there is a error
' see https://msdn.microsoft.com/en-us/library/aa389388%28v=vs.85%29.aspx
If Not retCode = 0 Then
WScript.Echo "ERROR code ["& Hex(retCode) &"] starting ["& command &"]"
Exit Sub
End If
' Wait for process termination, AND, every X seconds (10 in the code) also check
' if the process is still running just in case we miss the deletion event.
Dim oProcess, keepLooping, endTime, colProcesses
endTime = Now
keepLooping = True
Do While keepLooping
' Wait for the next process deletion event
Set oProcess = monitor.NextEvent
' If it is our event, no need to loop any more
If oProcess.TargetInstance.ProcessID = processID Then
keepLooping = False
End If
' If we are still looping, and the timeout has been reached
' check if the process still exists
If keepLooping And (Now >= endTime) Then
Set colProcesses = wmi.ExecQuery ( _
"Select ProcessID from Win32_Process Where ProcessID = " & processID _
)
' If no process meets the condition, leave the loop, else repeat
' this check in X seconds
If colProcesses.Count < 1 Then
keepLooping = False
Else
endTime = DateAdd("s", 10, Now )
End If
End If
Loop
End Sub
我有一个文件夹,里面装满了几个 vbscript(比如 10 个),这些 vbscript 必须按顺序 运行,而不是 运行 通过单击每个 vbscript,我想自动执行此过程。下面是我的 master.vbs 脚本,其中 运行 将那个文件夹中的每个 vbscript 一个接一个地添加。
strComputer = "."
Set objFSO = CreateObject("Scripting.FileSystemObject")
currentdirectory = objFSO.GetAbsolutePathName(".")
filedirectory = currentdirectory
Set objFolder = objFSO.GetFolder(filedirectory)
Dim filestring
Set colFiles = objFolder.Files
For Each objFile in colFiles
'Wscript.Echo objFile.Name
filestring = filestring & objFile.Name & ","
Next
'filestring = filestring.Trim().Substring(0, filestring.Length - 1)
filestring = Left(filestring,Len(filestring)-1)
Dim files
files = Split(filestring,",")
For Each f In files
'WScript.Echo f
chk = Split(f,".")
If chk(UBound(chk)) = "vbs" then
pat = filedirectory & "\" & f
Set objWMIService = GetObject("winmgmts:\" & strComputer & "\root\cimv2:Win32_Process")
proc = "cmd.exe /c"& Chr(32) &"cscript.exe " & Chr(32) & chr(34) & pat & Chr(34)
objWMIService.Create proc , null, null, intProcessID
Set objWMIService = GetObject("winmgmts:\" & strComputer & "\root\cimv2")
Set colMonitoredProcesses = objWMIService.ExecNotificationQuery _
("Select * From __InstanceDeletionEvent Within 1 Where TargetInstance ISA 'Win32_Process'")
Do Until i = 1
Set objLatestProcess = colMonitoredProcesses.NextEvent
If objLatestProcess.TargetInstance.ProcessID = intProcessID Then
i = 1
End If
Loop
'Wscript.Echo "Process has been terminated."
End If
Next
我在这里遇到的问题是脚本 运行 完美地通过了,因为进程名称对于所有脚本 (cscript) 都是相同的 它不会在启动之前等待进程终止另一个 .
我知道我的代码只需要进行细微的调整,但我不确定如何去做。 有人可以指出我在这里做错了什么吗?..
Option Explicit
' Styles for the window of the started process
Const SW_NORMAL = 1
Const SW_HIDE = 0
' Wait or not for the started process to end
Const RUN_WAIT = True
' Access to the shell
Dim shell
Set shell = WScript.CreateObject("WScript.Shell")
Dim oFile
With WScript.CreateObject("Scripting.FileSystemObject")
' Enumerate files in current active directory
For Each oFile In .GetFolder( shell.CurrentDirectory ).Files
' If it is a VBS script
If LCase(.GetExtensionName( oFile.Name )) = "vbs" Then
' But not the current script
If oFile.Path <> WScript.ScriptFullName Then
' Execute it and wait for the process to end
shell.Run "cscript.exe """ & oFile.Path & """", SW_NORMAL, RUN_WAIT
End If
End If
Next
End With
对于 WMI 解决方案,
Option Explicit
' Determine current directory for file retrieval
Dim currentDirectory
currentDirectory = WScript.CreateObject("WScript.Shell").CurrentDirectory
Dim oFile
With WScript.CreateObject("Scripting.FileSystemObject")
' For each file in the current directory
For Each oFile In .GetFolder( currentDirectory ).Files
' If it is a VBS file
If LCase(.GetExtensionName( oFile.Name )) = "vbs" Then
' But not the current script
If oFile.Path <> WScript.ScriptFullName Then
' Execute it via WMI
WMIExecute "cscript.exe """ & oFile.Path & """"
End If
End If
Next
End With
Sub WMIExecute( command )
' Styles for the window of the started process
Const SW_NORMAL = 1
Const SW_HIDE = 0
' Get a reference to WMI
Dim wmi
Set wmi = GetObject("winmgmts:{impersonationLevel=impersonate}!\.\root\cimv2")
' Configure how the process will be started
Dim processConfig
Set processConfig = wmi.Get("Win32_ProcessStartup").SpawnInstance_
processConfig.ShowWindow = SW_NORMAL
' Prepare a monitor to wait for process termination
Dim monitor
Set monitor = wmi.ExecNotificationQuery ( _
"Select * From __InstanceDeletionEvent Within 1 " & _
" Where TargetInstance ISA 'Win32_Process'" _
)
' Start the indicated process
Dim processID, retCode
retCode = wmi.Get("Win32_Process").Create( command, Null, processConfig, processID )
' The process is started if the return code is 0, else there is a error
' see https://msdn.microsoft.com/en-us/library/aa389388%28v=vs.85%29.aspx
If Not retCode = 0 Then
WScript.Echo "ERROR code ["& Hex(retCode) &"] starting ["& command &"]"
Exit Sub
End If
' Wait for process termination, AND, every X seconds (10 in the code) also check
' if the process is still running just in case we miss the deletion event.
Dim oProcess, keepLooping, endTime, colProcesses
endTime = Now
keepLooping = True
Do While keepLooping
' Wait for the next process deletion event
Set oProcess = monitor.NextEvent
' If it is our event, no need to loop any more
If oProcess.TargetInstance.ProcessID = processID Then
keepLooping = False
End If
' If we are still looping, and the timeout has been reached
' check if the process still exists
If keepLooping And (Now >= endTime) Then
Set colProcesses = wmi.ExecQuery ( _
"Select ProcessID from Win32_Process Where ProcessID = " & processID _
)
' If no process meets the condition, leave the loop, else repeat
' this check in X seconds
If colProcesses.Count < 1 Then
keepLooping = False
Else
endTime = DateAdd("s", 10, Now )
End If
End If
Loop
End Sub