10

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

Dean
  • 499
  • 6
  • 13
  • 34

3 Answers3

14

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
foxidrive
  • 40,353
  • 10
  • 53
  • 68
  • Why a single '|' doesn't work here, and what is the meaning of '^|' ? Thanks! – bigeast May 10 '16 at 12:41
  • 2
    Inside a FOR command tail you need to escape certain characters and `^` is the batch file escape character (and also a line continuation character when it is used as the last character on a line). These all require the escape character when used in a similar way. `^&` `^|` `^<` `^>` – foxidrive May 22 '16 at 12:54
  • 1
    `%%a was unexpected at this time.` – Florian Castellane Jun 28 '18 at 14:23
  • 1
    @FlorianCastellane that's because you run the command directly in cmd instead of a batch file. Use `%a` instead. From `for /?`: *To use the FOR command in a batch program, specify %%variable instead of %variable. Variable names are case sensitive, so %i is different from %I.* – phuclv Apr 02 '20 at 03:51
  • heads up wmic is deprecated. see [this thread](https://stackoverflow.com/questions/57121875/what-can-i-do-about-wmic-is-deprecated) – gojimmypi Jun 08 '20 at 00:15
13

Use tasklist

for /f "tokens=2" %%a in ('tasklist^|find /i "Las2xyz"') do (set pid=%%a)
Rafael
  • 3,042
  • 3
  • 20
  • 36
  • 1
    this only works if there's only one instancec of Las2xyz – phuclv Apr 02 '20 at 03:51
  • 1
    @phuclv Yes, because the 2nd `set pid` overwrites the value of the 1st `set pid`. I just tested this exact same `for`-loop but used `do echo %%a` instead and it works just fine. If you need more than one pid I guees piping the result to a textfile and iterating that would be a good option. – Andreas Mar 11 '21 at 09:01
7

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
Community
  • 1
  • 1
dbenham
  • 127,446
  • 28
  • 251
  • 390