Wait for program to complete - vbscript

To monitor the bandwidth usage and not to unnecessarily load programs in the start up,I want to execute the dumeter.exe then firefox.exe.When I shutdown firefox it should kill dumeter.I used the following code to start
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run "c:\progra~1\dumeter\dumeter.exe"
WshShell.Run "c:\progra~1\mozill~1\firefox.exe
Need to run taskkill only when firefox is closed.Tried using a bat file but sometimes the dumeter starts and closes on its own does not wait.
WshShell.Run "taskkill /f /im dumeter.exe"
Set WshShell = Nothing

You can wait for a process to end by subscribing to the appropriate WMI event. Here's an example:
strComputer = "."
Set oWMI = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
''# Create an event query to be notified within 5 seconds when Firefox is closed
Set colEvents = oWMI.ExecNotificationQuery _
("SELECT * FROM __InstanceDeletionEvent WITHIN 5 " _
& "WHERE TargetInstance ISA 'Win32_Process' " _
& "AND TargetInstance.Name = 'firefox.exe'")
''# Wait until Firefox is closed
Set oEvent = colEvents.NextEvent
More info here: How Can I Start a Process and Then Wait For the Process to End Before Terminating the Script?

Option Explicit
Const PROC_NAME = "<Process_You_Want_to_Check>"
Const SLEEP_INTERVAL_MS = 5000 '5 secs
Dim objWMIService
Dim colProcesses, objProcess, inteproc
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
inteproc = -1 'set in unknown state
Do Until inteproc = 0
Set colProcesses = objWMIService.ExecQuery(_
"Select * from Win32_Process where Name='" & PROC_NAME & "'")
inteproc = colProcesses.count
If inteproc > 0 then
WSCRIPT.ECHO "Process " & PROC_NAME & " is still runing, wait for " & SLEEP_INTERVAL_MS / 1000 & " seconds"
WScript.Sleep(SLEEP_INTERVAL_MS)
else
wscript.echo "Process " & PROC_NAME & " Finished. Continue running scripts"
End If
Loop

Related

VBScript *unintentionally* pauses on background

For a brief description of the code I have, I want to keep in track a certain app named 'CostX.exe' if it closes and opens and I log it on a file called CostXLog.txt
I keep it on an infinite loop. The problem is, i dont know why but it works for a brief period when Im not doing anything productive, but when I do, the script just pauses or should I say it doesnt work anymore though it still stays in the background.
This should be its desired output.
Opened at: 4/7/2021 9:00:52 AM
Closed at: 4/7/2021 9:07:56 AM
CostX was opened for 7 minutes and 4 seconds.
But when I say I do anything productive, the output stays at
Opened at: 4/7/2021 9:00:52 AM
This is my code
Option Explicit
Const ForReading = 1, ForAppending = 8
Dim i, processName, strComputer
Dim fso, inName, outName, shell, curDir, objWMIService, colProcessList
Set fso = CreateObject("Scripting.FileSystemObject")
Set shell = CreateObject("WScript.Shell")
curDir = shell.CurrentDirectory
outName = curDir & "\CostXLog.txt"
Dim counter1, counter2, initialOpen
Dim minDiff, secDiff
Dim timedate1, timedate2
timedate1 = Date() & " " & Time()
initialOpen = 0
counter1 = 0
counter2 = 1
'msgbox curDir
strComputer = "."
processName = "CostX.exe"
Dim newFile, outputFile
newFile = Not fso.FileExists( outName )
while(true)
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colProcessList = objWMIService.ExecQuery _
("Select Name from Win32_Process WHERE Name LIKE '" & processName & "%'")
Set outputFile = fso.OpenTextFile( outName, ForAppending, True )
if initialOpen = 0 Then
outputFile.WriteLine "Ignore time after this line"
initialOpen = 1
else
If colProcessList.count>0 then
If counter1 = 0 Then
outputFile.WriteLine "Opened at: " & Date() & " " & Time()
timedate1 = Date() & " " & Time()
counter1 = 1
counter2 = 1
End If
else
If counter2 = 1 Then
outputFile.WriteLine "Closed at: " & Date() & " " & Time()
timedate2 = Date() & " " & Time()
minDiff = DateDiff("s", timedate1, timedate2)/60
secDiff = DateDiff("s", timedate1, timedate2)
outputFile.WriteLine "CostX was opened for " & Fix(minDiff) & " minutes and " & secDiff - (Fix(secDiff/60) * 60) & " seconds."
counter2 = 0
counter1 = 0
End If
End if
End If
outputFile.Close
WScript.Sleep 50
wend
Set objWMIService = Nothing
Set colProcessList = Nothing
PS: I am not a programmer, I have assembled that from many sources in the internet, I do understand a bit, but some of the parts in there, I really dont have any idea, I just know that they work as I want them to. So i guess someone could provide me an idea as to how to keep it running no matter what I do in my computer. Is there anything wrong with what I did in the code?
I have also done a batch script with the same intended purpose, the issue is the same, it was also made with a loop, and it pauses when I am busy working.

