Exit status of tasklist in batch file? - file

I am executing following command in a label inside a batch file:
tasklist.exe /FI "USERNAME eq %USERDOMAIN%\%USERNAME%" /FI "IMAGENAME eq %1" /FI "PID eq %2" 2>nul && echo errorl:%errorlevel%
%1 is process running and %2 is its PID.
Even if process and its PID matches or doesnt matches, I m getting "errorl:1" in o/p.
I am not sure whats wrong here. Any idea?

You could pipe tasklist through the find command and get an errorlevel off of it.
Example:
tasklist | find "firefox.exe"
echo Error level = %ERRORLEVEL%
REM If firefox is running, the errorlevel is set to 0
REM If firefox is not running, errorlevel is set to 1

In my opinion, you can't use errorlevel at all,
because tasklist always returns a 0 even if the pid isn't found.
I suppose, you have to parse the output of tasklist.
To fetch the output of a command, FOR /F is a good choice.
To avoid problems wth the quoting in the FOR /F, I build first a cmd variable which is expanded with delayed expansion to avoid any side effects of special characters.
#echo off
setlocal enableDelayedExpansion
set "cmd=tasklist.exe /FI "USERNAME eq %USERDOMAIN%\%USERNAME%" /FI "IMAGENAME eq %1" /FI "PID eq %2""
for /F "delims=*" %%p in ('!cmd! ^| findstr "%2" ') do (
echo found %%p
)

%variables% are expanded before executing the line, so %errorlevel% will expand to some old value. (The fact that the code after && executes at all is your clue that the command returned 0)
You options are:
Use %errorlevel% or the more correct IF errorlevel 1 ... on the next line
Call setlocal ENABLEDELAYEDEXPANSION first and then use !errorlevel!
Edit:
I guess tasklist is buggy and/or stupid when it comes to exit codes, I wrote some code that does not use the exit code at all:
#echo off
if "%~1"=="SOTEST" (
start calc
ping -n 2 localhost >nul
for /F "tokens=1,2 skip=3" %%A in ('tasklist /FI "IMAGENAME eq calc.exe"') do (
call "%~0" %%A %%B
)
call "%~0" dummy.exe 666
goto :EOF
)
goto main
:IsTaskRunning
setlocal ENABLEEXTENSIONS&set _r=0
>nul 2>&1 (for /F "tokens=1,2" %%A in ('tasklist /FO LIST %*') do (
if /I "%%~A"=="PID:" set _r=1
))
endlocal&set IsTaskRunning=%_r%&goto :EOF
:main
call :IsTaskRunning /FI "USERNAME eq %USERDOMAIN%\%USERNAME%" /FI "IMAGENAME eq %1" /FI "PID eq %2"
if %IsTaskRunning% gtr 0 (echo.%1:%2 is running) else (echo.%1:%2 is NOT running)
Run it as test.cmd SOTEST and it prints:
calc.exe:4852 is running
dummy.exe:666 is NOT running

Easy solution to this, given that
1) you can't get an errorlevel from tasklist, and
2) you can't directly pipe it to a FIND
Just write it to a file using output redirection and use FIND to check the file. Each time this is run, it will overwrite the previous iteration, so no need to even do any file cleanup. Amazing how many bat/cmd file limitations can be overcome with a simple scratchpad file!!
:TOP
rem swap rems from good to bad to test
set findvar=goodfile.exe
rem set findvar=badfile.exe
set scratchfile=scratch.txt
tasklist /fi "status eq running" /fi "imagename eq %findvar%">%scratchfile%
type %scratchfile%
pause
echo Looking for %findvar%
find "%findvar%" %scratchfile%
echo Error level = %errorlevel%
pause
IF errorlevel 1 GOTO BAD
IF errorlevel 0 GOTO GOOD
GOTO OTHER
:BAD
echo Errrlevel 1 - task not found
PAUSE
GOTO TOP
:GOOD
echo Errrlevel 0 - task is running
pause
GOTO TOP
:OTHER
echo something else ????? you blew it somewhere!

tasklist returns 0 when executes successfully:
If you're looking for existence of some process or some attribute of a process, one method is to supply the attributes to tasklist and check if it returned any process names. If no matching processes are found, it'll return "INFO: No tasks are running which match the specified criteria."
The result of tasklist may be checked either via for command embedding (and parse command output) or filter via find or findstr, which accepts regular expressions & wildcards.
eg. To check if the any process is running with following criteria:
tasklist.exe /FI "USERNAME eq %USERDOMAIN%\%USERNAME%" /FI "IMAGENAME eq %1" /FI "PID eq %2" | find /v "No task" >nul && (echo process exists) || (echo na man).
Above method can also find if any document (window) is open, in addition to the underlying process, like "firefox.exe".
eg. close high speed vpn ad window if/when it pops up without notice:
tasklist /fi "windowtitle eq High-Speed*" | find /v "No task" >nul && (taskkill /fi "windowtitle eq High-Speed*")
Tested on Win 10 CMD

