简体   繁体   English

BATCH - 将命令输出存储到变量

[英]BATCH — Store command output to variable

I would like to make a bat script that performs an action only if fewer than 2 occurrences of cmd.exe are running.我想制作一个 bat 脚本,仅当 cmd.exe 运行的次数少于 2 时才执行操作。 I managed to find a solution that stores the occurrence count in a temporary file, but I find it very inelegant.我设法找到了一个将出现次数存储在临时文件中的解决方案,但我觉得它非常不雅。 So my question is how to do the same as below without a temporary file, but rather by storing the occurence count given by @TASKLIST | FIND /I /C "%_process%"所以我的问题是如何在没有临时文件的情况下执行与下面相同的操作,而是通过存储@TASKLIST | FIND /I /C "%_process%"给出的出现计数来完成。 @TASKLIST | FIND /I /C "%_process%" in a variable.在变量中@TASKLIST | FIND /I /C "%_process%" I saw that there may be a solution with a for loop, but I couldn't get it to work and anyway I would really prefer a solution based on SET (if this is possible).我看到可能有一个带有 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
)

Edit: This question is similar to Save output from FIND command to variable , but I wasn't able to apply the solution to my problem and I wanted to know if a solution without a for loop is possible.编辑:这个问题类似于Save output from FIND command to variable ,但我无法将解决方案应用于我的问题,我想知道是否可以使用没有 for 循环的解决方案。

The command FOR with option /F and the command or command line specified as set (string inside parentheses) additionally enclosed by ' can be used for processing the output of a command or a command line with multiple commands on one line.带有选项/F的命令FOR和指定为集合(括号内的字符串)另外用'括起来的命令或命令行可用于处理一个命令或一行包含多个命令的命令行的输出。

You can use this batch file:您可以使用此批处理文件:

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

The command FOR runs in background without a visible console window cmd.exe /C with the command line:命令FOR在后台运行,没有可见的控制台窗口cmd.exe /C使用命令行:

C:\Windows\System32\tasklist.exe /FI "IMAGENAME eq cmd.exe" | C:\Windows\System32\find.exe /I /C "cmd.exe"

TASKLIST option /FI "IMAGENAME eq cmd.exe" filters the output of TASKLIST already to processes with image name (= name of executable) cmd.exe . TASKLIST选项/FI "IMAGENAME eq cmd.exe"输出过滤到具有图像名称(= 可执行文件名称) cmd.exe的进程。 This makes further processing faster and avoids that a running process with file name totalcmd.exe is counted as cmd.exe as the command line in question does.这使得进一步的处理更快,并避免文件名为totalcmd.exe的正在运行的进程被视为cmd.exe ,就像相关命令行一样。

The output of TASKLIST written to handle STDOUT is redirected to handle STDIN of command FIND which processes the lines and counts the lines containing cmd.exe anywhere in line.为处理STDOUT而编写的TASKLIST的输出被重定向到处理命令FINDSTDIN ,该命令处理行并计算行中任何位置包含cmd.exe的行。 FIND outputs finally the number of lines containing searched string to handle STDOUT of command process running in background. FIND最终输出包含搜索字符串的行数,以处理在后台运行的命令进程的STDOUT

The redirection operator |重定向运算符| must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded command line with using a separate command process started in background.当 Windows 命令解释器在执行命令FOR之前使用在后台启动的单独命令进程执行嵌入式命令行时处理此命令行时,必须在FOR命令行上使用脱字符^进行转义,以将其解释为文字字符。

FOR with option /F captures everything written to handle STDOUT of executed command process and processes each line.带有选项/FFOR捕获为处理已执行命令进程的STDOUT而编写的所有内容并处理每一行。 In this case just one line is captured by FOR containing just a number.在这种情况下,仅包含一个数字的FOR仅捕获一行。 Therefore no additional options are needed to assign the number assigned to loop variable I by FOR to environment variable _count using command SET .因此,无需其他选项即可使用命令SETFOR分配给循环变量I的数字分配给环境变量_count

The goal of this batch file is counting the number of cmd.exe processes already running.此批处理文件的目标是计算已运行的cmd.exe进程的数量。 As the command line with TASKLIST and FIND is executed by FOR in background with using one more cmd.exe process, it is necessary to subtract the count by one to get the correct result using an arithmetic expression evaluated with SET /A _count-=1 .由于带有TASKLISTFIND的命令行是由FOR在后台使用另外一个cmd.exe进程执行的,因此必须使用SET /A _count-=1计算的算术表达式将计数减一以获得正确的结果. This decrement by one is needed only for counting right the number of cmd.exe processes.仅在正确计算cmd.exe进程的数量时才需要减一。 It is not necessary for any other process.任何其他过程都不需要。

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.要了解使用的命令及其工作原理,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。

  • echo /?
  • find /?
  • for /?
  • if /?
  • set /?
  • tasklist /?

You would do it like this, using TaskList in a For loop:你会这样做,在For循环中使用TaskList

@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

You can also perform a similar thing using WMIC too:您也可以使用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

These could be refined further to ensure processes containing the string as opposed to matching it aren't counted:这些可以进一步细化以确保不计算包含字符串而不是匹配它的进程:

@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

Note :注意
If you're really checking the cmd.exe process, be aware that an the command inside the For loop parentheses is spawned within a new cmd.exe instance, (thereby increasing your count by 1 )如果您真的在检查cmd.exe进程,请注意For循环括号内的命令是在新的cmd.exe实例中生成的(从而将您的计数增加1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM