46

In Windows batch scripting there is start command which starts a new process.

Is it possible to get PID of the process just started?

Mofi
  • 46,139
  • 17
  • 80
  • 143
  • 1
    Possible duplicate of [How to capture the PID of a process when launching it in DOS](https://stackoverflow.com/questions/1807794/how-to-capture-the-pid-of-a-process-when-launching-it-in-dos) – user May 29 '17 at 05:25
  • See the [answer from kybernetikos](https://stackoverflow.com/a/11616359/5413773) and the [answer from frog.clemens (me)](https://stackoverflow.com/a/59862878/5413773) at [How to capture the PID of a process when launching it in DOS](https://stackoverflow.com/questions/1807794/how-to-capture-the-pid-of-a-process-when-launching-it-from-command-line) for two different approaches. – frog.ca Jan 23 '20 at 11:53

7 Answers7

39

This is an old post but I think that it worth to share the following 'easy to use' solution which works fine nowadays on Windows.

Start multiple processes in parallel:

start "<window title>" <command will be executed>

Example:

start "service1" mvn clean spring-boot:run
start "service2" mvn clean spring-boot:run

Obtain the PID of the processes (optional):

tasklist /V /FI "WindowTitle eq service1*"
tasklist /V /FI "WindowTitle eq service2*"

Kill the processes:

taskkill /FI "WindowTitle eq service1*" /T /F
taskkill /FI "WindowTitle eq service2*" /T /F
Community
  • 1
  • 1
zappee
  • 20,148
  • 14
  • 73
  • 129
  • 1
    when I try to do `start "javapp" java -jar $app_path &` an alert pops up with warning `The system cannot find the file javapp`. Am i doing it wrong? – Zavael Sep 12 '19 at 07:43
  • This works like a charm on Windows 10: start "javaapp" java -version & The $app_path is a Unix variable. For Windows, you need this: %app_path%. – zappee Sep 12 '19 at 08:10
  • yes I am running it from bash on win10, therefore the unix variable.. weird, i get the same result(=the missing file javaapp warning) when I run `start "javaapp" java -version`.. both commands are working fine without the "javaapp" name :( – Zavael Sep 12 '19 at 09:05
  • oh my! it is working in win cmd, not in git bash :( thank you – Zavael Sep 12 '19 at 09:11
  • 6
    This does not work for GUI applications (for example 'start "x" notepad' will not result in a new console window, thus the search for WindowTitle won't work). The original post does not state whether GUI or command line processes are meant. This solution also does not address the specified window title occurring multiple times (all "matching" processes will be killed). – frog.ca Jan 21 '20 at 15:10
  • Pointing out problems is constructive discourse (even when one cannot propose a better or other solution). I suggest(ed) the solutions from [kybernetikos](https://stackoverflow.com/a/11616359/5413773) and [me](https://stackoverflow.com/a/59862878/5413773) in article [How to capture the PID of a process when launching it from command line?](https://stackoverflow.com/questions/1807794/how-to-capture-the-pid-of-a-process-when-launching-it-from-command-line/59862878#59862878) (in a comment to the original question of this article). – frog.ca Jan 23 '20 at 12:47
  • I started the process in the background with `/B` with window title but when i tried to kill the process, it didn't kill the process. Will it work for processes which run in the background ? – SRJ Jan 22 '21 at 17:08
19

You can in batch but not directly per say. You need to either parse the output of tasklist.exe or use wmic.exe. Both require you to know what you just started which of course you will.

Using tasklist.exe:

for /F "TOKENS=1,2,*" %a in ('tasklist /FI "IMAGENAME eq powershell.exe"') do set MyPID=%b
echo %MyPID%

To use this in a batch script double up the percent signs.

Using wmic.exe:

for /f "TOKENS=1" %a in ('wmic PROCESS where "Name='powershell.exe'" get ProcessID ^| findstr [0-9]') do set MyPID=%a
echo  %MyPID%
Andy Arismendi
  • 50,577
  • 16
  • 107
  • 124
15

If there are processes already running with the same name, you first need to get a list of the current pids, than start your local process(es) and then check the pids again. Here is a sample code that starts 3 process and kills them at the end (specifically the ones started locally):

@echo off
set PROCESSNAME=notepad.exe

::First save current pids with the wanted process name
setlocal EnableExtensions EnableDelayedExpansion
set "RETPIDS="
set "OLDPIDS=p"
for /f "TOKENS=1" %%a in ('wmic PROCESS where "Name='%PROCESSNAME%'" get ProcessID ^| findstr [0-9]') do (set "OLDPIDS=!OLDPIDS!%%ap")

::Spawn new process(es)
start %PROCESSNAME%
start %PROCESSNAME%
start %PROCESSNAME%

::Check and find processes missing in the old pid list
for /f "TOKENS=1" %%a in ('wmic PROCESS where "Name='%PROCESSNAME%'" get ProcessID ^| findstr [0-9]') do (
if "!OLDPIDS:p%%ap=zz!"=="%OLDPIDS%" (set "RETPIDS=/PID %%a !RETPIDS!")
)

::Kill the new threads (but no other)
taskkill %RETPIDS% /T > NUL 2>&1
endlocal
Oliver Zendel
  • 2,695
  • 34
  • 29
  • 3
    P.S. Of course this does introduce a racing condition if you execute multiple versions of the script in parallel. In case of taskkill this might be harmfull as a once killed pid could be reassigned to a completely different thread which you do not want to get killed "again". At that stage you should probably not rely on windows batch syntax anyways :) – Oliver Zendel Jun 17 '14 at 14:02
  • This also does not address process ID re-use. +1 for pointing out that Windows batch functionality is likely not an adequate tool for the problem. – frog.ca Jan 21 '20 at 15:12
5

you can try with

wmic process call create "notepad"

which will return the pid of the created process.

Processing this with FOR

setlocal
set "ReturnValue="
set "ProcessId="
for /f "eol=} skip=5 tokens=1,2 delims=;= " %%a in ('wmic process call create "notepad"') do (
    set "%%a=%%b"
)
echo %ReturnValue%
echo %ProcessId%
endlocal
npocmaka
  • 55,367
  • 18
  • 148
  • 187
  • I think this struggles when running a command with parameters in quotes. – Steve Smith Dec 15 '22 at 15:32
  • @SteveSmith Is there a command you have troubles with? There are some ways that the quotes can be escaped. – npocmaka Dec 15 '22 at 16:17
  • I was trying to run ffplay, and the input device name had spaces in it. I found a different way to do it that worked (nothing to do with needing to gett the pid). – Steve Smith Dec 16 '22 at 17:51
4

PowerShell can be used for this:

powershell -executionPolicy bypass -command "& {$process = start-process $args[0] -passthru -argumentlist $args[1..($args.length-1)]; exit $process.id}" notepad test.txt

echo Process ID of new process: %errorlevel%
frog.ca
  • 684
  • 4
  • 8
0

This is the code that i use to get a PID

for /f "tokens=2 delims=," %%a in ('tasklist /FO CSV ^| findstr /I /C:"entertheprocess.here"') do (
    echo PID:%%a
)
nk125
  • 1
  • 1
-1
@ECHO OFF
SETLOCAL EnableDelayedExpansion EnableExtensions
::
::weil es mehrere Sessions für UltraCompare gleichzeitig geben kann, es wird hier die
::neueste Instanz (soeben gestartet) ermittelt, um später mit ProcessId diese Instanz 
::aktivieren zu können...
::
set "CreationDate="
set /A "ProcessIdUltraCompare=0"
::
set /A "lineno=0"
FOR /F %%T IN ('Wmic process where^(Name^="uc.exe"^) get CreationDate^|sort /r') DO (
set /A lineno+=1
rem echo %%T
rem echo !lineno!
if !lineno! equ 2 (
    rem ECHO %%T   
    set CreationDate=%%T
    rem echo !CreationDate!
    set /A "lineno=0"
    FOR /F %%P IN ('Wmic process where^(CreationDate^="!CreationDate!"^) get ProcessId') DO (
          set /A lineno+=1
          rem echo %%P
          if !lineno! equ 2 (
              set "ProcessIdUltraCompare=%%P"
              rem echo ProcessIdUltraCompare=!ProcessIdUltraCompare!
              goto :l_pid_uc_got
          )
      )
 )
)  
:l_pid_uc_got
    echo ProcessIdUltraCompare=!ProcessIdUltraCompare!
PAUSE
  • There is no explanation for the downvote, but of course this opens up a race condition regarding the definition of "instance of application just started", because multiple instances may "just have been started", and going by the timestamp then may be misleading/wrong. I suggest my approach based on PowerShell shown above instead to avoid such uncertainties. – frog.ca Jul 01 '21 at 08:55