【问题标题】:How to capture the PID of a process when launching it from command line?从命令行启动进程时如何捕获进程的PID?
【发布时间】:2010-12-20 22:29:17
【问题描述】:

有没有办法纯粹在 .bat 文件中执行此操作?

目的是启动iexplore.exe,然后在完成后杀死该实例。

【问题讨论】:

  • 仅作记录:DOS 没有 PID。如果你的意思是 Windows 命令行环境,那么就这么说吧,但请不要将所有内容都标记为 DOS,它采用 16 色固定宽度字体...

标签: process cmd pid


【解决方案1】:

这是我使用的:

@echo off

rem there is a tab in the file at the end of the line below
set tab=    
set cmd=javaw -jar lib\MyProg.jar
set dir=%~dp0

echo Starting MyProg
set pid=notfound

for /F "usebackq tokens=1,2 delims=;=%tab% " %%i in (
    `wmic process call create "%cmd%"^, "%dir%"`
) do (
    if /I %%i EQU ProcessId (
        set pid=%%j
    )
)

echo %pid% > MyProg.pid

目录设置为 cmd 文件所在的目录。更改 dir 以更改它。修改 cmd 以更改运行的命令。

如果你想要一个杀死它的 stop.cmd,它看起来像这样

@echo off
for /F %%i in (%~dsp0MyProg.pid) do taskkill /F /PID %%i
del %~dsp0MyProg.pid

【讨论】:

  • 我刚刚在 Windows 7 上尝试了 wmic 调用,它可以工作。有可能是解析结果出了问题,我稍后再检查。
  • @kybernetikos 谢谢!开箱即用。这为我节省了很多精力!
  • 更清洁的解决方案:stackoverflow.com/a/51353994/12705489
【解决方案2】:

您可以使用 vbscript,这是一个创建记事本的示例,然后使用它的 pid 终止它

strComputer = "."
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set objStartup = objWMIService.Get("Win32_ProcessStartup")
Set objConfig = objStartup.SpawnInstance_
Set objProcess = GetObject("winmgmts:root\cimv2:Win32_Process")
errReturn = objProcess.Create("notepad.exe", null, objConfig, PID)
If errReturn = 0 Then
    WScript.Echo "Process ID is: " & PID
End If 

WScript.Echo "Ready to kill process: " & PID & "? [Y|y]"
Do While Not WScript.StdIn.AtEndOfLine
   strInput = strInput & WScript.StdIn.Read(1)
Loop
If LCase(strInput) = "y" Then
    WScript.Echo "Select * from Win32_Process Where ProcessId = '" & PID & "'"
    Set colProcessList = objWMIService.ExecQuery("Select * from Win32_Process Where ProcessId = '" & PID & "'")
    For Each objProcess in colProcessList
        objProcess.Terminate()
    Next
End If 

另存为 myscript.vbs 并在命令行中

c:\test> cscript /nologo myscript.vbs

【讨论】:

    【解决方案3】:

    @kybernetikos 提供的答案略有不同,因为它存在解析问题。注意if %%j gr 0 (这一行

    @echo off
    
    rem there is a tab in the file at the end of the line below
    set tab=    
    set cmd=javaw -jar lib\MyProg.jar
    set dir=%~dp0
    
    echo Starting MyProg
    set pid=notfound
    
    for /F "usebackq tokens=1,2 delims=;=%tab% " %%i in (
        `wmic process call create "%cmd%"^, "%dir%"`
    ) do (
        if %%j gtr 0 (
            set pid=%%j
        )
    )
    
    echo %pid% > MyProg.pid
    

    【讨论】:

      【解决方案4】:

      大多数情况下,您确实知道要开始什么任务 - 在这种情况下,iexplorer 应该显示哪个页面。

      怎么样

      taskkill /FI "Windowtitle eq *yourpagetitle*"
      

      它会杀死所有显示页面标题的实例,但对于特定标题,通常应该只有一个。

      汤姆

      【讨论】:

        【解决方案5】:

        嗯,TaskList & TaskKill?!

        【讨论】:

        • 所以我启动了 7 个 Iexplore 进程,然后启动另一个。我如何在启动时捕获该 PID?
        • 你不能在启动它之前和之后做一个任务列表,区分它们并获取你的 PID 吗? -- 我知道这不是最简单的方法,但我不知道用一些常规的 Windows 脚本来做这件事的好方法。
        【解决方案6】:

        由于某种原因,您获取进程 ID 的方法对我不起作用,但由于我是批处理方面的专家,因此我编写了自己的方法,附在此处:

        @echo off
        
        call:AsyncCmd
        rem call:AsyncCmd "echo hello world"
        rem call:AsyncCmd "call build.bat"
        exit /b
        
        rem ------------------------------------------------------------------------------------------
        rem Starts asynchronous command execution 
        rem %1 is command, if empty - only aborts existing build.
        rem ------------------------------------------------------------------------------------------
        :AsyncCmd
        if exist %~dp0SetupBuild_Completed.txt (
            del /f %~dp0SetupBuild_Pid.txt >nul 2>&1
            del /f %~dp0SetupBuild_Completed.txt >nul 2>&1
        )
        
        if not exist %~dp0SetupBuild_Pid.txt goto lStartProc
            rem --------------------------------------------------
            rem Abort build process
            rem --------------------------------------------------
            set /p pid=<%~dp0SetupBuild_Pid.txt
            echo Cancelling setup build process, process id %pid%
            pskill -t %pid%
            del /f %~dp0SetupBuild_Pid.txt >nul 2>&1
        
        :lStartProc
        if "%~1" == "" exit /b 0
        
        rem --------------------------------------------------
        rem Starts asyncronous build process
        rem --------------------------------------------------
        set dir=%~dp0
        set dir=%dir:~0,-1%
        for /f "tokens=2 delims==; " %%a in ('wmic process call create "cmd /c mincon.exe && %~1 && echo 1>%~dp0SetupBuild_Completed.txt"^, "%dir%" ^| findstr /r "ProcessId"') do set pid=%%a
        echo Setup build started, process id: %pid%
        echo %pid%>%~dp0SetupBuild_Pid.txt
        exit /b 0
        

        【讨论】:

          【解决方案7】:

          我认为你不能使用简单的命令行实用程序来做到这一点,因为 IE 实际上会为每个选项卡生成子进程,即如果 IE 尚未运行,你将获得一个父 IE 进程和一个用于选项卡的子进程,并且如果 IE 已经在运行,您只需获得一个子进程。

          如果你自己写一个工具来杀死IE,那就更麻烦了,因为当你杀死一个子(tab)进程时,IE会自动恢复这个tab。

          另请参阅此相关问题:How to obtain process of newly created IE8 window?(尽管那里没有好的答案)。

          【讨论】:

          • 我们仍然坚持使用 IE6!所以它们都在不同的进程上——但我认为后来的选项卡版本仍然在幕后使用进程。
          【解决方案8】:

          PowerShell 可用于此:

          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%
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-02-02
            • 1970-01-01
            • 1970-01-01
            • 2012-02-27
            • 2020-03-24
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多