How to check if a process is running via a batch script
How can I check if an application is running from a batch (well cmd) file?
I need to not launch another instance if a program is already running. (I can't change the app to make it single instance only.)
Also the application could be running as any user.
Solution 1:
Another possibility I came up with, which does not require to save a file, inspired by using grep is:
tasklist /fi "ImageName eq MyApp.exe" /fo csv 2>NUL | find /I "myapp.exe">NUL
if "%ERRORLEVEL%"=="0" echo Program is running
-
/fi ""
defines a filter of apps to find, in our case it's the *.exe name -
/fo csv
defines the output format, csv is required because by default the name of the executable may be truncated if it is too long and thus wouldn't be matched byfind
later. -
find /I
means case-insensitive matching and may be omitted
See the man page of the tasklist command for the whole syntax.
Solution 2:
Here's how I've worked it out:
tasklist /FI "IMAGENAME eq notepad.exe" /FO CSV > search.log
FOR /F %%A IN (search.log) DO IF %%~zA EQU 0 GOTO end
start notepad.exe
:end
del search.log
The above will open Notepad if it is not already running.
Edit: Note that this won't find applications hidden from the tasklist. This will include any scheduled tasks running as a different user, as these are automatically hidden.
Solution 3:
I like Chaosmaster's solution! But I looked for a solution which does not start another external program (like find.exe or findstr.exe). So I added the idea from Matt Lacey's solution, which creates an also avoidable temp file. At the end I could find a fairly simple solution, so I share it...
SETLOCAL EnableExtensions
set EXE=MyProg.exe
FOR /F %%x IN ('tasklist /NH /FI "IMAGENAME eq %EXE%"') DO IF NOT %%x == %EXE% (
echo %EXE% is Not Running
)
This is working for me nicely...
The above is an edit. The original code apparently had a GOTO in it, which someone in the comments thought uncouth.
Spaces
If you are concerned that the program name may have spaces in it then you need to complicate the code very slightly:
SETLOCAL EnableExtensions
set EXE=My Prog.exe
FOR /F %%x IN ("%EXE%") do set EXE_=%%x
FOR /F %%x IN ('tasklist /NH /FI "IMAGENAME eq %EXE%"') DO IF NOT %%x == %EXE_% (
echo %EXE% is Not Running
)
The original code will work fine whether or not other running processes have spaces in their names. The only concern is whether or not the process we are targeting has space(s).
ELSE
Keep in mind that if you add an ELSE clause then it will be executed once for every instance of the application that is already running. There is no guarantee that there be only a single instance running when you run this script.
Should you want one anyway, either a GOTO or a flag variable is indicated.
Ideally the targeted application should already mutex itself to prevent multiple instances, but that is a topic for another SO question and is not necessarily applicable to the subject of this question.
GOTO again
I do agree with the "ELSE" comment. The problem with the GOTO-less solution, that is may run the condition part (and the ELSE part) multiple times, so it is a bit messy as it has to quit the loop anyway. (Sorry, but I do not deal with the SPACE issue here, as it seems to be pretty rare and a solution is shown for it)
SETLOCAL EnableExtensions
SET EXE=MyProg.exe
REM for testing
REM SET EXE=svchost.exe
FOR /F %%x IN ('tasklist /NH /FI "IMAGENAME eq %EXE%"') DO IF NOT %%x == %EXE% (
ECHO %EXE% is Not Running
REM This GOTO may be not necessary
GOTO notRunning
) ELSE (
ECHO %EXE is running
GOTO Running
)
...
:Running
REM If Running label not exists, it will loop over all found tasks
Solution 4:
The suggestion of npocmaka to use QPROCESS instead of TASKLIST is great but, its answer is so big and complex that I feel obligated to post a quite simplified version of it which, I guess, will solve the problem of most non-advanced users:
QPROCESS "myprocess.exe">NUL
IF %ERRORLEVEL% EQU 0 ECHO "Process running"
The code above was tested in Windows 7, with a user with administrator rigths.