Get only PID from tasklist using cmd title

白昼怎懂夜的黑 提交于 2019-12-04 17:47:33

The difficult thing with tasklist is its default output format. For example, when command line:

tasklist /FI "ImageName eq cmd.exe" /FI "Status eq Running"

is executed, we get:

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

Unless the column widths are fixed, which I would not rely on, extracting the PID is not that trivial, because the image name could also have SPACEs in it, so using such as delimiters would not work.
A possible way was to count the number of =-signs in the second line up to the first SPACE, so we know the number of characters to truncate to have the image name removed, but this requires some kind of loop (using goto), so the performance might be quite bad.

However, there are other output formats available for tasklist. The command line:

tasklist /FI "ImageName eq cmd.exe" /FI "Status eq Running" /FO CSV

results in this output:

"Image Name","PID","Session Name","Session#","Mem Usage"
"cmd.exe","12740","Console","1","3'328 K"
"cmd.exe","11020","Console","1","3'304 K"

Now it is quite easy to extract the 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=#"
    )
)

Another output formats is used by the following command line:

tasklist /FI "ImageName eq cmd.exe" /FI "Status eq Running" /FO LIST

resulting in this output:

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

With this it is even simpler to get the desired output:

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

By the way, for the filter options /FI, there are the following operators available:

  • eq -- equal to;
  • ne -- not equal to;
  • gt -- greater than;
  • lt -- less than;
  • ge -- greater than or equal to;
  • le -- less than or equal to;

The Microsoft documentation as well as the help message (tasklist /?) do not explain their meaning, but I found the following external resources:

Use for /f to parse output. The PID is the 2nd column space separated. The default separator/delmiter is the space, adjacent delims count as one.

So this sample ouput:

> tasklist | findstr /i "cmd.exe"
cmd.exe                      14924 Console                    9         6.008 K

Is parsed on the cmd line

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

Or in a batch:

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

cmd.exe has PID(s) 14924,11268,3652

The last one presumably the temporary one used by the for /f itself.


EDIT late addition to my answer.

The tool cmdow from Ritchie Lawrence can accomplish your task.

With this question open in 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

To only get the PID on cmd line

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

In a batch file double the percent signs %%A.

Demonstration using start to run another cmd.exe with a specified title:

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

I am not sure what you are expecting. There could be several cmd shells running. If they are running a program, their window title typically changes.

It is easy enough to get the cmd processes and there PID (the Id field). The window title is also available.

PS C:\src\t\s1> Get-Process | Where-Object { $_.ProcessName -eq 'cmd' }

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    152      15    10280      16432      10.80   2808   1 cmd
    153      13     8472      12220       3.68   7232   1 cmd

PS C:\src\t\s1> Get-Process | Where-Object { $_.ProcessName -eq 'cmd' } | ForEach-Object { $_.MainWindowTitle }
cmd.exe
dirlist.bat (C:\src\t) - VIM

Getting the PID only to appear is easy enough. But, which one do you want?

PS C:\src\t\s1> Get-Process | Where-Object { $_.ProcessName -eq 'cmd' } | ForEach-Object { $_.Id }
2808
7232
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!