How to check if a process is running via a batch script

WindowsCommand LineBatch File

Windows Problem Overview


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.

Windows Solutions


Solution 1 - Windows

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 by find 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 - Windows

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 - Windows

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 - Windows

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.

Solution 5 - Windows

TASKLIST | FINDSTR ProgramName || START "" "Path\ProgramName.exe"

Solution 6 - Windows

Under Windows you can use Windows Management Instrumentation (WMI) to ensure that no apps with the specified command line is launched, for example:

wmic process where (name="nmake.exe") get commandline | findstr /i /c:"/f load.mak" /c:"/f build.mak" > NUL && (echo THE BUILD HAS BEEN STARTED ALREADY! > %ALREADY_STARTED% & exit /b 1)

Solution 7 - Windows

TrueY's answer seemed the most elegant solution, however, I had to do some messing around because I didn't understand what exactly was going on. Let me clear things up to hopefully save some time for the next person.

TrueY's modified Answer:

::Change the name of notepad.exe to the process .exe that you're trying to track
::Process names are CASE SENSITIVE, so notepad.exe works but Notepad.exe does NOT
::Do not change IMAGENAME
::You can Copy and Paste this into an empty batch file and change the name of
::notepad.exe to the process you'd like to track
::Also, some large programs take a while to no longer show as not running, so
::give this batch a few seconds timer to avoid a false result!!

@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!

Anyway, I hope that helps. I know sometimes reading batch/command-line can be kind of confusing sometimes if you're kind of a newbie, like me.

Solution 8 - Windows

I use PV.exe from http://www.teamcti.com/pview/prcview.htm installed in Program Files\PV with a batch file like this:

@echo off
PATH=%PATH%;%PROGRAMFILES%\PV;%PROGRAMFILES%\YourProgram
PV.EXE YourProgram.exe >nul
if ERRORLEVEL 1 goto Process_NotFound
:Process_Found
echo YourProgram is running
goto END
:Process_NotFound
echo YourProgram is not running
YourProgram.exe
goto END
:END

Solution 9 - Windows

The answer provided by Matt Lacey works for Windows XP. However, in Windows Server 2003 the line

 tasklist /FI "IMAGENAME eq notepad.exe" /FO CSV > search.log

returns

> INFO: No tasks are running which match the specified criteria.

which is then read as the process is running.

I don't have a heap of batch scripting experience, so my soulution is to then search for the process name in the search.log file and pump the results into another file and search that for any output.

tasklist /FI "IMAGENAME eq notepad.exe" /FO CSV > search.log

FINDSTR notepad.exe search.log > found.log

FOR /F %%A IN (found.log) DO IF %%~zA EQU 0 GOTO end

start notepad.exe

:end

del search.log
del found.log

I hope this helps someone else.

Solution 10 - Windows

I like the WMIC and TASKLIST tools but they are not available in home/basic editions of windows.Another way is to use QPROCESS command available on almost every windows machine (for the ones that have terminal services - I think only win XP without SP2 , so practialy every windows machine):

@echo off
:check_process
setlocal
if "%~1" equ "" echo pass the process name as forst argument && exit /b 1
:: first argument is the process you want to check if running
set process_to_check=%~1
:: QPROCESS can display only the first 12 symbols of the running process
:: If other tool is used the line bellow could be deleted
set process_to_check=%process_to_check:~0,12%

QPROCESS * | find /i "%process_to_check%" >nul 2>&1 && (
	echo process %process_to_check%  is running
) || (
	echo process %process_to_check%  is not running
)
endlocal

QPROCESS command is not so powerful as TASKLIST and is limited in showing only 12 symbols of process name but should be taken into consideration if TASKLIST is not available.

More simple usage where it uses the name if the process as an argument (the .exe suffix is mandatory in this case where you pass the executable name):

@echo off
:check_process
setlocal
if "%~1" equ "" echo pass the process name as forst argument && exit /b 1
:: first argument is the process you want to check if running
:: .exe suffix is mandatory
set "process_to_check=%~1"


QPROCESS "%process_to_check%" >nul 2>&1 && (
    echo process %process_to_check%  is running
) || (
    echo process %process_to_check%  is not running
)
endlocal

The difference between two ways of QPROCESS usage is that the QPROCESS * will list all processes while QPROCESS some.exe will filter only the processes for the current user.

Using WMI objects through windows script host exe instead of WMIC is also an option.It should on run also on every windows machine (excluding the ones where the WSH is turned off but this is a rare case).Here bat file that lists all processes through WMI classes and can be used instead of QPROCESS in the script above (it is a jscript/bat hybrid and should be saved as .bat):

