ERRORLEVEL 与 %ERRORLEVEL% 与感叹号 ERRORLEVEL 感叹号
ERRORLEVEL vs %ERRORLEVEL% vs exclamation mark ERRORLEVEL exclamation mark
我想我对 ERRORLEVEL 与 %ERRORLEVEL% 有基本的了解,但是 !ERRORLEVEL!让我困惑。
我正在制作一个调用可执行文件的脚本,然后是 tasklist 以查看它是否 运行,然后 taskkill 将其杀死,如果是,然后尝试输出错误级别并为其他 exe 和我重复我意识到我真的不明白批量错误级别。
我设置了一个等于 !errorlevel! 的变量!
然后在回显中使用不带引号的变量,当设置后出现错误时,变量从一个 uint16 更改为另一个 uint16,就像它对真实变量的引用而不是副本。我要复印件。有人可以解释一下这些人之间的区别吗?
更新:
这是我正在处理的片段。
for %%P in (%executableList%) do (
echo ----------------------------------------------------------------------------------
set exeErrorlevel=0
set running=false
start %%~fP
set exeErrorlevel=!ERRORLEVEL!
rem for debugging purposes
echo %%~nP%%~xP older errorlevel %ERRORLEVEL%
echo %%~nP%%~xP newer errorlevel !ERRORLEVEL!
echo before tasklist running var is : !running!
tasklist /FI "IMAGENAME eq %%~fP" | find /I /N /C "%%~fP" >nul && set running=true
echo after tasklist is running var is: !running!
if !running! equ true (
echo %%~nP%%~xP Program is running
taskkill /F /IM %%~nP%%~xP /T
echo %%~nP%%~xP Program was killed
if !exeErrorlevel! == 0 (
echo %passString% %%~nP%%~xP process was started and killed safely
echo %passString% %%~nP%%~xP process was started and killed safely >>%outputfile%
) else (
echo %failString% %%~nP%%~xP process was killed with errorcode !exeErrorlevel!
echo %failString% %%~nP%%~xP process was killed with errorcode !exeErrorlevel! >>%outputfile%
)
) else (
if !exeErrorlevel! == 0 (
echo %passString% %%~nP%%~xP process exited safely
echo %passString% %%~nP%%~xP process exited safely >>%outputfile%
) else (
taskkill /F /IM %%~nP%%~xP /T
echo %failString% %%~nP%%~xP process abruptly exited with errorcode !exeErrorlevel!
echo %failString% %%~nP%%~xP process abruptly exited with errorcode !exeErrorlevel! >>%outputfile%
)
)
echo. >>%outputfile%
)
我需要确保 exeErrorlevel 在某个时间点有错误级别的副本 - 我只想捕获来自 exe 的错误,而不是来自 tasklist/find/taskill 的 success/failure。我担心 exeerrorlevel 由于延迟扩展而在执行时访问延迟错误级别。也许应该改为设置 exeErrorlevel=%errorlevel% 。在我回显旧变量和新变量的行中,通常 return 不同的整数?在我所有的测试运行中,%errorlevel% 似乎通常是 return 0 而 !errorlevel!对于退出代码错误的可执行文件,始终不为零。
错误级别
errorlevel
是一个动态变量的名称(它不放在环境块中,而是保存在内存中),它存储先前执行的 process/command 的退出代码(如果它设置值,读 , , and here).
if
命令允许使用if errorlevel n
语法来检查errorlevel
变量的值是否大于或等于n
,而不涉及批解析器检索变量的值。
但是,如果我们让批解析器处理变量值,%errorlevel%
只是对存储在变量中的值的引用,即读取操作。就和!errorlevel!
一样。两者之间的主要区别是 when 取值取决于 rules on variable expansion.
使用if errorlevel
和获取变量中的值有很大区别:
- 变量读取操作将检查环境块是否包含具有指定名称的变量。
if
构造不会进行此测试。
如果您执行类似 set errorlevel=10
的操作,则不会使用 %errorlevel%
或 !errorlevel!
检索动态 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
是什么?),而是 [= 的退出代码31=] 命令。
第 6 行:由于删除了 %errorlevel%
读取操作,此行将回显 do
子句之前存储在 errorlevel
变量中的值开始执行了。
第 7 行:检索 errorlevel
变量的当前值。在这里,我们可能会遇到问题。正在执行的脚本是如何命名的? .bat
和 .cmd
是有区别的。如果这是一个 .cmd
文件,第 4 行中的 set
命令将清除(设置为 0)变量 errorlevel
,但如果它是 errorlevel
,则不会更改 errorlevel
一个 .bat
文件。
第 11、14、21 行:如所见,exeErrorlevel
变量不包含有效值。不,将行更改为 !errorlevel!
不会检索进程的退出代码,而是检索 taskkill
.
的退出代码
为了能够检索进程的退出代码/错误级别,我们需要等待它结束。如果你需要启动进程,如果它保持 运行ning 杀死它,并且在这两种情况下检索退出代码,直接调用可执行文件或使用 start "" /wait programName
,并且 运行 杀死进程并行(例如 start /b "" monitor.bat programName
或启动程序之前的类似内容)。主进程将等待并检索退出代码。监控进程处理杀戮。
我想我对 ERRORLEVEL 与 %ERRORLEVEL% 有基本的了解,但是 !ERRORLEVEL!让我困惑。
我正在制作一个调用可执行文件的脚本,然后是 tasklist 以查看它是否 运行,然后 taskkill 将其杀死,如果是,然后尝试输出错误级别并为其他 exe 和我重复我意识到我真的不明白批量错误级别。
我设置了一个等于 !errorlevel! 的变量! 然后在回显中使用不带引号的变量,当设置后出现错误时,变量从一个 uint16 更改为另一个 uint16,就像它对真实变量的引用而不是副本。我要复印件。有人可以解释一下这些人之间的区别吗?
更新: 这是我正在处理的片段。
for %%P in (%executableList%) do (
echo ----------------------------------------------------------------------------------
set exeErrorlevel=0
set running=false
start %%~fP
set exeErrorlevel=!ERRORLEVEL!
rem for debugging purposes
echo %%~nP%%~xP older errorlevel %ERRORLEVEL%
echo %%~nP%%~xP newer errorlevel !ERRORLEVEL!
echo before tasklist running var is : !running!
tasklist /FI "IMAGENAME eq %%~fP" | find /I /N /C "%%~fP" >nul && set running=true
echo after tasklist is running var is: !running!
if !running! equ true (
echo %%~nP%%~xP Program is running
taskkill /F /IM %%~nP%%~xP /T
echo %%~nP%%~xP Program was killed
if !exeErrorlevel! == 0 (
echo %passString% %%~nP%%~xP process was started and killed safely
echo %passString% %%~nP%%~xP process was started and killed safely >>%outputfile%
) else (
echo %failString% %%~nP%%~xP process was killed with errorcode !exeErrorlevel!
echo %failString% %%~nP%%~xP process was killed with errorcode !exeErrorlevel! >>%outputfile%
)
) else (
if !exeErrorlevel! == 0 (
echo %passString% %%~nP%%~xP process exited safely
echo %passString% %%~nP%%~xP process exited safely >>%outputfile%
) else (
taskkill /F /IM %%~nP%%~xP /T
echo %failString% %%~nP%%~xP process abruptly exited with errorcode !exeErrorlevel!
echo %failString% %%~nP%%~xP process abruptly exited with errorcode !exeErrorlevel! >>%outputfile%
)
)
echo. >>%outputfile%
)
我需要确保 exeErrorlevel 在某个时间点有错误级别的副本 - 我只想捕获来自 exe 的错误,而不是来自 tasklist/find/taskill 的 success/failure。我担心 exeerrorlevel 由于延迟扩展而在执行时访问延迟错误级别。也许应该改为设置 exeErrorlevel=%errorlevel% 。在我回显旧变量和新变量的行中,通常 return 不同的整数?在我所有的测试运行中,%errorlevel% 似乎通常是 return 0 而 !errorlevel!对于退出代码错误的可执行文件,始终不为零。
错误级别
errorlevel
是一个动态变量的名称(它不放在环境块中,而是保存在内存中),它存储先前执行的 process/command 的退出代码(如果它设置值,读
if
命令允许使用if errorlevel n
语法来检查errorlevel
变量的值是否大于或等于n
,而不涉及批解析器检索变量的值。
但是,如果我们让批解析器处理变量值,%errorlevel%
只是对存储在变量中的值的引用,即读取操作。就和!errorlevel!
一样。两者之间的主要区别是 when 取值取决于 rules on variable expansion.
使用if errorlevel
和获取变量中的值有很大区别:
- 变量读取操作将检查环境块是否包含具有指定名称的变量。
if
构造不会进行此测试。
如果您执行类似 set errorlevel=10
的操作,则不会使用 %errorlevel%
或 !errorlevel!
检索动态 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
是什么?),而是 [= 的退出代码31=] 命令。第 6 行:由于删除了
%errorlevel%
读取操作,此行将回显do
子句之前存储在errorlevel
变量中的值开始执行了。第 7 行:检索
errorlevel
变量的当前值。在这里,我们可能会遇到问题。正在执行的脚本是如何命名的?.bat
和.cmd
是有区别的。如果这是一个.cmd
文件,第 4 行中的set
命令将清除(设置为 0)变量errorlevel
,但如果它是errorlevel
,则不会更改errorlevel
一个.bat
文件。第 11、14、21 行:如所见,
exeErrorlevel
变量不包含有效值。不,将行更改为!errorlevel!
不会检索进程的退出代码,而是检索taskkill
. 的退出代码
为了能够检索进程的退出代码/错误级别,我们需要等待它结束。如果你需要启动进程,如果它保持 运行ning 杀死它,并且在这两种情况下检索退出代码,直接调用可执行文件或使用 start "" /wait programName
,并且 运行 杀死进程并行(例如 start /b "" monitor.bat programName
或启动程序之前的类似内容)。主进程将等待并检索退出代码。监控进程处理杀戮。