错误级别
errorlevel
是动态变量的名称(它不放置在环境块中,而是保存在内存中),用于存储先前执行的进程/命令的退出代码(如果设置了该值,则读取here https://stackoverflow.com/q/34968009/2861476, here https://stackoverflow.com/q/34987885/2861476, here https://stackoverflow.com/q/30714985/2861476 and here https://stackoverflow.com/q/41318027/2861476).
The if
命令允许使用if errorlevel n
语法来检查值是否errorlevel
变量大于或等于n
,而不涉及批处理解析器来检索变量的值。
但是,如果我们让批处理解析器处理变量值,%errorlevel%
只是对变量中存储的值的引用,即读取操作。就像!errorlevel!
。两者之间的主要区别是when该值的检索取决于rules https://stackoverflow.com/a/4095133/2861476关于变量扩展。
使用起来有很大的区别if errorlevel
或检索变量中的值:
- 变量读取操作将检查环境块是否包含具有指定名称的变量。
- The
if
构造不会进行此测试。
如果你做类似的事情set errorlevel=10
,动态errorlevel
值将不会被检索%errorlevel%
or !errorlevel!
因为环境中设置的值将隐藏动态值。但作为if errorlevel
不读取环境块,而是直接读取保存该值的内部变量,它将正常工作。
变量
批处理语法不包括让多个变量指向内存中相同值的选项,如果其中一个变量更改其值,另一个变量也会反映该更改。
这种行为可以通过正确使用变量扩展中的不同阶段来模拟,将一个变量正确设置为另一个变量的名称,并强制批处理解析器对命令执行两次传递,以便第一个变量解析为第二个变量的名称,并且到真正的价值。
你的问题
仅用于分析的简化(甚至不起作用)代码
1 for %%P in (%executableList%) do (
2
3 start %%~fP
4 set exeErrorlevel=!ERRORLEVEL!
5
6 echo %%~nP%%~xP older errorlevel %ERRORLEVEL%
7 echo %%~nP%%~xP newer errorlevel !ERRORLEVEL!
8 ....
9 if !running! equ true (
10 taskkill /F /IM %%~nP%%~xP /T
11 if !exeErrorlevel! == 0 (
12 ....
13 ) else (
14 echo process killed with errorcode !exeErrorlevel!
15 )
16 ) else (
17 if !exeErrorlevel! == 0 (
18 ....
19 ) else (
20 taskkill /F /IM %%~nP%%~xP /T
21 echo process abruptly exited with errorcode !exeErrorlevel!
22 )
23 )
第 1 行:中的代码do
子句,所有代码,都被解析。任何%var%
变量读取操作已从代码中删除,并在开始执行之前替换为变量内的值。这意味着,如果变量更改其值,您将无法检索更改后的值,因为不存在读取操作,只能检索变量中的初始值。
第 3 行:可执行文件在单独的进程中启动,无需等待进程结束。是不是重要?请参阅下一行
第 4 行:当前(使用延迟扩展)值errorlevel
变量被检索并存储在exeErrorlevel
多变的。但存储的值不是errorlevel
由可执行文件返回(单独的进程,不等待它结束,我们如何知道exit code = errorlevel
是?),但是退出代码start
命令。
第 6 行:作为%errorlevel%
读取操作被删除,这一行将回显存储在errorlevel
之前的变量do
条款开始执行。
第 7 行:当前值errorlevel
变量被检索。在这里,我们可能会遇到问题。正在执行的脚本如何命名?之间存在差异.bat
and .cmd
。论成功set
第 4 行中的命令将清除(设置为 0)errorlevel
变量,如果这是一个.cmd
文件,但不会改变errorlevel
如果它是一个.bat
file.
第 11、14、21 行:如图所示exeErrorlevel
变量不包含有效值。不,将行更改为!errorlevel!
不会检索进程的退出代码,但会检索进程的退出代码taskkill
.
为了能够检索进程的退出代码/错误级别,我们需要等待它结束。如果您需要启动该进程,如果它继续运行,则将其杀死,并且在这两种情况下检索退出代码,直接调用可执行文件或使用start "" /wait programName
,并并行运行终止进程(例如start /b "" monitor.bat programName
或启动程序之前类似的事情)。主进程将等待并检索退出代码。监控进程负责处理杀戮。