Related

How to check if multiple processes is running via a batch script

I got this script form stackoverflow and its working for me . and because i can't comment there im asking my question in new post.
This script check if exe is running in tasklist:
#echo off
SETLOCAL EnableExtensions
set EXE=notepad.exe
FOR /F %%x IN ('tasklist /NH /FI "IMAGENAME eq %EXE%"') DO IF %%x == %EXE% goto ProcessFound
goto ProcessNotFound
:ProcessFound
echo %EXE% is running
goto END
:ProcessNotFound
echo %EXE% is not running
goto END
:END
echo Finished!
The question is :
How can I check multiple process is running on tasklist?
for example exe1 and exe2
thanks in advance
From your comments; if all you want to do is run a third executable if neither of two other executables are running then here is a single line complete batch file example for you:
#TaskList/NH /FI "Status Eq Running"|FindStr/IC:"first.exe" /C:"second.exe">Nul||Start "" "X:\PathTo\third.exe"
Note:Do not change anything other than the names first, second and X:\PathTo\third; all double quotes, ", are necessary!
I've organised your code a bit differently so it's easier to follow and has more functionality. Note: This means it will be slower if you have lots of processes. If you wish to only see if it exists, I'd recommend using findstr.
I've added REM (batch-file equivalent for comments) explaining what each section does.
#echo off
REM Create variable's for exe's and their counter
set exe_1=notepad.exe
set exe_2=explorer.exe
set exe_3=chrome.exe
set "count_1=0"
set "count_2=0"
set "count_3=0"
REM Store all tasklist findings in a temp file
>tasklist.temp (
tasklist /NH /FI "IMAGENAME eq %exe_1%"
tasklist /NH /FI "IMAGENAME eq %exe_2%"
tasklist /NH /FI "IMAGENAME eq %exe_3%"
)
REM Go through all finds and count for each task instance
for /f %%x in (tasklist.temp) do (
if "%%x" EQU "%exe_1%" set /a count_1+=1
if "%%x" EQU "%exe_2%" set /a count_2+=1
if "%%x" EQU "%exe_3%" set /a count_3+=1
)
REM Use variables to see instance count
Echo %exe_1%: %count_1%
Echo %exe_2%: %count_2%
Echo %exe_3%: %count_3%
REM Use GTR 0 to see if process exists
if %count_1% GTR 0 if %count_2% GTR 0 Echo Both notepad and explorer are open
REM Delete temp file once finished. (NB: Will still exist if your code crashes)
del tasklist.temp
Conditional if-statements
As requested from your comment:
if %count_1% GTR 0 if %count_2% GTR 0 (
Echo Both notepad and explorer are open
goto :finish
)
if %count_1% GTR 0 (
Echo Only notepad is open
goto :finish
)
if %count_2% GTR 0 (
Echo Only explorer is open
goto :finish
)
REM Not Finished means none are open
Echo Neither notepad nore explorer are open
:finish
Here is my solution, keeping a similar structure to that of your sample script. Modify the EXE variable to reference the IMAGENAMEs you're interested in checking.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET EXE=(notepad.exe wordpad.exe winword.exe thunderbird.exe outlook.exe greenshot.exe)
FOR %%i IN %EXE% DO (
TASKLIST /NH /FI "IMAGENAME EQ %%i" 2>NUL | FIND /I /N "%%i">NUL
IF !ERRORLEVEL! EQU 0 ( CALL :ProcessFound %%i ) ELSE ( CALL :ProcessNotFound %%i )
)
ECHO Finished^^!
EXIT /B 0
:ProcessFound
ECHO %1 is running
EXIT /B 0
:ProcessNotFound
ECHO %1 is not running
EXIT /B 1
If you want to start the program when the process is not found, insert START %1 after ECHO %1 is not running.

Batch file that identifies if a named window is open, and then closes it

I have been using the following script to check if a particular named window is open.
I got it from this thread:-
How do you test if a window (by title) is already open from the command prompt?
ideally I will expand the else part to close the window if it is found to be open.
#For /f "Delims=:" %A in ('tasklist /v /fi "WINDOWTITLE eq test.bat - Notepad"') do #if %A==INFO (echo Prog not running) else SET "BREX=Awesome" &echo %BREX%
Unfortunately when I run this script it returns three instances of my else string?
Is there any way to reduce this down to returning one instance?
You could use findstr instead. You're getting multiple lines of output as you're looping over each line of output
tasklist /v /fi "WINDOWTITLE eq test.bat - Notepad" | findstr /C:"No tasks are running"
if %errorlevel% NEQ 0 (
echo awesome
) else (
echo Prog not running
)
If you really want to do this with one line from the cmd prompt you can do this.
cmd /v:on /c "#For /f "Delims=:" %A in ('tasklist /v /nh /fi "WINDOWTITLE eq test.bat - Notepad"') do #if %A==INFO (echo Prog not running) else (SET "BREX=Awesome") &echo !BREX!"
Or use some conditional execution.
tasklist /v /nh /fi "WINDOWTITLE eq test.bat - Notepad" |findstr /B /C:"INFO: No tasks are running">nul && (echo Program not running) || (echo Awesome)

