【问题标题】:getting process ID of exe running in Bat File获取在 Bat File 中运行的 exe 的进程 ID
【发布时间】:2014-02-07 03:45:19
【问题描述】:

我需要在我的 bat 文件中运行的“Las2xyz”进程的进程 ID。

我怎样才能做到这一点?我不能使用最后一个 RUN ID 或第一个 ID,我需要实际的进程 ID,因为在任何给定时间运行多个这些 ID,并且在任何给定时间结束我无法猜测。

这是我的批次:

@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"

有人教我怎么做! 谢谢你

【问题讨论】:

    标签: windows batch-file batch-processing


    【解决方案1】:

    这将启动一个可执行文件并获取 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
    

    【讨论】:

    • 为什么要一个'|'在这里不起作用,'^|'是什么意思?谢谢!
    • 在 FOR 命令尾中,您需要转义某些字符,^ 是批处理文件转义字符(当它用作行上的最后一个字符时也是行继续字符)。当以类似方式使用时,这些都需要转义字符。 ^&^|^<^>
    • %%a was unexpected at this time.
    • @FlorianCastellane 这是因为您直接在 cmd 而不是批处理文件中运行命令。请改用%a。来自for /?要在批处理程序中使用 FOR 命令,请指定 %%variable 而不是 %variable。变量名区分大小写,因此 %i 与 %I 不同。
    • 提醒 wmic 已弃用。见this thread
    【解决方案2】:

    使用tasklist

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

    【讨论】:

    • 这仅在只有一个 Las2xyz 实例时才有效
    • @phuclv 是的,因为第二个set pid 会覆盖第一个set pid 的值。我刚刚测试了这个完全相同的for-loop,但使用了do echo %%a,它工作得很好。如果您需要多个 pid,我认为将结果通过管道传输到文本文件并进行迭代,这将是一个不错的选择。
    【解决方案3】:

    扩展 foxidrive 的答案以显示需要参数的 OP 调用:

    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%"
    

    引用参数的内容几乎可以包含除双引号或逗号之外的任何内容。如果参数之间使用逗号,则必须对其进行转义。

    可能有另一种语法允许在参数中使用逗号,但它不允许在参数中使用括号。

    那么如果你的命令行无法通过WMIC PROCESS CALL CREATE怎么办?

    有一个解决方案。但这并不漂亮 ;-) 我首先在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
    

    【讨论】:

      猜你喜欢
      • 2014-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多