@if (@X)==(@Y) @end /* JSCRIPT COMMENT **


@echo off
cscript //E:JScript //nologo "%~f0"
exit /b

************** end of JSCRIPT COMMENT **/


var winmgmts = GetObject("winmgmts:\\\\.\\root\\cimv2");
var colProcess = winmgmts.ExecQuery("Select * from Win32_Process");
var processes =  new Enumerator(colProcess);
for (;!processes.atEnd();processes.moveNext()) {
	var process=processes.item();
	WScript.Echo( process.processID + "   " + process.Name );
}

And a modification that will check if a process is running:

@if (@X)==(@Y) @end /* JSCRIPT COMMENT **


@echo off
if "%~1" equ "" echo pass the process name as forst argument && exit /b 1
:: first argument is the process you want to check if running
set process_to_check=%~1

cscript //E:JScript //nologo "%~f0" | find /i "%process_to_check%" >nul 2>&1 && (
    echo process %process_to_check%  is running
) || (
    echo process %process_to_check%  is not running
)

exit /b

************** end of JSCRIPT COMMENT **/


var winmgmts = GetObject("winmgmts:\\\\.\\root\\cimv2");
var colProcess = winmgmts.ExecQuery("Select * from Win32_Process");
var processes =  new Enumerator(colProcess);
for (;!processes.atEnd();processes.moveNext()) {
    var process=processes.item();
    WScript.Echo( process.processID + "   " + process.Name );
}

The two options could be used on machines that have no TASKLIST.

The ultimate technique is using MSHTA . This will run on every windows machine from XP and above and does not depend on windows script host settings. the call of MSHTA could reduce a little bit the performance though (again should be saved as bat):

@if (@X)==(@Y) @end /* JSCRIPT COMMENT **
@echo off

setlocal
if "%~1" equ "" echo pass the process name as forst argument && exit /b 1
:: first argument is the process you want to check if running

set process_to_check=%~1


mshta "about:<script language='javascript' src='file://%~dpnxf0'></script>" | find /i "%process_to_check%" >nul 2>&1 && (
    echo process %process_to_check%  is running
) || (
    echo process %process_to_check%  is not running
)
endlocal
exit /b
************** end of JSCRIPT COMMENT **/


   var fso= new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1);

   
   var winmgmts = GetObject("winmgmts:\\\\.\\root\\cimv2");
   var colProcess = winmgmts.ExecQuery("Select * from Win32_Process");
   var processes =  new Enumerator(colProcess);
   for (;!processes.atEnd();processes.moveNext()) {
    var process=processes.item();
    fso.Write( process.processID + "   " + process.Name + "\n");
   }
   close();

Solution 11 - Windows

I don't know how to do so with built in CMD but if you have grep you can try the following:

tasklist /FI "IMAGENAME eq myApp.exe" | grep myApp.exe
if ERRORLEVEL 1 echo "myApp is not running"

Solution 12 - Windows

Just mentioning, if your task name is really long then it won't appear in its entirety in the tasklist result, so it might be safer (other than localization) to check for the opposite.

Variation of this answer:

:: in case your task name is really long, check for the 'opposite' and find  the message when it's not there
tasklist /fi "imagename eq yourreallylongtasknamethatwontfitinthelist.exe" 2>NUL | find /I /N "no tasks are running">NUL
if "%errorlevel%"=="0" (
	echo Task Found
) else (
	echo Not Found Task
)

Solution 13 - Windows

I needed a solution with a retry. This code will run until the process is found and then kill it. You can set a timeout or anything if you like.

Notes:

  • The ".exe" is mandatory
  • You could make a file runnable with parameters, version below
	:: Set programm you want to kill
	:: Fileextension is mandatory
	SET KillProg=explorer.exe

	:: Set waiting time between 2 requests in seconds
	SET /A "_wait=3"
	
	:ProcessNotFound
		tasklist /NH /FI "IMAGENAME eq %KillProg%" | FIND /I "%KillProg%"
		IF "%ERRORLEVEL%"=="0" (
			TASKKILL.EXE /F /T /IM %KillProg%
		) ELSE (
			timeout /t %_wait%
			GOTO :ProcessNotFound
		)

taskkill.bat:

	:: Get program name from argumentlist
	IF NOT "%~1"=="" (
		SET "KillProg=%~1"
	) ELSE (
		ECHO Usage: "%~nx0" ProgramToKill.exe & EXIT /B
	)

	:: Set waiting time between 2 requests in seconds
	SET /A "_wait=3"
	
	:ProcessNotFound
		tasklist /NH /FI "IMAGENAME eq %KillProg%" | FIND /I "%KillProg%"
		IF "%ERRORLEVEL%"=="0" (
			TASKKILL.EXE /F /T /IM %KillProg%
		) ELSE (
			timeout /t %_wait%
			GOTO :ProcessNotFound
		)