Find command not working when used in pipe

echo off
:loop
tasklist /fi "imagename eq Notepad.exe" | find "INFO:" > nul
if errorlevel 1 goto loop
wordpad.exe
This is not working in XP. It works fine in Windows 7.
When notepad.exe does not exist in the task list, tasklist /fi "imagename eq Notepad.exe" dumps the "INFO:" line to stderr in Windows XP. You could redirect stderr to stdout with 2>&1, but it's easier just to find /i "notepad" instead.
On a side note, instead of doing if errorlevel 1 you could use conditional execution.
#echo off
setlocal
:loop
rem // Output nothing for the following code block.
>NUL 2>NUL (
rem // Make sure notepad is not running before continuing.
tasklist /fi "imagename eq notepad.exe" | find /i "notepad" && (
rem // Notepad is in tasklist. Sleep 1 second, then check again.
timeout /t 1 /nobreak || ping -n 2 localhost
goto loop
)
)
wordpad.exe

Batch File to Check for Running Program and Start if not Running is not working

I have been trying to get this batch file to work but keep running into issues. I think I am close but need help getting this working. When the script runs I get Find: Parameter format not correct.
I am running this on a Windows Server 2008 R2 Standard.
#echo off
tasklist /FI "IMAGENAME eq program.exe" | find /i “program.exe"
IF ERRORLEVEL 2 GOTO NEXTPROGRAM
IF ERRORLEVEL 1 GOTO LAUNCHPROGRAM
:NEXTPROGRAM
goto SMADMIN
:LAUNCHPROGRAM
start "" "C:\path\to\program.exe"
goto SMADMIN
:SMADMIN
tasklist /FI "IMAGENAME eq program1.exe" | find /i “program1.exe"
IF ERRORLEVEL 2 GOTO NEXTPROGRAM2
IF ERRORLEVEL 1 GOTO LAUNCHPROGRAM2
:NEXTPROGRAM2
goto COMPLETE
:LAUNCHPROGRAM2
start "" "C:\path\to\program1.exe"
goto COMPLETE
You can check whether the exe is running this way:
SET running=0
FOR /f "tokens=*" %%A IN ('tasklist^ /v^| findstr /i /c:"program.exe"') DO SET running=1
IF %running%=1 GOTO NEXTPROGRAM
IF %running%=0 GOTO LAUNCHPROGRAM
Afterwards you just have to check if the %ProgramRunning% is set to 1.
Don't forget to reset the %running% flag back to 0 before reusing it.

Compare number of a specific process to a number

I get the number of a specific process with the help of this thread:
How to count amount of processes with identical name currently running, using a batchfile
I hope to assign the result of this command to a variable, then compare the variable with a number. My code is listed as below:
#echo off
setlocal enabledelayedexpansion
set procName=chrome.exe
set a=tasklist /FI "IMAGENAME eq %procName%" 2>NUL | find /I /C "%procName%"
if !a! equ 1 (
echo !a!
echo %procName% starts to run...
) else (
echo !a!
echo %procName% has not run!
)
Here I got '0' for
'set a=tasklist /FI "IMAGENAME eq %procName%" 2>NUL | find /I /C "%procName%"' command.
It also gives me "Echo closed" hint for 'echo !a!'.
FYI, when running the following command in cmd
tasklist /FI "IMAGENAME eq chrome.exe" 2>NUL | find
/c /i "chrome.exe"
set a=tasklist /FI "IMAGENAME eq chrome.exe" 2>NUL
| find /c /i "chrome.exe"
the output is 16 and 0 respectively.
What's the reason? How could I assign the result of a command to a variable? How to compare the variable to a number?
Thank you so much!
Well, set a=tasklist /FI "IMAGENAME eq chrome.exe" 2>nul | find /c "chrome.exe" does not work for me either. Which is good because I don't know how that was supposed to work.
I believe that this will be faster, because it doesn't have the overhead of FIND.EXE and writing, reading and deleting proc_temp.
set a=0
for /f "skip=3" %%x in ('tasklist /FI "IMAGENAME eq chrome.exe"') do set /a a=a+1
echo Total chrome.exe tasks running: %a%
EDIT: I just discovered that set /a does not require expanded variables and so removed the setlocal and endlocal commands and altered the set /a syntax.
after this line in environment a has the pid of the process sought
for /F "tokens=1,2,*" %%a in ('tasklist /fi "imagename eq %procName%"') do if !%%a!==!%procName%! set a=%b
I think I found a solution:
tasklist /fi "imagename eq %procName%" 2>nul | findstr /i %procName% | find /c /v "">proc_temp
set /p current_num= < proc_temp
echo !current_num!
Also I think the code can be simplified. Hope some of you can give brief version :)

Resources