使用 Windows 批处理脚本定期检查是否有多个进程正在运行,然后如果其中任何一个进程正在运行则执行一个代码块,如果没有一个进程正在运行则执行不同的代码块,那么最好的方法是什么?
我尝试使用
for
循环并将循环内的变量设置为标志,然后使用 if
语句根据该标志的值执行代码,但它不起作用。
整个脚本较长,但我已将其简化为测试文件,仅检查基本记事本或计算器应用程序是否正在运行,以隔离问题。这是我的测试代码(不起作用):
echo off
for /L %%A in (3,-1,1) do (
set flag=no
tasklist /fi "ImageName eq notepad.exe" /fo csv 2>NUL | find /I "notepad.exe">NUL
if "%ERRORLEVEL%"=="0" (set flag=yes)
tasklist /fi "ImageName eq CalculatorApp.exe" /fo csv 2>NUL | find /I "CalculatorApp.exe">NUL
if "%ERRORLEVEL%"=="0" (set flag=yes)
if "%flag%" == "no" ( echo Flag is no ) else (echo Flag is yes)
timeout 60 /nobreak > NUL
)
现在,无论进程是否正在运行,它都会输出“Flag is no”。
我错了什么?我尝试在顶部添加
SETLOCAL ENABLEDELAYEDEXPANSION
,但没有什么区别。我还尝试重写它以使用 goto
,这在循环内不起作用,然后再次重写它以使用 call
的子例程,但这搞乱了逻辑,因为如果我不需要执行某些操作,找到进程。
有更好的方法吗?
在评论中 @Stephan 发现变量在与
ENABLEDELAYEDEXPANSION
一起使用的循环中被错误引用,这解释了为什么当我尝试它时它不起作用。
以下版本使用
ENABLEDELAYEDEXPANSION
并正确引用了变量,并且似乎可以工作:
echo off
SETLOCAL ENABLEDELAYEDEXPANSION
for /L %%A in (3,-1,1) do (
set flag=no
tasklist /fi "ImageName eq notepad.exe" /fo csv 2>NUL | find /I "notepad.exe">NUL
if "!ERRORLEVEL!"=="0" (set flag=yes)
tasklist /fi "ImageName eq CalculatorApp.exe" /fo csv 2>NUL | find /I "CalculatorApp.exe">NUL
if "!ERRORLEVEL!"=="0" (set flag=yes)
if "!flag!" == "no" ( echo Flag is no ) else (echo Flag is yes)
timeout 60 /nobreak > NUL
)
echo on
请注意,必须使用感叹号引用
ERRORLEVEL
变量以及 flag
变量。
对于那些不想使用
ENABLEDELAYEDEXPANSION
或有理由认为它对他们不起作用的人,这里有相同的功能,但将 for
循环替换为 goto
结构:
echo off
set /a i = 3
:loop
set flag=no
tasklist /fi "ImageName eq notepad.exe" /fo csv 2>NUL | find /I "notepad.exe">NUL
if "%ERRORLEVEL%"=="0" (set flag=yes)
tasklist /fi "ImageName eq CalculatorApp.exe" /fo csv 2>NUL | find /I "CalculatorApp.exe">NUL
if "%ERRORLEVEL%"=="0" (set flag=yes)
if "%flag%" == "no" ( echo Flag is no ) else (echo Flag is yes)
timeout 60 /nobreak > NUL
set /a i = %i% - 1
if %i% GEQ 1 (goto loop)
echo on
希望这对遇到类似问题的人有所帮助。