VBS process memory consumption growing over time

I have a VBScript that I run with Windows Script Host. The script reads some stuff from a text file and then launches a desktop shortcut every time a file is added to a certain folder. It starts of at 1.4Mb memory and grows every time I add a file to that folder. Is there a way to solve that? If not, I guess I could have a script that periodically kills the first script and relaunches it? Here is the script:
'- Read some stuff from a file
Set f = CreateObject("Scripting.FileSystemObject").OpenTextFile("D:\Post
Processing Files\Common Files\New Data Folder Watcher\DATA_STORE.txt", 1)
dataStore = replace(f.ReadLine,"Title:","")
f.SkipLine
shortCut = replace(f.ReadLine,"Title:","")
f.Close
strComputer = "."
Set objWMIService = GetObject("winmgmts:" & "
{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colMonitoredEvents = objWMIService.ExecNotificationQuery("SELECT * FROM
__InstanceCreationEvent WITHIN 5 WHERE " & "Targetinstance ISA
'CIM_DirectoryContainsFile' and " & "TargetInstance.GroupComponent= " &
"'Win32_Directory.Name=" &Chr(34)& dataStore &Chr(34)& "'")
Set objShell = CreateObject("Wscript.Shell")
'- Watch
Do
Set objLatestEvent = colMonitoredEvents.NextEvent
objLatestEvent.TargetInstance.PartComponent
objShell.Run shortCut
'- Delay
WScript.Sleep 120000
Loop
EDIT: Added Set object = Nothing. Process is still growing (a little less though). What else can possibly make it grow?
New code:
'- Read some stuff from a file
Set f = CreateObject("Scripting.FileSystemObject").OpenTextFile("D:\Post
Processing Files\Common Files\New Data Folder Watcher\DATA_STORE.txt", 1)
dataStore = replace(f.ReadLine,"Title:","")
f.SkipLine
shortCut = replace(f.ReadLine,"Title:","")
f.Close
Set f = Nothing
strComputer = "."
' LOOP THROUGH EACH NEWLY ADDED FILE
Do
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colMonitoredEvents = objWMIService.ExecNotificationQuery("SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE " & "Targetinstance ISA 'CIM_DirectoryContainsFile' and " & "TargetInstance.GroupComponent= " & "'Win32_Directory.Name=" &Chr(34)& dataStore &Chr(34)& "'")
Set objLatestEvent = colMonitoredEvents.NextEvent
Set objShell = CreateObject("Wscript.Shell")
objLatestEvent.TargetInstance.PartComponent
objShell.Run shortCut
'- Delay
WScript.Sleep 120000
'- Clear Memory
Set objLatestEvent = Nothing
Set objShell = Nothing
Set colMonitoredEvents = Nothing
Set objWMIService = Nothing
Loop

Can anyone help me close this program in VBScript?

MsgBox ("Do you want to start the autoclicker?", vbOkOnly, "Autoclicker")
CreateObject("WScript.Shell").Run("""C:\Users\Henry\Desktop\Fun.vbs""")
MsgBox ("Do you want to stop the autoclicker?", vbOkOnly, "Autoclicker")
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * From Win32_Process")
For Each objItem in colItems
'msgbox objItem.ProcessID & " " & objItem.CommandLine
If objItem.name = "Calculator.exe" then objItem.terminate
Next
This kills calculator.exe. Change it to wscript.exe. You might want to check command line if you just want to kill fun.vbs.
The following routine kills all processes whose command lines contain a specified string. The 3 lines below the routine are for testing it. We pause the routine by showing a message box and when you dismiss the message box, we kill the script instance, so the second message box doesn't show up. When you use it, you want to replace the last 3 lines with
KillProcesses "Fun.vbs"
I'd be careful using this and specify as much of the command line as possible to make sure I absolutely, positively match only the processes I want to terminate. You can modify the Task Manager and add a column to show the command line for every running process. In the routine below, the search in command line is case-insensitive.
Option Explicit
Sub KillProcesses(strPartOfCommandLine)
Dim colProcesses
Dim objProcess
Dim lReturn
' Get list of running processes using WMI
Set colProcesses = GetObject("winmgmts:\\.\root\cimv2").ExecQuery("Select * From Win32_Process")
For Each objProcess in colProcesses
If (Instr(1, objProcess.Commandline, strPartOfCommandLine, vbTextCompare) <> 0) Then
lReturn = objProcess.Terminate(0)
End If
Next
End Sub
Msgbox "Before being killed"
KillProcesses "KillProcesses.vbs"
Msgbox "After being killed"
I made before a script that ask you what vbscript did you want to kill and log the result into file.
So just, give a try :
Option Explicit
Dim Titre,Copyright,fso,ws,NomFichierLog,temp,PathNomFichierLog,OutPut,Count,strComputer
Copyright = "[© Hackoo © 2014 ]"
Titre = " Process "& DblQuote("Wscript.exe") &" running "
Set fso = CreateObject("Scripting.FileSystemObject")
Set ws = CreateObject( "Wscript.Shell" )
NomFichierLog="Process_WScript.txt"
temp = ws.ExpandEnvironmentStrings("%temp%")
PathNomFichierLog = temp & "\" & NomFichierLog
Set OutPut = fso.CreateTextFile(temp & "\" & NomFichierLog,1)
Count = 0
strComputer = "."
Call Find("wscript.exe")
Call Explorer(PathNomFichierLog)
'***************************************************************************************************
Function Explorer(File)
Dim ws
Set ws = CreateObject("wscript.shell")
ws.run "Explorer "& File & "\",1,True
end Function
'***************************************************************************************************
Sub Find(MyProcess)
Dim colItems,objItem,Processus,Question
Set colItems = GetObject("winmgmts:").ExecQuery("Select * from Win32_Process " _
& "Where Name like '%"& MyProcess &"%' AND NOT commandline like '%" & wsh.scriptname & "%'",,48)
For Each objItem in colItems
Count= Count + 1
Processus = Mid(objItem.CommandLine,InStr(objItem.CommandLine,""" """) + 2) 'Extraction of the commandline script path
Processus = Replace(Processus,chr(34),"")
Question = MsgBox ("Did you want to stop this script : "& DblQuote(Processus) &" ?" ,VBYesNO+VbQuestion,Titre+Copyright)
If Question = VbYes then
objItem.Terminate(0)'Kill this process
OutPut.WriteLine DblQuote(Processus)
else
Count= Count - 1 'decrement the counter -1
End if
Next
OutPut.WriteLine String(100,"*")
OutPut.WriteLine count & Titre & " were stopped !"
End Sub
'**********************************************************************************************
Function DblQuote(Str)
DblQuote = Chr(34) & Str & Chr(34)
End Function
'**********************************************************************************************

Need to monitor a process

I am writing a vb script to monitor a process. The script monitors the status of a process and if the process is not running since 10 mins it should execute a command.Below is my script:
set objWMIService = GetObject ("winmgmts:")
foundProc = False
procName = "calc.exe"
Dim wshell
' Initialise the shell object to return the value to the monitor
Set wshell = CreateObject("WScript.Shell")
if err.number <> 0 then
WScript.Echo "Error: could not create WScript.Shell (error " & err.number & ", " & err.Description & ")"
WScript.quit(255)
end if
for each Process in objWMIService.InstancesOf ("Win32_Process")
If StrComp(Process.Name,procName,vbTextCompare) = 0 then
foundProc = True
procID = Process.ProcessId
End If
Next
#####code to check the proces status
If foundProc = True Then
WScript.Quit(0)
Else
WScript.sleep(1*60*1000)
If foundProc = True Then
WScript.Echo "Found Process (" & procID & ")"
Else
WScript.Echo "Process not running since 10 mins"
WScript.Quit(0)
End If
End If
Set WshShell = WScript.CreateObject("WScript.Shell")
Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2")
Set objEvents = objWMIService.ExecNotificationQuery _
("SELECT * FROM Win32_ProcessTrace")
Do
Set objReceivedEvent = objEvents.NextEvent
If objReceivedEvent.ProcessName = "svchost.exe" then msgbox objReceivedEvent.ProcessName
' msgbox objReceivedEvent.ProcessName
Loop
You also have Win32_ProcessTraceStart and Win32_ProcessTraceStop. Above code is both.
It is also pointless doing error checking on WScript.Shell. It's a system component - it should be available. Also if it's not your script won't run as wscript isn't available to run your script.

Echo whether a process is running on a range of remote computers

I'm trying to create a script that will connect to remote computers within an IP address range and then echo which of those is running the explorer.exe process.
When I run the script within a small range (10.2.1.1 - 10.2.1.10), I know that 10.2.1.4 is offline and that 10.2.1.9 and 10.2.1.10 are not Windows based computers and should therefore echo "Explorer.exe is not running" however that doesn't seem to be the case. They appear to return the same result of the previous server. For instance, 10.2.1.3 has 3 instances of Explorer.exe and echo's 3 times, I then get the same result for 10.2.1.4 which is offline.
My script is as follows:
On Error Resume Next
intStartingAddress = InputBox("Please enter a starting address: (e.g. 1)", "Starting Address")
intEndingAddress = InputBox("Please enter an ending address: (e.g. 254)", "Ending Address")
strSubnet = InputBox("Please enter a subnet excluding the last octet: (e.g. 10.2.1.)", "Subnet")
For i = intStartingAddress to intEndingAddress
strComputer = strSubnet & i
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colProcess = objWMIService.ExecQuery("Select * From Win32_Process Where Name = 'Explorer.exe'")
For Each objProcess in colProcess
If colProcess.Count > 0 Then
Wscript.Echo strComputer & " Explorer.exe is running."
Else
Wscript.Echo strComputer & " Explorer.exe is not running."
End If
Next
Next
Wscript.Echo "That's all folks!"
What makes you believe that non-Windows computers would respond to WMI queries in the first place? For most non-Windows computers the statement
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" _
& strComputer & "\root\cimv2")
will simply fail, because they don't support WMI (which is short for Windows Management Instrumentation). Because of this error, the objWMIService object remains the same as it was in the previous loop cycle, so your subsequent instructions query the same host you did before. You never see the error, though, because it's masked by the global On Error Resume Next.
This can be mitigated by removing the global On Error Resume Next and changing this loop:
For i = intStartingAddress to intEndingAddress
strComputer = strSubnet & i
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
...
Next
into something like this:
For i = intStartingAddress to intEndingAddress
strComputer = strSubnet & i
Set objWMIService = Nothing
On Error Resume Next
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" _
& strComputer & "\root\cimv2")
On Error Goto 0
If Not objWMIService Is Nothing Then
...
Else
WScript.Echo strComputer & " cannot be accessed."
End If
Next
You can distinguish between unreachable computers and computers that don't appear to be running Windows by combining the above with a ping test:
Set wmi = GetObject("winmgmts://./root/cimv2")
qry = "SELECT * FROM Win32_PingStatus WHERE Address='" & strComputer & "'"
For Each ping In wmi.ExecQuery(qry)
reachable = (0 = ping.StatusCode)
Next
If reachable Then
If objWMIService Is Nothing Then
'computer is not running Windows
Else
'computer is running Windows
End If
Else
'computer is offline
End If
First: I would move the colProcess.Count check to occur before the colProcess loop. If there are no collections in the object you will not get an echo response.
Second: I would test for a value within the WMI query such as ProcessID and check if it is Null or if it does have a value, meaning that it is actually running.
intStartingAddress = InputBox("Please enter a starting address: (e.g. 1)", "Starting Address")
intEndingAddress = InputBox("Please enter an ending address: (e.g. 254)", "Ending Address")
strSubnet = InputBox("Please enter a subnet excluding the last octet: (e.g. 10.2.1.)", "Subnet")
For i = intStartingAddress to intEndingAddress
strComputer = strSubnet & i
Set objWMIService = Nothing
On Error Resume Next
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
On Error Goto 0
If objWMIService Is Nothing Then
Wscript.Echo strComputer & " Explorer.exe is not running."
Else
Set colProcess = objWMIService.ExecQuery("Select * From Win32_Process Where Name = 'Explorer.exe'")
If colProcess.Count = 0 Then
Wscript.Echo strComputer & " Explorer.exe is not running."
Else
For Each objProcess in colProcess
If IsNull(objItem.ProcessID) Or Not IsNumeric(objItem.ProcessID) Then
Wscript.Echo strComputer & " Explorer.exe is not running."
Else
Wscript.Echo strComputer & " Explorer.exe is running. (Process ID: " & objItem.ProcessID & ")"
End If
Next
End If
End If
Next
Wscript.Echo "That's all folks!"
EDIT:
Modified Script to take into account the WMI Query will fail on Non-Windows Operating Systems as pointed out by Ansgar Wiechers.

Resources