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

Viewed 713313

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.

19 Answers

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.

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)

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

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"

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
)

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

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

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.

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.

Related