getting process ID of exe running in Bat File

45,428

Solution 1

This will launch an executable and get the PID:

@echo off
for /f "tokens=2 delims==; " %%a in (' wmic process call create "notepad.exe" ^| find "ProcessId" ') do set PID=%%a
echo "%PID%"
pause

Solution 2

Use tasklist

for /f "tokens=2" %%a in ('tasklist^|find /i "Las2xyz"') do (set pid=%%a)

Solution 3

Extending foxidrive's answer to show the OP's call that requires arguments:

set "exe=las2xyz.exe"
set "arg1=[ flightpath 2 out 5 lasformat 1 target 0 FIXCLASS 1 step 20 unit *METRIC* fov 20.0 rollfix 1   sn_number *H68_038-003* lsystem *LIDAR_1* DESTSYS 144 minele -100.00 maxele 6000.00 hoff 0.00 eoff 0.00 noff 0.00 bootnr 13110201 leg 1]"
set "arg2=C:\Users\Developer-One\Desktop\las2xyz_Data\131102_003243_GPE.sdc"
set "arg3=\\192.168.0.102\agis\Macquarie_Barwon_1310\Area_01\sbet_038_13110201.out"
set "arg4=131102_003243_cov"

for /f "tokens=2 delims==; " %%A in (
  'wmic process call create '"%exe%" "%arg1%" ^, "%arg2%" "%arg3%" - "%arg4%"' ^| find "ProcessId"'
) do set "PID=%%A"
echo "%PID%"

The content of the quoted arguments can contain pretty much anything except for double quote or comma. If a comma is used between arguments then it must be escaped.

There may be another syntax that allows commas within arguments, but then it would not allow parentheses within arguments.

So what to do if your command line cannot be passed through WMIC PROCESS CALL CREATE?

There is a solution. But it is not pretty ;-) I first posted this at Escaping strings when using wmic

@echo off
setlocal enableDelayedExpansion

:: Get the PID and UID for this batch process
call :getMyPID

:: Initialize an existing PIDs list
set "PIDs= "

:: Get a list of all existing child processes, except for the
:: child CMD.EXE process that was created by this FOR /F loop.
:: This is necessary because the console session that this script
:: is running in might have previously created a child process.
for /f %%A in (
  '2^>nul wmic process where "ParentProcessID=%myPID% and not CommandLine like '%%<%UID%>%%'" get ProcessID'
) do for %%B in (%%A) do set "PIDs=!PIDs!%%B "

:: Create your new process as you normally would.
:: For this demonstration, I will simply create a new CMD.EXE session 
start

:: Get the PID of the newly created child process by getting all child PIDs,
:: except for the child CMD.EXE process that was created by this FOR /F loop.
:: Ignore any PID that already exists in the %PIDs% list. The only PID left
:: is your new process.
for /f %%A in (
  '2^>nul wmic process where "ParentProcessID=%myPID% and not CommandLine like '%%<%UID%>%%'" get ProcessID'
) do for %%B in (%%A) do if "!PIDs: %%B =!" equ "!PIDs!" set "PID=%%B"

:: At this point you could append the new PID to the PIDs list using
::   set "PIDs=!PIDs!%PID% "
:: Then you can repeat the steps of creating a new proces and getting the new PID
::
:: But instead, I will simply show the result and exit
echo new PID=%PID%

exit /b


:getMyPID 
setlocal disableDelayedExpansion

:getLock

:: Establish a nearly unique temp file name using %time%
set "lock=%temp%\%~nx0.%time::=.%.lock"

:: Transform the full path into a UID that can be used in a WMIC query
set "uid=%lock:\=:b%"
set "uid=%uid:,=:c%"
set "uid=%uid:'=:q%"
set "uid=%uid:_=:u%"
setlocal enableDelayedExpansion
set "uid=!uid:%%=:p!"
endlocal & set "uid=%uid%"


:: Establish an exclusive lock on the temp file
:: If this fails, then loop back and try again until success
:: This guaranees no two process will ever have the same UID
2>nul ( 9>"%lock%" (

  %= The FOR /F loops creates a child CMD.EXE process which in turn invokes WMIC.         =%
  %= The child CMD.EXE process contains the WMIC query with the UID in its command line.  =%
  %= The WMIC query identifies the CMD.EXE process with the UID in the command line,      =%
  %= and returns the parent process ID, which happens to be the PID for this batch script =%
  for /f "skip=1" %%A in (
    'wmic process where "name='cmd.exe' and CommandLine like '%%<%uid%>%%'" get ParentProcessID'
  ) do for %%B in (%%A) do set "PID=%%B"
  (call ) %= Guarantee success so we don't accidently loop again =%

))||goto :getLock

:: Delete the temp file
del "%lock%" 2>nul

:: Return the result
( endlocal
  set "myPID=%PID%"
  set "UID=%uid%"
)
exit /b
Share:
45,428
Dean
Author by

Dean

Updated on May 24, 2020

Comments

  • Dean
    Dean almost 4 years

    I require the Process id of the "Las2xyz" process that's being run in my bat file.

    How can i achieve this? I can't use the last RUN ID or the first ID, I need the actual process ID, as there are multiple of these running at any given time and ending at any given time i cannot guessimate it.

    this is my batch:

    @echo off
    @echo off
    set PATH=C:\Windows\system32;C:\atlass\las2xyz;C:\atlass\las2xyz\bin;C:\atlass\las2xyz\lib
    set TOP_HOME=%C:\atlass\las2xyz%
    del dat*.xyz dat*.seg dat*.pat dat*.tmp dat*.txt test.nam
    las2xyz.exe "[ flightpath 2 out 5 lasformat 1 target 0 FIXCLASS 1 step 20 unit *METRIC* fov 20.0 rollfix 1   sn_number *H68_038-003* lsystem *LIDAR_1* DESTSYS 144 minele -100.00 maxele 6000.00 hoff 0.00 eoff 0.00 noff 0.00 bootnr 13110201 leg 1]" "C:\Users\Developer-One\Desktop\las2xyz_Data\131102_003243_GPE.sdc" , "\\192.168.0.102\agis\Macquarie_Barwon_1310\Area_01\sbet_038_13110201.out" - "131102_003243_cov"
    

    Someone show me how to do it! thank you