我想创建一个bat脚本,只有在运行的cmd.exe少于2次时才会执行操作。我设法找到一个解决方案,将出现次数存储在临时文件中,但我发现它非常不优雅。所以我的问题是如何在没有临时文件的情况下如下所示,而是将@TASKLIST | FIND /I /C "%_process%"
给出的出现次数存储在变量中。我看到可能有一个for循环的解决方案,但我无法让它工作,无论如何我真的更喜欢基于SET
的解决方案(如果可能的话)。
@SET _process=cmd.exe
@SET _temp_file=tempfiletodelete.txt
@TASKLIST | FIND /I /C "%_process%" > %_temp_file%
@SET /p _count=<%_temp_file%
@DEL /f %_temp_file%
@IF %_count% LSS 2 (
@ECHO action 1
) ELSE (
@ECHO action 2
)
编辑:此问题类似于Save output from FIND command to variable,但我无法将解决方案应用于我的问题,我想知道是否可以使用没有for循环的解决方案。
答案 0 :(得分:3)
带有选项/F
的命令 FOR 和另外由'
括起来的命令或命令行指定为 set (括号内的字符串)可以用于在一行上处理具有多个命令的命令或命令行的输出。
您可以使用此批处理文件:
@ECHO OFF
SET "_process=cmd.exe"
FOR /F %%I IN ('%SystemRoot%\System32\tasklist.exe /FI "IMAGENAME eq %_process%" ^| %SystemRoot%\System32\find.exe /I /C "%_process%"') DO SET "_count=%%I"
IF /I "%_process%" == "cmd.exe" SET /A _count-=1
IF %_count% LSS 2 (
ECHO action 1
) ELSE (
ECHO action 2
)
命令 FOR 在没有可见控制台窗口cmd.exe /C
的后台运行命令行:
C:\Windows\System32\tasklist.exe /FI "IMAGENAME eq cmd.exe" | C:\Windows\System32\find.exe /I /C "cmd.exe"
TASKLIST 选项/FI "IMAGENAME eq cmd.exe"
已将 TASKLIST 的输出过滤为具有图片名称(=可执行文件名称)cmd.exe
的进程。这样可以更快地进行进一步处理,并避免将文件名为totalcmd.exe
的正在运行的进程计为cmd.exe
,与所涉及的命令行一样。
为处理 STDOUT 而编写的 TASKLIST 输出被重定向到处理命令 FIND 的 STDIN 处理行和任意位置包含cmd.exe
的行。 FIND 最后输出包含搜索字符串的行数,以处理在后台运行的命令进程的 STDOUT 。
重定向运算符|
必须使用 FOR 命令行上的符号字符^
进行转义,以便在执行命令之前Windows命令解释程序处理此命令行时将其解释为文字字符 FOR ,它在后台启动的单独命令进程中执行嵌入式命令行。
/F
的 FOR 会捕获为处理执行命令进程的 STDOUT 而编写的所有内容并处理每一行。在这种情况下,仅包含一个数字的 FOR 只捕获一行。因此,使用命令 SET 将 FOR 分配给循环变量I
的编号分配给环境变量_count
时,不需要其他选项。
此批处理文件的目标是计算已运行的cmd.exe
进程数。由于 TASKLIST 和 FIND 的命令行在背景中由 FOR 执行并再使用一个cmd.exe
进程,因此有必要使用SET /A _count-=1
计算的算术表达式将计数减1以获得正确的结果。只需计算cmd.exe
个进程的数量,就需要减1。没有必要进行任何其他过程。
要了解使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完全阅读为每个命令显示的所有帮助页面。
echo /?
find /?
for /?
if /?
set /?
tasklist /?
答案 1 :(得分:3)
你会这样做,在TaskList
循环中使用For
:
@Set "_process=cmd.exe"
@For /F %%A In ('TaskList^|Find /C /I "%_process%"'
) Do @If %%A Lss 2 (Echo Action 1) Else Echo Action 2
@Pause
您也可以使用WMIC
执行类似的操作:
@Set "_process=cmd.exe"
@For /F %%A In ('WMIC Process Get Name^|Find /C "%_process%"'
) Do @If %%A Lss 2 (Echo Action 1) Else Echo Action 2
@Pause
可以进一步细化这些以确保包含字符串而不是匹配字符串的进程不计算在内:
@Set "_process=cmd.exe"
@For /F %%A In ('TaskList /FI "ImageName Eq "%_Process%""^|Find /C "."'
) Do @If %%A Lss 2 (Echo Action 1) Else Echo Action 2
@Pause
@Set "_process=cmd.exe"
@For /F %%A In (
'WMIC Process Where "Name='%_process%'" Get Name^|Find /C "."'
) Do @If %%A Lss 2 (Echo Action 1) Else Echo Action 2
@Pause
注意:
如果您确实正在检查cmd.exe
进程,请注意For
循环括号内的命令是在新的内部生成的cmd.exe
实例,(从而增加了1
的数量)