期望的输出:
1234
只是PID。没有别的 - 没有其他字符,数字或符号。
我正在尝试运行tasklist
所以它只给我一个命名或标题过程的PID。
tasklist | findstr /i "cmd.exe"
是我得到的最接近的,但结果太过冗长。我只想要PID号。
奖励点用于链接我对任务列表过滤器运算符的含义的描述 - “eq”,“ne”等,因为它们不在the documentation中的任何位置。
答案 0 :(得分:3)
tasklist
的难点在于它的默认输出格式。例如,命令行:
tasklist /FI "ImageName eq cmd.exe" /FI "Status eq Running"
执行,我们得到:
Image Name PID Session Name Session# Mem Usage ========================= ======== ================ =========== ============ cmd.exe 12740 Console 1 3'328 K cmd.exe 11020 Console 1 3'304 K
除非列宽是固定的,否则我不会依赖它,因此提取PID并不是那么简单,因为图像名称中也可能包含 SPACEs ,因此使用诸如分隔符不会工作。
一种可能的方法是计算第二行中=
- 符号的数量,直到第一个 SPACE ,因此我们知道要截断的字符数,以删除图像名称,但是这需要某种循环(使用goto
),因此性能可能非常差。
但是,tasklist
还有其他可用的输出格式。命令行:
tasklist /FI "ImageName eq cmd.exe" /FI "Status eq Running" /FO CSV
导致此输出:
"Image Name","PID","Session Name","Session#","Mem Usage" "cmd.exe","12740","Console","1","3'328 K" "cmd.exe","11020","Console","1","3'304 K"
现在很容易提取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=#"
)
)
以下命令行使用另一种输出格式:
tasklist /FI "ImageName eq cmd.exe" /FI "Status eq Running" /FO LIST
导致此输出:
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
有了这个,获得所需的输出就更简单了:
@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
)
顺便说一句,对于过滤器选项/FI
,可以使用以下运算符:
eq
- 等于; ne
- 不等于; gt
- 大于; lt
- 小于; ge
- 大于或等于; le
- 小于或等于; Microsoft文档以及帮助消息(tasklist /?
)没有解释它们的含义,但我发现了以下外部资源:
答案 1 :(得分:1)
使用#include <iostream>
#include <cstring>
template <typename T>
class Pair {
public:
Pair(T val) : value(val) {}
bool operator==(const Pair& other) {
return value == other.value;
}
private:
T value;
};
template <>
class Pair<char*> {
public:
Pair(const char* val) {
std::size_t size = std::strlen(val) + 1;
value = new char[size];
memcpy(value, val, size);
}
~Pair() {
delete value;
}
bool operator==(const Pair& other) {
return std::strcmp(value, other.value) == 0;
}
private:
char* value;
};
int main() {
Pair<int> p1(5), p2(5), p3(4);
Pair<char*> p4("Hey"), p5("Hey"), p6("Bye");
std::cout << (p1 == p2) << '\n' << (p1 == p3) << '\n';
std::cout << (p4 == p5) << '\n' << (p4 == p6) << '\n';
}
解析输出。 PID是第二列空格分隔。
默认分隔符/ delmiter是空格,相邻的delims计数为1。
所以这个样本输出:
for /f
在cmd行解析
> tasklist | findstr /i "cmd.exe"
cmd.exe 14924 Console 9 6.008 K
或批量生产:
for /f "tokens=2" %A in ('tasklist ^| findstr /i "cmd.exe" 2^>NUL') do @Set "PID=%A"
cmd.exe有PID(s)14924,11268,3652
最后一个可能是@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%
本身使用的临时文件。
答案 2 :(得分:0)
我不确定你在期待什么。可能有几个cmd
个shell正在运行。如果他们正在运行程序,他们的窗口标题通常会更改。
获取cmd进程和PID(Id字段)很容易。窗口标题也可用。
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
仅显示PID是很容易的。但是,你想要哪一个?
PS C:\src\t\s1> Get-Process | Where-Object { $_.ProcessName -eq 'cmd' } | ForEach-Object { $_.Id }
2808
7232