I'm trying to create a way that will check if a certain program is running - and if it is, launch another program.
This is my progress in BAT
#ECHO OFF
:LOOP
tasklist /nh /fi "imagename eq steam.exe" | find /i "steam.exe" >nul && START "" "C:\Program Files\TeamSpeak 3 Client\ts3client_win64.exe" || goto :LOOP
And I created a VBS that basically starts the BAT at Windows startup (this is only to make sure the batch file runs without a visible console window):
Set WshShell = CreateObject("WScript.Shell" )
WshShell.Run chr(34) & "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\if Steam running then TS.bat" & Chr(34), 0
Set WshShell = Nothing
My problem is that doing so, i get a incredibly high CPU usage (20 to 60% with a I5-4670k).
Have i done something wrong? Or can I improve the code anyhow? I was thinking about slowing the time where windows checks for the process (i.e. wait 2 sec then check) but I'm really new to coding and I don't have any idea on how to do so.
I know my English isn't perfect, excuse me.
EDIT: If it helps, my PC is running on Windows 10.
i get a incredibly high CPU usage
You need to give your computer a break between the checks. The timeout command interrupts batch execution for a configurable number of seconds:
#echo off
setlocal
set "FIND_STEAM=tasklist /nh /fi "imagename eq steam.exe" ^| find /i "steam.exe" ^> NUL"
set "START_TS=start "C:\Program Files\TeamSpeak 3 Client\ts3client_win64.exe""
:LOOP
timeout 5 > NUL
%FIND_STEAM% && %START_TS% || goto LOOP
EDIT
Here is bells-and-whistles sophisticated way of reacting to the start and termination of a process in Windows using VBScript.
It works with the WMI, a powerful framework that can do all kinds of things in Windows. Here we use it to listen to process creation and process termination events. (listening to events is a lot more efficient than polling all processes every second or so):
Option Explicit
Dim WMIService, ProcessNew, ProcessEnd
Dim computer, query, teamspeakPID
' create a WMI service object and ProcessNew / ProcessEnd event sinks
computer = "."
Set WMIService = GetObject("winmgmts:\\" & computer & "\root\CIMV2")
Set ProcessNew = WScript.CreateObject("WbemScripting.SWbemSink", "ProcessNew_")
Set ProcessEnd = WScript.CreateObject("WbemScripting.SWbemSink", "ProcessEnd_")
' we will be waiting for Win32_Process creation events and notify event sink "ProcessNew"
WMIService.ExecNotificationQueryAsync ProcessNew, _
"SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_Process'"
' we will also be waiting for Win32_Process deletion events and notify event sink "ProcessEnd"
WMIService.ExecNotificationQueryAsync ProcessEnd, _
"SELECT * FROM __InstanceDeletionEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_Process'"
' main loop: nothing to do, we just sit and wait
While True
Wscript.Sleep(500)
Wend
' function that handles "process created" events
Sub ProcessNew_OnObjectReady(latestEvent, asyncContext)
Dim process
If LCase(latestEvent.TargetInstance.Name) = "steam.exe" Then
' start TeamSpeak
Set process = GetObject("winmgmts:Win32_Process")
process.Create "C:\Program Files\TeamSpeak 3 Client\ts3client_win64.exe", null, null, teamspeakPID
End If
End Sub
' function that handles "process ended" events
Sub ProcessEnd_OnObjectReady(latestEvent, asyncContext)
Dim processList, process
If LCase(latestEvent.TargetInstance.Name) = "steam.exe" Then
' kill TeamSpeak (but only the one we started earlier)
Set processList = WMIService.ExecQuery("SELECT * FROM Win32_Process WHERE Name = 'ts3client_win64.exe' AND ProcessId = " & teamspeakPID)
For Each process in processList
process.Terminate()
Next
End If
End Sub
As an exercise you can try to extend this so that it only starts TS when it's not already running.
Further reading:
Technet "Doctor Scripto's Script Shop" column
WMI asynchronous event monitoring with VBScript
Out of Sync: The Return of Asynchronous Event Monitoring
MSDN
The Win32_Process Class
Create method of the Win32_Process class
Terminate method of the Win32_Process class
SWbemServices.ExecNotificationQueryAsync method
Related
I'm having a hard time finding an answer to this question. I'm looking specifically to execute a command in a batch file only after a program is terminated - however, a program that wasn't launched by the batch file.
My problem is this - the program I am actually launching in the batch file I want to wait on is in turn launching another program, which in turn launches another. This probably doesn't make any sense - but it's because it's a game launcher. It is for Final Fantasy XIV. The normal program that is launched to start it is ffxivboot.exe, which in turn launches ffxivlauncher.exe. That is a login window, and once you login, it in turn launches ffxiv_dx11.exe. So while I originally wrote it to wait on ffxivboot.exe, that process doesn't stay running so I am unable to wait on it.
Here's my file (excluded paths for simplicity):
taskkill /im someprogram.exe
ffxivboot.exe
timeout /t 60 /nobreak
### ??? need to wait on ffxiv_dx11.exe to close before executing next command
someprogram.exe
I added a timer to wait so that it gives me plenty of time to login - because the ffxiv_dx11.exe process doesn't start until after logging in.
Is what I'm trying to do possible? It's hard to search for answers to this because I only get results regarding when you're waiting on a task to end that was started from the batch file. But like I said, that one launches another which in turn launches another - so the original process is no longer running.
Thanks for any help!
taskkill /im someprogram.exe
ffxivboot.exe
timeout /t 60 /nobreak
:repeat
::### ??? need to wait on ffxiv_dx11.exe to close before executing next command
tasklist /fi "imagename eq ffxiv_dx11.exe"|find /i "=========================" >nul 2>nul &&(
w32tm /stripchart /computer:localhost /period:10 /dataonly /samples:2 1>nul
goto :repeat
)
someprogram.exe
try this
Set WshShell = WScript.CreateObject("WScript.Shell")
Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2")
Set objEvents = objWMIService.ExecNotificationQuery _
("SELECT * FROM Win32_ProcessStopTrace")
Do
Set objReceivedEvent = objEvents.NextEvent
msgbox objReceivedEvent.ProcessName
If lcase(objReceivedEvent.ProcessName) = lcase("Notepad.exe") then
Msgbox "Process exited with exit code " & objReceivedEvent.ExitStatus
WshShell.Run "c:\Windows\notepad.exe", 1, false
End If
Loop
This is a vbs file that needs to run elevated. It waits for any program to exit and checks if it's notepad and springs to life restarting it.
Type in a elevated command prompt taskkill /f /I'm wscript.exe to stop it.
I'm trying to execute this simple test script, but a command shell window is appearing after I execute the script.:
Set objShell = WScript.CreateObject("WScript.Shell")
strCommand = "cmd /C tasklist"
Set objExecObject = objShell.Exec(strCommand)
wscript.echo "Test"
How can I prevent it from showing up?
Update
I was able to improve it with this code change:
strCommand = "cmd /C /Q tasklist"
Now the window only shows up for a split second. But I don't want it to show up at all.
You're always going to get a window flash with Exec(). You can use Run() instead to execute the command in a hidden window. But you can't directly capture the command's output with Run(). You'd have to redirect the output to a temporary file that your VBScript could then open, read, and delete.
For example:
With CreateObject("WScript.Shell")
' Pass 0 as the second parameter to hide the window...
.Run "cmd /c tasklist.exe > c:\out.txt", 0, True
End With
' Read the output and remove the file when done...
Dim strOutput
With CreateObject("Scripting.FileSystemObject")
strOutput = .OpenTextFile("c:\out.txt").ReadAll()
.DeleteFile "c:\out.txt"
End With
The FileSystemObject class has methods like GetSpecialFolder() to retrieve the path of Windows temp folder and GetTempName() to generate a temporary filename that you can use instead of hardcoding an output filename as I've done above.
Also note that you can use the /FO CSV argument with tasklist.exe to create a CSV file which should make parsing it much easier.
Finally, there are VBScript "native" ways to retrieve the list of running processes. WMI's Win32_Process class, for example, can do this without the need for Run/Exec.
Edit:
For the sake of completeness, I should mention that your script can relaunch itself in a hidden console window where you can run Exec() silently. Unfortunately, this hidden console window will also hide your output from functions like WScript.Echo(). Aside from that, however, you probably won't notice any differences running your script under cscript vs wscript. Here's an example of this method:
' If running under wscript.exe, relaunch under cscript.exe in a hidden window...
If InStr(1, WScript.FullName, "wscript.exe", vbTextCompare) > 0 Then
With CreateObject("WScript.Shell")
WScript.Quit .Run("cscript.exe """ & WScript.ScriptFullName & """", 0, True)
End With
End If
' "Real" start of script. We can run Exec() hidden now...
Dim strOutput
strOutput = CreateObject("WScript.Shell").Exec("tasklist.exe").StdOut.ReadAll()
' Need to use MsgBox() since WScript.Echo() is sent to hidden console window...
MsgBox strOutput
Of course, if your script expects command-line parameters, those would need to be forwarded when relaunching your script as well.
Edit 2:
Yet another possibility is to use the Windows clipboard. You can pipe the output of your command to the clip.exe utility. Then, retrieve the text via any number of available COM objects that can access the contents of the clipboard. For example:
' Using a hidden window, pipe the output of the command to the CLIP.EXE utility...
CreateObject("WScript.Shell").Run "cmd /c tasklist.exe | clip", 0, True
' Now read the clipboard text...
Dim strOutput
strOutput = CreateObject("htmlfile").ParentWindow.ClipboardData.GetData("text")
You can use .Exec() method, without console window flash, temp files and unexpected WScript.Echo output muting. The method is slightly tricky, and requires to launch secondary linked script, so I added the comments:
Option Explicit
Dim objDummy, strSignature, objPrimary, objSecondary, objContainer, objWshShell, objWshShellExec, strResult
' this block is executed only in the secondary script flow, after primary script runs cscript
If WScript.Arguments.Named.Exists("signature") Then
' retrieve signature string from argument
strSignature = WScript.Arguments.Named("signature")
Do
' loop through all explorer windows
For Each objContainer In CreateObject("Shell.Application").Windows
' check if the explorer's property with signature name contains the reference to the live script
If ChkVBScriptTypeInfo(objContainer.getProperty(strSignature)) Then
Exit Do
End If
Next
WScript.Sleep 10
Loop
' create shell object within secondary script
Set objWshShell = CreateObject("WScript.Shell")
' retrieve the primary script me object reference from explorer's property with signature name
Set objPrimary = objContainer.getProperty(strSignature)
' quit explorer window to release memory as it's no longer needed
objContainer.Quit
' assign the secondary script me object to the primary script's variable
Set objPrimary.objSecondary = Me
' emtpy loop while primary script is working
Do While ChkVBScriptTypeInfo(objPrimary)
WScript.Sleep 10
Loop
' terminate secondary
WScript.Quit
End If
' the code below is executed first in the primary script flow
' create signature string
strSignature = Left(CreateObject("Scriptlet.TypeLib").Guid, 38)
' create new hidden explorer window as container to transfer a reference between script processes
Set objContainer = GetObject("new:{C08AFD90-F2A1-11D1-8455-00A0C91F3880}")
' put this script's me object reference into explorer's property
objContainer.putProperty strSignature, Me
' launch new secondary process of the same script file via cscript.exe with hidden console window, providing signature string in named argument to identify host script
CreateObject("WScript.Shell").Run ("""" & Replace(LCase(WScript.FullName), "wscript", "cscript") & """ //nologo """ & WScript.ScriptFullName & """ ""/signature:" & strSignature & """"), 0
' wait until secondary script has been initialized and put his me object into this script variable
Do Until ChkVBScriptTypeInfo(objSecondary)
WScript.Sleep 10
Loop
' here is your code starts...
' create exec object within hidden console window of secondary script, execute cmd instruction
Set objWshShellExec = objSecondary.objWshShell.Exec("%comspec% /c tasklist")
' read cmd output
strResult = objWshShellExec.StdOut.ReadAll()
WScript.Echo strResult
' ...
' utility check if me object is live
Function ChkVBScriptTypeInfo(objSample)
On Error Resume Next
If TypeName(objSample) <> "VBScriptTypeInfo" Then
ChkVBScriptTypeInfo = False
Exit Function
End If
ChkVBScriptTypeInfo = True
End Function
UPDATE
I've slightly reworked the code to make it more straightforward:
Option Explicit
Dim strCmd, strRes, objWnd, objParent, strSignature
If WScript.Arguments.Named.Exists("signature") Then WshShellExecCmd
strCmd = "%comspec% /c tasklist"
RunCScriptHidden
WScript.Echo strRes
Sub RunCScriptHidden()
strSignature = Left(CreateObject("Scriptlet.TypeLib").Guid, 38)
GetObject("new:{C08AFD90-F2A1-11D1-8455-00A0C91F3880}").putProperty strSignature, Me
CreateObject("WScript.Shell").Run ("""" & Replace(LCase(WScript.FullName), "wscript", "cscript") & """ //nologo """ & WScript.ScriptFullName & """ ""/signature:" & strSignature & """"), 0, True
End Sub
Sub WshShellExecCmd()
For Each objWnd In CreateObject("Shell.Application").Windows
If IsObject(objWnd.getProperty(WScript.Arguments.Named("signature"))) Then Exit For
Next
Set objParent = objWnd.getProperty(WScript.Arguments.Named("signature"))
objWnd.Quit
objParent.strRes = CreateObject("WScript.Shell").Exec(objParent.strCmd).StdOut.ReadAll()
WScript.Quit
End Sub
BTW, here is VBScript "multithreading" implementation that uses the same container approach.
Some great suggestions are listed above. I'd like to make one more suggestion which is more of a workaround. You can use Sysinternals Desktops (a free program) to run your macro on another desktop on your same machine. That way the flashing can all happen on its own desktop and won't interrupt your work.
I use Sysinternals PSEXEC
https://learn.microsoft.com/sv-se/sysinternals/downloads/psexec
Created a Batch-file (in the same folder as the vbs and exe-file) that runs the script as system user.
I can not Access the user profile and I need to be local Admin but when i run the script without interaction with the desktop it will hide all annoying popups.
Run Script as system without interaction with desktop
"%~dp0PsExec.exe" -s wscript.exe "%~dp0MyScript.vbs"
Run Script as system with interaction with desktop
"%~dp0PsExec.exe" -s -i wscript.exe "%~dp0MyScript.vbs"
To hide the command line windows in VBscipt is use Run in WshShell Object
Then to get the result you can send this result to text file in %temp%
Then read this result with FileSystemObject
Set Sh = CreateObject("WScript.Shell")
tFile=Sh.ExpandEnvironmentStrings("%Temp%")&"\t.txt"
Sh.Run "cmd.exe /C tasklist > """&tFile&""" ",0,False
Wscript.echo CreateObject("Scripting.FileSystemObject").openTextFile(tFile).readAll()
OR
If StrComp(right(WScript.FullName,11),"wscript.exe",1) = 0 Then '' get only wscript.exe from "c:\windows\system32\wscript.exe" to compere with wscript.exe
WScript.Quit CreateObject("WScript.Shell").Run("cscript.exe """ & WScript.ScriptFullName & """", 0, False)
End If
MsgBox CreateObject("WScript.Shell").Exec("cmd.exe /c tasklist /v /fi ""imagename EQ explorer*"" /FO LIST | FIND ""PID:""").StdOut.ReadAll()
An alternative to using to windows scripting host is here: Run a batch program(.bat) through a Visual Basic 6.0
It runs a program and captures its screen output. It works for me in VB6, but not in VBA (hangs at WaitForSingleObject, don't know why).
After trying the main solutions without success, I was able to solve my problem with the following code:
With CreateObject("WScript.Shell")
.Run "cmd /c start /b tasklist.exe > c:\out.txt", 0, True
End With
The real deal was the "/b" as the console help display:
START ["title"] [/D path] [/I] [/MIN] [/MAX] [/SEPARATE | /SHARED]
[/LOW | /NORMAL | /HIGH | /REALTIME | /ABOVENORMAL | /BELOWNORMAL]
[/NODE <NUMA node>] [/AFFINITY <hex affinity mask>] [/WAIT] [/B]
[command/program] [parameters]
"title" Title to display in window title bar.
path Starting directory.
B Start application without creating a new window. The
application has ^C handling ignored. Unless the application
enables ^C processing, ^Break is the only way to interrupt
the application.
I have a batch file that I use every time I start my work PC. Basically, it kills all the bloatware that the IT department puts on the PC that run as my user account that I never even use using taskkill, installs a small program, then loads all the programs I actually need at once. Problem is, one of the programs that I run, the IT department recently thought it would be helpful to install a "helper" program to automate some things within the program that I already know how to do and can do it fairly quickly manually. Problem is, the helper program actually has the reverse effect and slows the actual program down. We are of course complaining to IT about it but it'll probably take them months to fix it, if ever. In the meantime, I found out that the helper program runs as it's own process under my user account, which means I can kill it, and everything runs smoothly again. Problem is, how the program runs. I launch the program normally and this happens:
Process A loads. Process A loads process B. Process A kills itself. Process B loads process C. Process C loads process D, E, and F (the helper programs). Process B kills itself, while leaving C, D, E, and F in memory (program is fully loaded at this point)
How can I have the batch file just wait for process B to kill itself, before proceeding with the taskkill commands to kill processes D, E, and F? Since the command line only sees process A when directly calling the EXE, it resumes the batch file in under a second since A kills itself that quickly. I can't just use timeout or some other generic time waster because the load time of the program is too volatile, what with network issues, program updates, etc.
I built something exactly like this a few years ago, but unfortunately don't have the code with me and don't have access to a Windows machine at the moment.
However, it should be fairly simple, and will be along these lines (just tweak the code to get it work or let me know if there are any issues; I can't test it but should be able to fix them if I know what they are):
rem Usage: :killprocesswithwait [pid]
call :killprocesswithwait 1234
:killprocesswithwait
set pid=%1
taskkill /pid %pid%
:iloop
ping 127.0.0.1 -n 2 > nul
for /f "tokens=*" %%a in ('tasklist /fi "PID eq %pid%" ^| find /i %pid%') do (
if /i "%%a"=="" (
goto :eof
) else (
goto :iloop
)
)
This waits for a any and all programs to exit and checks if Notepad and restarts it if it is.
It surely would be better to wait for the three programs to start. Change Win32_ProcessStopTrace to Win32_ProcessStartTrace.
Set WshShell = WScript.CreateObject("WScript.Shell")
Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2")
Set objEvents = objWMIService.ExecNotificationQuery _
("SELECT * FROM Win32_ProcessStopTrace")
Do
Set objReceivedEvent = objEvents.NextEvent
msgbox objReceivedEvent.ProcessName
If lcase(objReceivedEvent.ProcessName) = lcase("Notepad.exe") then
Msgbox "Process exited with exit code " & objReceivedEvent.ExitStatus
WshShell.Run "c:\Windows\notepad.exe", 1, false
End If
Loop
And this lists processes and terminate any called calculator.
Set objWMIService = GetObject("winmgmts:\\.\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
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q36241667.txt"
SET "filename2=%sourcedir%\q36241667_2.txt"
:dloop
FOR /f "usebackqdelims=" %%a IN ("%filename1%") DO (
tasklist|FIND "%%a" >NUL
IF ERRORLEVEL 1 timeout /t 1 >nul&GOTO dloop
)
FOR /f "usebackqdelims=" %%a IN ("%filename2%") DO ECHO(%%a
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
I used files named q36241667.txt & q36241667_2.txt containing some dummy data for my testing.
Suppose filename1 contains
processa.exe
processb.exe
processc.exe
processd.exe
processe.exe
then the for loop will wait until all of the processes are running before proceeding.
filename2 contains the kill commands required (echoed for demo purposes)
If this routine is simply started in your startup routine, then it could itself trigger start commands to kill any unwanted processes.
I use a similar routine to back up critical directories to a ramstick on start-up.
Thanks guys, I actually took Ruslan's answer and simplified and changed it a bit. This works great. Waits for exe3 to load since it's the last one to load, then kills all 3. Didn't need to set the variables so removed those and completely forgot about putting it in a loop.
:start
FOR /F %%x IN ('tasklist /NH /FI "IMAGENAME eq exe3.exe"') DO IF %%x == exe3.exe goto found
goto start
:found
taskkill /f /fi "blah1.exe"
taskkill /f /fi "blah2.exe"
taskkill /f /fi "blah3.exe"
total vbs scripting newb here. I'm trying to automate closing a certain open window, namely a program called HostsMan. This is on Windows 8.1 Pro 64 bit, and this is what my script currently looks like:
Set WshShell = CreateObject("WScript.Shell")
WshShell.AppActivate "HostsMan"
WshShell.SendKeys "%{F4}"
The second line doesn't seem to work. I know line 3 works because it activates the Windows shutdown menu. Is there something I'm missing?
Update/more info: Manually entering alt-F4 does close it, so I know this should work. I also tested this script with other open windows and they close just fine. Additionally, HostsMan is opened with Admin privileges, so I tried running the script as a task set with highest privileges to see if that would do it, and still no go. But that does work with other open windows running with Admin privileges. Frustrating!
I've tried it, too, and couldn't get it to work. There must be something about the window class, perhaps, where AppActivate doesn't see it as a top-level window?
In any event, AppActivate also lets you pass the process ID instead of the window title. When I installed HostsMan, the process name was hm.exe, so I'll use that in my example below.
Set Processes = GetObject("winmgmts:").InstancesOf("Win32_Process")
For Each Process In Processes
If StrComp(Process.Name, "hm.exe", vbTextCompare) = 0 Then
' Activate the window using its process ID...
With CreateObject("WScript.Shell")
.AppActivate Process.ProcessId
.SendKeys "%{F4}"
End With
' We found our process. No more iteration required...
Exit For
End If
Next
Alternative solution using WMIService (no loop through all processes required):
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
Set colItems = objWMIService.ExecQuery("SELECT * from Win32_Process WHERE Name = '" & ProcessName & "'")
If colItems.Count = 0 Then
WScript.Echo "Process not found"
Wscript.Quit
End If
For Each objProcess in colItems
WshShell.AppActivate(objProcess.ProcessId)
Exit For
Next
The key here is to put a small pause after the 'run' command but before the 'appactivate' command so the application shows up in the process list.
WshShell.Run "calc"
WScript.Sleep 100
WshShell.AppActivate "Calculator"
To solve the problem of AppActivate you have to use loop and if condition statement to check if the active windows is the target windows or not because sometime you deselect or the system deselect the target windows before execute the sendkeys directly so you got error.
I create this tight strict way
Set WshShell = CreateObject("WScript.Shell")
for i=0 to 300 ' this loop will continue about 30 sec if this not enough increase this number
Rtn=WshShell.AppActivate("HostsMan") ' HostMan have to be the windows title of application or its process ID
If Rtn = True Then
WshShell.SendKeys "%{F4}" ' send key to click ALT+F4 to close
wscript.sleep 100 ' stop execute next line until finish close app
Rtn=WshShell.AppActivate("HostsMan")
If Rtn=False Then ' using nested If to sure of selected windows is false because its close
Exit For ' exit for loop directly and execute what after for next
End If
End If
wscript.sleep 100
Next
Dim sh : Set sh =CreateObject("Wscript.Shell")
sh.Exec "calc.exe"
Wscript.Sleep 1000
sh.Exec "taskkill /f /FI ""WINDOWTITLE eq ""calc*"""
OR
sh.Run "taskkill /f /im calc.exe",0,False
I'm trying to write a Windows command file to open a webpage in IE, wait for it to load, then close the IE window. The following works but will kill all IE windows so any that were already open before running the .cmd will also get closed.
start iexplore.exe "page to load"
ping localhost -n 10 > nul
taskkill /IM iexplore.exe
I only want to kill the IE that was opened. I know I can just kill a particular process if I know its PID but how can find this from the command line? Is there a way to get it when starting the IE window? What I really want to do is:
start iexplore.exe "page to load"
ping localhost -n 10 > nul
taskkill /PID ?
where ? is the PID of the IE that gets opened but how can I get this? This needs to run as a .cmd file without any input from a user.
IE already supports automation, there is no point in finding and killing the correct process:
Set IE = CreateObject("InternetExplorer.Application")
IE.visible=true
IE.navigate "http://stackoverflow.com/"
while IE.Busy
WScript.Sleep 555
wend
IE.Quit
Save as .vbs (And run with wscript.exe from parent program/batch file)
use vbscript
Set objFS=CreateObject("Scripting.FileSystemObject")
Set objArgs = WScript.Arguments
strProcess = objArgs(0) 'argument, which is the process name
strComputer = "."
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
' call WMI service Win32_Process
Set colProcessList = objWMIService.ExecQuery("Select * from Win32_Process Where Name = '"&strProcess&"'")
t=0
For Each objProcess in colProcessList
' do some fine tuning on the process creation date to get rid of "." and "+"
s = Replace( objProcess.CreationDate ,".","")
s = Replace( objProcess.CreationDate ,"+","")
' Find the greatest value of creation date
If s > t Then
t=s
strLatestPid = objProcess.ProcessID
End If
Next
WScript.Echo "latest: " & t , strLatestPid
'Call WMI to terminate the process using the found process id above
Set colProcess = objWMIService.ExecQuery("Select * from Win32_Process where ProcessId =" & strLatestPid)
For Each objProcess in colProcess
objProcess.Terminate()
Next
usage:
c:\test>cscript //nologo kill.vbs "iexplore.exe"