Run with .\taskkill.bat ProgramToKill.exe

Solution 14 - Windows

If you have more than one .exe-file with the same name and you only want to check one of them (e.g. you care about C:\MyProject\bin\release\MyApplication.exe but not C:\MyProject\bin\debug\MyApplication.exe) then you can use the following:

@echo off

set "workdir=C:\MyProject\bin\release"
set "workdir=%workdir:\=\\%"

setlocal enableDelayedExpansion
for /f "usebackq tokens=* delims=" %%a in (`
    wmic process  where 'CommandLine like "%%!workdir!%%" and not CommandLine like "%%RuntimeBroker%%"'   get CommandLine^,ProcessId  /format:value
`) do (
    for /f "tokens=* delims=" %%G in ("%%a")  do (
        if "%%G" neq "" (
rem            echo %%G
            set "%%G"
rem            echo !ProcessId!
            goto :TheApplicationIsRunning
        )
    )
) 

echo The application is not running
exit /B

:TheApplicationIsRunning
echo The application is running
exit /B

Solution 15 - Windows

I'm assuming windows here. So, you'll need to use WMI to get that information. Check out The Scripting Guy's archives for a lot of examples on how to use WMI from a script.

Solution 16 - Windows

I used the script provided by Matt (2008-10-02). The only thing I had trouble with was that it wouldn't delete the search.log file. I expect because I had to cd to another location to start my program. I cd'd back to where the BAT file and search.log are, but it still wouldn't delete. So I resolved that by deleting the search.log file first instead of last.

del search.log

tasklist /FI "IMAGENAME eq myprog.exe" /FO CSV > search.log

FOR /F %%A IN (search.log) DO IF %%-zA EQU 0 GOTO end

cd "C:\Program Files\MyLoc\bin"

myprog.exe myuser mypwd

:end

Solution 17 - Windows

Building on vtrz's answer and Samuel Renkert's answer on an other topic, I came up with the following script that only runs %EXEC_CMD% if it isn't already running:

@echo off
set EXEC_CMD="rsync.exe"
wmic process where (name=%EXEC_CMD%) get commandline | findstr /i %EXEC_CMD%> NUL
if errorlevel 1 (
	%EXEC_CMD% ...
) else (
	@echo not starting %EXEC_CMD%: already running.
)

As was said before, this requires administrative privileges.

Solution 18 - Windows

I usually execute following command in cmd prompt to check if my program.exe is running or not:

tasklist | grep program

Solution 19 - Windows

You should check the parent process name, see The Code Project article about a .NET based solution**.

A non-programmatic way to check:

  1. Launch Cmd.exe
  2. Launch an application (for instance, c:\windows\notepad.exe)
  3. Check properties of the Notepad.exe process in Process Explorer
  4. Check for parent process (This shows cmd.exe)

The same can be checked by getting the parent process name.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMatt LaceyView Question on Stackoverflow
Solution 1 - WindowsChaosmasterView Answer on Stackoverflow
Solution 2 - WindowsMatt LaceyView Answer on Stackoverflow
Solution 3 - WindowsTrueYView Answer on Stackoverflow
Solution 4 - WindowsaldemarcalazansView Answer on Stackoverflow
Solution 5 - WindowsRiccardo La MarcaView Answer on Stackoverflow
Solution 6 - WindowsvtrzView Answer on Stackoverflow
Solution 7 - WindowskayleeFrye_onDeckView Answer on Stackoverflow
Solution 8 - WindowsAdamView Answer on Stackoverflow
Solution 9 - WindowsbenmodView Answer on Stackoverflow
Solution 10 - WindowsnpocmakaView Answer on Stackoverflow
Solution 11 - WindowsMottiView Answer on Stackoverflow
Solution 12 - WindowsdrzausView Answer on Stackoverflow
Solution 13 - WindowsPatrickView Answer on Stackoverflow
Solution 14 - Windowsarnold_wView Answer on Stackoverflow
Solution 15 - WindowsNotMeView Answer on Stackoverflow
Solution 16 - WindowsNinView Answer on Stackoverflow
Solution 17 - WindowsCalimoView Answer on Stackoverflow
Solution 18 - WindowsRajeev JayaswalView Answer on Stackoverflow
Solution 19 - WindowsprakashView Answer on Stackoverflow