1

I would like to write a windows script that waits until a given process (PID) has ended before executing something. So far I have (PID=1234):

:loop
set VAR="tasklist | find /i " 1234 " /c"
if NOT (' %VAR% ')=="0" goto loop
**do something**

but already the line

set VAR="tasklist | find /i " 1234 " /c"

doesn't work, it stores the string instead of the evaluation. Or maybe it's supposed to? In which case the line

if NOT (' %VAR% ')=="0" goto loop

should evaluate the contents of VAR, but if I type this manually in a console I just get

"tasklist | find /i " was unexpected

I understand the double quotes in

set VAR="tasklist | find /i " 1234 " /c"

are problematic but I need a space on each side of the PID (1234 in the example) to ensure that it is not a substring of another process (like 12345) for it to work properly.

Any DOS experts out there?

schmop
  • 1,440
  • 1
  • 12
  • 21

3 Answers3

6
:loop
tasklist | find " 1234 " >nul
if not errorlevel 1 (
    timeout /t 10 >nul
    goto :loop
)

Get the list, search in the content, if found (on not found errorlevel = 1) wait and loop

To get the data into the variable

for /f %%a in ('tasklist ^| find /c " 1234 "') do set "var=%%a"
MC ND
  • 69,615
  • 8
  • 84
  • 126
  • I'm marking this as the answer for being concise and complete, thanks. On a side note, that last line to get the data in a variable is a comical testimony to the utter rottenness of this language – schmop Mar 21 '14 at 13:15
  • note that since windows uses 3 digit PIDs too in those cases it might incorrectly catch the number in the printed memory usage (on some locales only?). PA's answer is better – Sopel May 12 '22 at 10:14
  • @sopel, it should not, there are two spaces as delimiters in the find search string – MC ND May 13 '22 at 16:47
  • @MCND one on each side, yes. So it can catch in here for example `firefox.exe 9048 Console 1 296 896 KB` – Sopel May 13 '22 at 21:18
2

You can combine tasklist and find to check if the process with the given pid is running or not.

Then, you can loop around this check to wait for the given pid

 :waitforpid
 tasklist /fi "pid eq %1" 2>nul | find "%1" >nul
 if %ERRORLEVEL%==0 (
   timeout /t 2 /nobreak >nul
   goto :waitforpid
 )
 goto :eof

EDIT:added some sleep

and use this as

 call :waitforpid 1234
PA.
  • 28,486
  • 9
  • 71
  • 95
1
@echo off
setlocal enabledelayedexpansion
:check
set stillalive=no
for /f "tokens=2" %%a in ('tasklist') do (
set pid=%%a
if !pid! == 1234 (
set stillalive=yes
)
)
if %stillalive% == yes (
cls
 echo/Oh! He's still there, I'll wait.
 goto check
) else (
 echo/He's not there anymore, start the party!!
)
Rafael
  • 3,042
  • 3
  • 20
  • 36