使用 cmd 标题仅从任务列表中获取 PID

Gre*_*sJB 3 cmd pid title tasklist

期望的输出:

1234
Run Code Online (Sandbox Code Playgroud)

只是PID。没有别的 - 没有其他字符、数字或符号。

我正在尝试运行,tasklist所以它只给我一个命名或标题进程的 PID。

tasklist | findstr /i "cmd.exe"是我得到的最接近的,但结果太冗长了。我只想要PID号。

将任务列表过滤器运算符的含义描述链接给我的奖励点 - “eq”、“ne”等,因为它们不在文档中的任何地方。

asc*_*pfl 9

困难的tasklist是它的默认输出格式。例如,当命令行:

tasklist /FI "ImageName eq cmd.exe" /FI "Status eq Running"
Run Code Online (Sandbox Code Playgroud)

被执行,我们得到:

Image Name                     PID Session Name        Session#    Mem Usage
========================= ======== ================ =========== ============
cmd.exe                      12740 Console                    1      3'328 K
cmd.exe                      11020 Console                    1      3'304 K
Run Code Online (Sandbox Code Playgroud)

除非列宽是固定的,我不会依赖,否则提取 PID 并不是那么简单,因为图像名称也可以包含SPACEs在其中,因此使用诸如分隔符之类的方法是行不通的。
一种可能的方法是计算=第二行中 -符号的数量直到第一行SPACE,因此我们知道要截断以删除图像名称的字符数,但这需要某种循环(使用goto),因此性能可能会很糟糕。

但是,还有其他输出格式可用于tasklist. 命令行:

tasklist /FI "ImageName eq cmd.exe" /FI "Status eq Running" /FO CSV
Run Code Online (Sandbox Code Playgroud)

导致此输出:

"Image Name","PID","Session Name","Session#","Mem Usage"
"cmd.exe","12740","Console","1","3'328 K"
"cmd.exe","11020","Console","1","3'304 K"
Run Code Online (Sandbox Code Playgroud)

现在很容易提取PID:

@echo off
for /F "delims=" %%R in ('
    tasklist /FI "ImageName eq cmd.exe" /FI "Status eq Running" /FO CSV /NH
') do (
    set "FLAG1=" & set "FLAG2="
    for %%C in (%%R) do (
        if defined FLAG1 (
            if not defined FLAG2 (
                echo %%~C
            )
            set "FLAG2=#"
        )
        set "FLAG1=#"
    )
)
Run Code Online (Sandbox Code Playgroud)

以下命令行使用另一种输出格式:

tasklist /FI "ImageName eq cmd.exe" /FI "Status eq Running" /FO LIST
Run Code Online (Sandbox Code Playgroud)

导致此输出:

Image Name:   cmd.exe
PID:          12740
Session Name: Console
Session#:     1
Mem Usage:    3'328 K

Image Name:   cmd.exe
PID:          11020
Session Name: Console
Session#:     1
Mem Usage:    3'304 K
Run Code Online (Sandbox Code Playgroud)

有了这个,获得所需的输出就更简单了:

@echo off
for /F "tokens=2" %%K in ('
   tasklist /FI "ImageName eq cmd.exe" /FI "Status eq Running" /FO LIST ^| findstr /B "PID:"
') do (
   echo %%K
)
Run Code Online (Sandbox Code Playgroud)

顺便说一下,对于过滤器选项/FI,有以下运算符可用:

  • eq - 等于;
  • ne - 不等于;
  • gt - 比...更棒;
  • lt - 少于;
  • ge -- 大于或等于;
  • le ——小于或等于;

Microsoft 文档以及帮助消息 ( tasklist /?) 没有解释它们的含义,但我找到了以下外部资源:


小智 6

用于for /f解析输出。PID 是分隔的第二列空间。默认分隔符/定界符是空格,相邻定界符计为 1。

所以这个示例输出:

> tasklist | findstr /i "cmd.exe"
cmd.exe                      14924 Console                    9         6.008 K
Run Code Online (Sandbox Code Playgroud)

在cmd行上解析

for /f "tokens=2" %A in ('tasklist ^| findstr /i "cmd.exe" 2^>NUL') do @Set "PID=%A"
Run Code Online (Sandbox Code Playgroud)

或者批量:

@Echo off & SetLocal EnableDelayedExpansion
set "PID="
for /f "tokens=2" %%A in ('tasklist ^| findstr /i "cmd.exe" 2^>NUL') do @Set "PID=!PID!,%%A"
if defined PID Echo cmd.exe has PID(s) %PID:~1%
Run Code Online (Sandbox Code Playgroud)

cmd.exe 的 PID 为 14924,11268,3652

最后一张大概是自己临时用的for /f


编辑我的答案的最新补充。

Ritchie Lawrence 的cmdow工具可以完成您的任务。

在 Firefox 中打开这个问题:

> cmdow.exe "get only PID from task*" /f
Handle  Lev Pid -Window status- Image    Caption
0x0103DE 1 9532 Max Ina Ena Vis firefox  Get only PID from tasklist using cmd title - Stack Overflow - Mozilla Firefox
Run Code Online (Sandbox Code Playgroud)

仅在命令行上获取 PID

> for /f "tokens=3" %A in ('cmdow.exe "get only PID from task*" /B /F') Do @Echo:%A
9532
Run Code Online (Sandbox Code Playgroud)

在批处理文件中,将百分号加倍%%A

start使用指定标题运行另一个 cmd.exe 的演示:

:: Q:\Test\2018\05\27\SO_50555929_2.cmd
@Echo off
set "MyTitle=This is a quite long title to distinguish from other"
start "%MyTitle%" cmd.exe /k cmdow.exe @ /F

:: wait to get other cmd instance get started
timeout /t 3 >NUL

set "PID="
for /F "tokens=3" %%A in ('cmdow.exe "%MyTitle%*"') do set "PID=%%A"
if defined PID Echo %PID%
Run Code Online (Sandbox Code Playgroud)