I trying to do an infinite loop to check if node.exe is using over some number of memory. Like this:
:loop2
sleep
taskkill /f /im node.exe "memusage gt 85000" > nul
timeout /t 30
GOTO loop2
But how can I break this infinite loop, when the taskkill is processed?
set "Myprocess=node.exe"
:test
tasklist | find /i "%MyProcess%">nul && Taskkill /F /IM "%MyProcess%" & exit/b
timeout /t 30
goto:test
:loop2
sleep
( taskkill /f /im node.exe /fi "memusage gt 85000" | find "PID" >nul ) || (
timeout /t 30
GOTO loop2
)
Check the output of the command to determine if a process has been killed.
Edited I thought the PID string was locale independent, but it is not. If needed, the find command can be replaced by
find /i "node.exe" > nul
to search for the name of the process in the output, or
findstr /r /c:" [1-9][0-9]*[02468][\., ]" > nul
to search for the presence of a process ID (note: all process IDs are multiple of 4)
Works for me, for any locale.
:loop2
sleep
set _tk=
for /f "skip=1 delims=, tokens=2" %%A in ('tasklist /fi "imagename eq node.exe" /fi "memusage gt 85000" /fo csv') do (
taskkill /f /pid %%~A
set _tk=1
)
if not "%_tk%"=="1" (
timeout /t 30
GOTO loop2
)
Another approach would be to use TASKLIST to see if a matching image is running. This code is -not- tested.
:loop2
SET TEMPFILE=%TEMP%\tk_%RANDOM%.tmp
TASKLIST /FI "IMAGENAME eq cmd.exe" /FI "MEMUSAGE gt 9000" >"%TEMPFILE%"
SET /P TKI=<"%TEMPFILE%"
IF "%TKI%" EQU "INFO: No tasks are running which match the specified criteria." (GOTO OutOfIt)
taskkill /f /im node.exe "memusage gt 85000" > nul
timeout /t 30
GOTO loop2
:OutOfIt
IF EXISTS "%TEMPFILE%" (DEL "%TEMPFILE%")
EXIT /B
taskkill /IM notepad.exe /FI "memusage gt 999" |find "SUCCESS" &&GOTO :BREAKOUT
Related
I have this batch code and its working perfectly well, BUT:
every line take ~60 seconds to execute and I'm wondering, if I could do this faster...
Also the if Statements.. I want to check, if every Window is closed, and if so, I want to execute something. But if at least one window is still open, then it should check it again.
:loop
for /f %%i in ('tasklist /v /fi "WINDOWTITLE eq %server1%" /FO Table') do set #1=%%i
for /f %%i in ('tasklist /v /fi "WINDOWTITLE eq %server2%" /FO Table') do set #2=%%i
for /f %%i in ('tasklist /v /fi "WINDOWTITLE eq %server3%" /FO Table') do set #3=%%i
for /f %%i in ('tasklist /v /fi "WINDOWTITLE eq %server4%" /FO Table') do set #4=%%i
for /f %%i in ('tasklist /v /fi "WINDOWTITLE eq %server5%" /FO Table') do set #5=%%i
for /f %%i in ('tasklist /v /fi "WINDOWTITLE eq %server6%" /FO Table') do set #6=%%i
if not %#1%==cmd.exe (
if not %#2%==cmd.exe (
if not %#3%==cmd.exe (
if not %#4%==cmd.exe (
if not %#5%==cmd.exe (
if not %#6%==cmd.exe (
goto backup
)
)
)
)
)
) else (
echo back to loop
goto openWindow
)
Let me suggest a slightly different approach. Instead of all those if statements, you can just loop whenever one of the tasks exist:
:wait
timeout 1 >nul
for %%a in (%server1% %server2% %server3% %server4% %server5% %server6%) do (
tasklist /nh /fi "windowtitle eq %%a" |find " " >nul && goto :wait
)
echo all closed.
or
setlocal enabledelayedexpansion
:wait
timeout 1 >nul
for /l %%a in (1,1,6) do (
tasklist /nh /fi "windowtitle eq !server%%a!" |find " " >nul && goto :wait
)
echo all closed.
Note: find " " looks for two consecutive spaces, not a TAB)
If you choose your window titles wisely, you don't even need a for loop:
:wait
timeout 1 >nul
tasklist /nh /fi "windowtitle eq MySubWindow*" |find " " >nul && goto :wait
echo all closed.
where the window titles all start with a fixed string (MySubWindow here), like MySubWindow-1, MySubWindow-2 etc. (yes, tasklist is able to use a wildcard - but only at the end of the string). This is basically "if any window exists with a title that starts with MySubWindow then loop"
little optimization of Stephan answer.
This execute faster.
:wait
timeout 1 >nul
for %%a in (%server1% %server2% %server3% %server4% %server5% %server6%) do (
if not defined v%%a tasklist /nh /fi "windowtitle eq %%a" |find " " >nul && goto :wait
set v%%a=done
)
echo all closed.
You have not explained how your 6 Batch files are "open", but if they are open via START command, then there is a much simpler way to do the same:
(
start call batch1.bat
start call batch2.bat
start call batch3.bat
start call batch4.bat
start call batch5.bat
start call batch6.bat
) | pause
echo All 6 Batch files are closed
The previous code run the 6 Batch files in parallel and then the control flow is stopped at the pause command. When all the 6 Batch files terminates, this program continue.
Note that there is not any Batch code that check if the procesess ends; this is done automatically by the Operating System. In this way, the wait state of this program does not waste any CPU time. For a further explanation, see this answer
Without being able to test this, perhaps it would be quicker to run just one tasklist command per loop:
#Echo Off
SetLocal EnableExtensions
:Loop
For /F Tokens^=17^ Delims^=^" %%G In (
'%SystemRoot%\System32\tasklist.exe /Fi "ImageName Eq cmd.exe" /Fo CSV /NH /V 2^>NUL'
) Do Set /P "=%%G" 0<NUL | %SystemRoot%\System32\findstr.exe /I ^
"\<%server1%\> \<%server2%\> \<%server3%\> \<%server4%\> \<%server5%\> \<%server6%\>" 1>NUL && GoTo Loop
:Backup
The findstr.exe options may need to be adjusted depending upon the content of those variables.
I have a process called "Ulti.exe". Due to my project requirements I have more than one copy of it running at any one time. If the number of copies of "Ulti.exe" drop below 3, I need to kill all the processes and restart them again.
How can I save the TaskList count into a variable? Currently, the following command:
TaskList | FIND /C "Ulti.exe"
if typed into cmd.exe returns me the number of "Ulti.exe" processes accurately. How can I incorporate this into a .bat file so I can use this number as a variable?
Get the output of a command with a for /f loop:
for /f %%a in ('TaskList ^| FIND /I /C "Ulti.exe"') do set count=%%a
echo %count%
While counting you can as well gather the PIDs to ease killing them if needed
:: Q:\Test\2018\11\02\SO_53115422.cmd
#Echo off & SetLocal EnableExtensions EnableDelayedExpansion
Set "Prog=Ulti.exe"
::Set "Prog=firefox.exe"
Set "Count="
Set "PIDs="
for /f "tokens=2" %%A in (
'TaskList /FI "IMAGENAME eq %Prog%" ^| Findstr /i "%Prog%"'
) do (
Set /A Count+=1
Set PIDs=!PIDs! /PID %%A
)
If defined Count (
If !Count! lss 3 (
echo taskkill %PIDs%
echo restart %Prog%
) else (
echo %Prog% running %Count% times [%PIDs%]
)
) else (
Echo %Prog% not running
Echo start %Prog%
)
Sample output:
> SO_53115422
Ulti.exe running 5 times [ /PID 3664 /PID 10332 /PID 3544 /PID 8996 /PID 11192]
> SO_53115422
Ulti.exe not running
start Ulti.exe
> SO_53115422
taskkill /PID 8056 /PID 2704
restart Ulti.exe
The taskkill command is only echoed while testing
I'm trying to realize a batch file that checks if a program is running and if not launch it, and more if is it launched more than one time close all the duplicate instances.
this is the code I implemented using also some tips found here in stackoverflow:
:check
tasklist /fi "imagename eq notepad.exe" /nh |find /i /c "notepad.exe" > "%temp%\variable.txt" #here I count how many instances are running
set /p value=<"%temp%\variable.txt" #and save the value in the variable.txt file
##check and choose action
if %value% equ nul goto none
if %value% geq 2 goto more
if %value% equ 1 goto one
:more
for /f "tokens=2" %%x in ('tasklist ^| findstr notepad.exe') do set PIDTOKILL=%%x
taskkill /F /PID %PIDTOKILL%
goto check
:none
start notepad.exe
goto check
:one
timeout 10 > nul
goto check
But some strange behavior happens when I test it...
if only one instances is running all fine, but if I close notepad while the batch file is running the routine goes to the :more label apparently without any reason...what I'm doing wrong?
thanks for any help
stupid error ... this is the working code:
:check
timeout 10 > nul
tasklist /fi "imagename eq notepad.exe" /nh |find /i /c "notepad.exe" > "%temp%\variable.txt"
set /p value=<"%temp%\variable.txt"
if %value% equ 0 goto none
if %value% geq 2 goto more
if %value% equ 1 goto check
:more
for /f "tokens=2" %%x in ('tasklist ^| findstr notepad.exe') do set PIDTOKILL=%%x
taskkill /F /PID %PIDTOKILL%
goto check
:none
start notepad.exe
goto check
I'm making a batch that checks whether the process is active and if it is closed it ... the point is that when the process has spaces in the name it is not found.
Set "EXE=Process name.exe">nul 2>&1
FOR /F %%x IN ('tasklist /NH /FI "IMAGENAME eq %EXE%"') DO IF %%x == %EXE% Taskkill /F /IM "%EXE%" >nul 2>&1
This should handle the spaces in the code, depending on what the first tasklist prints:
Set "EXE=Process name.exe"
FOR /F "delims=" %%x IN ('tasklist /NH /FI "IMAGENAME eq %EXE%"') DO IF /i "%%x" == "%EXE%" Taskkill /F /IM "%EXE%" >nul 2>&1
This is another way of doing it:
Set "EXE=Process name.exe"
tasklist|find /i "%EXE%" >nul && Taskkill /F /IM "%EXE%" >nul 2>&1
and this is functionally equivalent: it will only kill the task if it exists.
Set "EXE=Process name.exe"
Taskkill /F /IM "%EXE%" >nul 2>&1
wmic process where name="Process name.exe" get Name,ProcessId
?
Try, putting quotes around your process name like
Set EXE="Process name.exe" >nul 2>&1
Hi guys is it possible to detect application crash with .bat code then restart that with .bat.
pleas give me a method.
i write a code to start and restart application but i don't know how to detect crashed application.
thank you
#echo off
cls
echo Protecting NpAPIserver from crashes...
title NpAPIServer Watchdog
tasklist /FI "aplication.exe" | find /i "aplication.exe"
for /f "tokens=2" %%x in ('tasklist ^| findstr aplication.exe') do set PIDTOKILL=%%x
IF ERRORLEVEL 2 GOTO KILLPROGRAM
IF ERRORLEVEL 1 GOTO LAUNCHPROGRAM
:KILLPROGRAM
taskkill /F /PID %PIDTOKILL%
goto LAUNCHPROGRAM
:LAUNCHPROGRAM
cd "c:\np"
start aplication.exe
goto WAITLUNCH
:WAITLUNCH
timeout /T 300
for /f "tokens=2" %%x in ('tasklist ^| findstr aplication.exe') do set PIDTOKILL=%%x
taskkill /F /PID %PIDTOKILL%
goto LAUNCHPROGRAM
(tasklist /FI "Status eq not responding"|find "lol.exe")&&rem not reponding