如何从 Windows 中的命令提示符获取自己的进程 pid

rad*_*dai 34 windows command-line-interface

我正在尝试找到一种从命令提示符获取我自己的 PID 的方法(供以后在 bat 脚本中使用)。

到目前为止,我发现的唯一有用的方法是getpids.exe从这里使用:http : //www.scheibli.com/projects/getpids/index.html,但我正在寻找一个“内置”到 Windows 的命令。

我正在寻找一种“防弹”方式。不假设我的进程是唯一的 cmd.exe 或任何东西。

ton*_*oth 43

由于没有其他解决方案是防弹和内置的,我想我会提供以下解决方案,但请注意,您需要以某种方式解析/保存结果:

title mycmd
tasklist /v /fo csv | findstr /i "mycmd"
Run Code Online (Sandbox Code Playgroud)

  • 如果调度程序同时调用批处理脚本两次,请不要使用 %random% + %time%。我遇到了同时使用不同参数调用同一个脚本的问题。random 的种子是相同的,我在创建临时目录时遇到了冲突。创建临时目录时没有办法处理错误。长话短说,如果你可以假设你的脚本不会同时被触发两次,那么这个技巧应该有效。 (4认同)

Nic*_*lay 12

使用 PowerShell + WMI :

powershell (Get-WmiObject Win32_Process -Filter ProcessId=$PID).ParentProcessId
Run Code Online (Sandbox Code Playgroud)

使用 WMIC :

for /f %a in ('wmic os get LocalDateTime ^| findstr [0-9]') do set NOW=%a
wmic process where "Name='wmic.exe' and CreationDate > '%NOW%'" get ParentProcessId | findstr [0-9]
Run Code Online (Sandbox Code Playgroud)

(一如既往,在批处理文件中加倍%符号for


小智 11

扩展托尼罗斯的回答:

title uniqueTitle
for /f "tokens=2 USEBACKQ" %f IN (`tasklist /NH /FI "WINDOWTITLE eq uniqueTitle*"`) Do echo %f
Run Code Online (Sandbox Code Playgroud)

使用 WINDOWTITLE 过滤器可以避免管道,因此您可以将其放入 for 循环中,并根据需要将其分配给 SET 变量:

title uniqueTitle
for /f "tokens=2 USEBACKQ" %f IN (`tasklist /NH /FI "WINDOWTITLE eq uniqueTitle*"`) Do set ourPID=%f
Run Code Online (Sandbox Code Playgroud)

删除/v使其更快,并/NH摆脱标题行。您需要通配符之后,"uniqueTitle"因为窗口标题实际上包含当前命令(因此,如果您尝试完全匹配它,它将继续下去)。


dbe*_*ham 7

我相信以下内容是万无一失的,前提是用户可以访问 WMIC 并且 TEMP 指向用户具有写入权限的有效路径。这是http://www.dostips.com/forum/viewtopic.php?f=3&t=6133上一些协作工作的最终结果。

@echo off

:getPID  [RtnVar]
::
:: Store the Process ID (PID) of the currently running script in environment variable RtnVar.
:: If called without any argument, then simply write the PID to stdout.
::
setlocal disableDelayedExpansion
:getLock
set "lock=%temp%\%~nx0.%time::=.%.lock"
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%"
2>nul ( 9>"%lock%" (
  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 )
))||goto :getLock
del "%lock%" 2>nul
endlocal & if "%~1" equ "" (echo(%PID%) else set "%~1=%PID%"
exit /b
Run Code Online (Sandbox Code Playgroud)

该脚本在将当前时间合并到名称中的临时文件上建立排他锁。如果两个类似命名的批处理进程试图在相同的 0.01 秒时间间隔内获取 PID,则只会发生冲突,在这种情况下,只有一个会成功。

任何失败的进程都会反复循环返回并使用新的锁定文件路径重试,直到成功为止。

锁定文件的完整路径转换为可在 WMIC 查询中使用的唯一 ID。WMIC 在 FOR /F 命令中运行,这意味着它在子 cmd.exe 进程中运行。这就是为什么要检索 cmd.exe 进程的 ParentProcessID。


Viv*_*har 5

  1. Windows 任务管理器,您需要转到查看 -> 选择列.. 并选择 PID。
  2. “tasklist /v”在命令提示符中获取详细的任务信息。
  3. 来自live.sysinternals.com 的Process Explorer 。

  • @Vivek,从命令提示符......你在重复答案 (2认同)

小智 5

如果您知道只有一个 cmd.exe 正在运行,您可以通过以下方式获取 PID:

for /F "tokens=1,2" %%i in ('tasklist /FI "IMAGENAME eq cmd.exe" /fo table /nh') do set pid=%%j

echo %pid%
Run Code Online (Sandbox Code Playgroud)