我正在尝试从它自己的命令提示符中获取 PID。但是当使用下面的命令时,我并不总是得到所需的输出。您能指出以下语句中的错误是什么吗?
cmd.exe /c title="mycmd" & tasklist /v /fo csv | findstr /i "mycmd" & dir & help
编辑:
以下命令工作正常。但是当它与另外两个命令结合使用时。没用。
cmd.exe /c title="mycmd" & tasklist /v /fo csv | findstr /i "mycmd"
附加信息:
我正在使用Java
final List<String> commands = new ArrayList<String>();
commands.add("cmd.exe");
commands.add("/C");
//.. Add more commands
ProcessBuilder pb = new ProcessBuilder(commands);
您可以使用下面的批处理文件获取cmd提示符的PID。
参考:http://social.msdn.microsoft.com/Forums/en-US/msbuild/thread/270f0842-963d-4ed9-b27d-27957628004c/
获取PID.bat
@echo off
if not defined SESSIONNAME set SESSIONNAME=Console
setlocal
set instance=%DATE% %TIME% %RANDOM%
title %instance%
for /f "usebackq tokens=2" %%a in (`tasklist /FO list /FI "SESSIONNAME eq %SESSIONNAME%" /FI "USERNAME eq %USERNAME%" /FI "WINDOWTITLE eq %instance%" ^| find /i "PID:"`)
do set PID=%%a
if not defined PID for /f "usebackq tokens=2" %%a in (`tasklist /FO list /FI "SESSIONNAME eq %SESSIONNAME%" /FI "USERNAME eq %USERNAME%" /FI "WINDOWTITLE eq Administrator: %instance%" ^| find /i "PID:"`)
do set PID=%%a
if not defined PID
echo !Error: Could not determine the Process ID of the current script. Exiting.& exit /b 1
echo PID: "%PID%"
您需要在要在子 shell 中执行的复合命令两边加上引号:
cmd.exe /c "title="mycmd" & tasklist /v /fo csv | findstr /i "mycmd" & dir & help"
如果没有引号,命令将被解析为
(cmd.exe /c title="mycmd") & (tasklist /v /fo /csv) | (findstr /i "mycmd") & (dir) & (help)
因此,当
tasklist
运行具有指定标题的 cmd.exe
实例时,已经退出。
您可能缺少一些重定向运算符。阅读更多这里。
为 CMD 窗口指定一个唯一的名称,在本例中为“test”。 “Windowstitle”是“test*”,因为执行的命令行将附加到标题中。
title test
taskkill /FI "IMAGENAME eq cmd.exe" /FI "WINDOWTITLE ne test*" /f
我发现我还必须使用带有用户名的域。
@IF NOT DEFINED SESSIONNAME (@SET SESSIONNAME=Console)
@SETLOCAL
@SET EXITCODE=0
@SET instance=%DATE% %TIME% %RANDOM%
@TITLE %instance%
@FOR /F "usebackq tokens=1,2" %%a IN (`tasklist /FO list /FI "SESSIONNAME eq %SESSIONNAME%" /FI "USERNAME eq %USERDOMAIN%\%USERNAME%" /FI "WINDOWTITLE eq %instance%" ^| FIND /I "PID:"`) DO @(
@SET PID=%%b
)
@IF NOT DEFINED PID (
@FOR /F "usebackq tokens=1,2" %%a IN (`tasklist /FO list /FI "SESSIONNAME eq %SESSIONNAME%" /FI "USERNAME eq %USERDOMAIN%\%USERNAME%" /FI "WINDOWTITLE eq Administrator: %instance%" ^| FIND /I "PID:"`) DO @(
@SET PID=%%b
)
)
@IF NOT DEFINED PID (
@ECHO ERROR: Could not determine the Process ID of the current script.
@SET EXITCODE=1
) ELSE (
@ECHO %PID%
)
@EXIT /B %EXITCODE%
这是一种优雅且防弹的方法,它利用 PowerShell,并且无法被用户检测到,因为它不需要设置或更改窗口标题(如果在批处理脚本中使用,这一点很重要)。
for /F %a in ('powershell -Command "$tempPID = (Get-WmiObject Win32_Process -Filter ProcessId=$pid).ParentProcessId; (Get-WmiObject Win32_Process -Filter ProcessId=$tempPID).ParentProcessId"') do (set "my_pid=%a")
“$pid”变量存储由 for 循环内的“powershell”命令创建的 PowerShell 进程的 PID。 PowerShell 命令的第一部分 (
$tempPID = (Get-WmiObject Win32_Process -Filter ProcessId=$pid).ParentProcessId
) 获取父进程的 PID 并将其存储到“$tempPID”变量中。但是,该父进程不是主 CMD 窗口,而是由主 CMD 创建的子 cmd.exe 进程。由于某种原因,CMD 总是为每个 for 循环创建一个新的子 cmd.exe 进程,并且主 CMD 是其父进程。所以你实际上需要获取父级的父级的PID。这是通过 PowerShell 命令的第二部分 ((Get-WmiObject Win32_Process -Filter ProcessId=$tempPID).ParentProcessId
) 完成的。
最后,正确的 PID 被捕获并存储在“my_pid”变量中。
P。 S. 如果您想在批处理脚本中使用该命令,请确保使用双百分号作为标记(“%%a”而不是“%a”)。