问题
I'm writing a batch script which runs a few programs. As each program finishes what it's doing it waits for either the user to close it out, moving on to the next, or being closed by taskkill after a timeout of so many seconds. If I consider the main script as MAIN, the program as TASK and the timer as KILLER. The MAIN starts the TASK and KILLER at (about) the same time. TASK does what it's supposed to and KILLER waits 600 seconds before killing TASK. However if TASK were closed by the user it should kill the KILLER and return to MAIN without user interaction. However using ping or timeout I still have to wait for the timer to expire before the batch will actually close. I would like not to have my desktop littered with command windows that'll do nothing. Is there any way around this?
回答1:
You can use something like this
@echo off
setlocal enableextensions disabledelayedexpansion
start "" task.exe
call :timeoutProcess "task.exe" 300
start "" task.exe
call :timeoutProcess "task.exe" 300
exit /b
:timeoutProcess process timeout [leave]
rem process = name of process to monitor
rem timeout = timeout in seconds to wait for process to end
rem leave = 1 if process should not be killed on timeout
for /l %%t in (1 1 %~2) do (
timeout /t 1 >nul
tasklist | find /i "%~1" >nul || exit /b 0
)
if not "%~3"=="1" taskkill /f /im "%~1" >nul 2>nul
if %errorlevel% equ 128 ( exit /b 0 ) else ( exit /b 1 )
The timeout logic is moved to a subroutine that will wait until the process ends or the timeout is reached.
回答2:
Here's a vbs script.
It waits till a program exits, see's if it's notepad, then restarts notepad if it is. Change Win32_ProcessStopTrace
to Win32_ProcessStartTrace
for program starts, or Win32_ProcessTrace
for all starts and stops.
Console scripts are started like so. GUI scripts just execute the script direct. GUI scripts are invisible.
cscript "c:\somefolder\script.vbs"
To wait in a script use wscript.sleep 600000
(milliseconds).
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
wscript.echo objReceivedEvent.ProcessName
If lcase(objReceivedEvent.ProcessName) = lcase("Notepad.exe") then
WScript.echo "Process exited with exit code " & objReceivedEvent.ExitStatus
WshShell.Run "c:\Windows\notepad.exe", 1, false
End If
Loop
And this is how to start an invisible command window.
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run "cmd /k dir c:\windows\*.*", 0, false
来源:https://stackoverflow.com/questions/26553727/batch-taskkill-timeout-without-waiting-for-timer