.bat 和 .cmd 在 ERRORLEVEL 上不同,谁决定 SET 的行为?
.bat and .cmd different on ERRORLEVEL, who determines SET's behavior?
我刚刚发现,SET
的行为对于 .bat
和 .cmd
是不同的。我的实验表明,SET
的行为由启动批处理文件的扩展名(.bat 或 .cmd)决定,而不是由 SET
语句所在的文件扩展名决定。
这是 Windows NT CMD 批处理脚本引擎的一个模糊角落,Ben Hoffstein talks about it a bit。而我想知道,我的结论是否正确?或者,Microsoft docs 是否在某处正式讨论过这个问题?
我也想知道,有没有办法查看,甚至改变当前的模式?bat模式还是cmd模式?如果两者都不是,我不得不接受这样一个事实,即我们批处理脚本作者(尤其是将批处理编写为函数时)不能做出任何假设。
下面是我的实验
运行 来自 Windows 7 SP1。
showerr.bat
@echo off
setlocal EnableDelayedExpansion
call :SetErrorlevel 40
set var=1
echo Err=%ERRORLEVEL%
exit /b 0
REM ==== Functions below ====
:SetErrorlevel
exit /b %1
showerr.cmd
与 showerr.bat 相同。
开始-subcmd.bat
call showerr.cmd
开始-subbat.cmd
call showerr.bat
结果如下:
我建议 运行 .bat
,set
保持 errorlevel
不变,但 .cmd
已“更正”为当 set
成功时将 errorlevel
设置为 0。
这并没有让我感到惊讶,尽管我之前从未测试过这个特定点...
以下信息来自我的个人经历。据我所知,这在任何地方都没有记录
通过call subFile.bat
调用的“子程序”就是我所说的内部子程序。它继承 其父级的几个状态,如“echo on/off”等。现在,我知道它也继承了“BAT|CMD”模式。
当然,内部子例程与其父例程共享的最广为人知的值是环境变量。
通过 cmd /C subFile.bat
调用的子例程是 外部子例程 。当它启动时,它有一组新的几个状态的初始值,包括“BAT|CMD”模式。
查看此测试:
start-SubBat.cmd
call ShowErr.bat
cmd /C ShowErr.bat
输出:
Err=0
Err=40
start-SubCmd.bat
call ShowErr.cmd
cmd /C ShowErr.cmd
输出:
Err=40
Err=0
知道什么是“当前模式”的方法非常简单:首先通过 verify other 2>NUL
将错误级别设置为 1(这是 MS 建议的方法),然后执行 set var=1
.如果新的 %errorlevel% 为 1,则处于 BAT 模式;如果为0,则表示您处于CMD模式。
为了完成这个主题,一个“子程序”通过它的名字执行,没有 call
也没有 cmd /C
命令(即只有 subFile.bat
)被称为 overlay :在各个方面替代调用程序
Table 3 在 .
我刚刚发现,SET
的行为对于 .bat
和 .cmd
是不同的。我的实验表明,SET
的行为由启动批处理文件的扩展名(.bat 或 .cmd)决定,而不是由 SET
语句所在的文件扩展名决定。
这是 Windows NT CMD 批处理脚本引擎的一个模糊角落,Ben Hoffstein talks about it a bit。而我想知道,我的结论是否正确?或者,Microsoft docs 是否在某处正式讨论过这个问题?
我也想知道,有没有办法查看,甚至改变当前的模式?bat模式还是cmd模式?如果两者都不是,我不得不接受这样一个事实,即我们批处理脚本作者(尤其是将批处理编写为函数时)不能做出任何假设。
下面是我的实验
运行 来自 Windows 7 SP1。
showerr.bat
@echo off
setlocal EnableDelayedExpansion
call :SetErrorlevel 40
set var=1
echo Err=%ERRORLEVEL%
exit /b 0
REM ==== Functions below ====
:SetErrorlevel
exit /b %1
showerr.cmd
与 showerr.bat 相同。
开始-subcmd.bat
call showerr.cmd
开始-subbat.cmd
call showerr.bat
结果如下:
我建议 运行 .bat
,set
保持 errorlevel
不变,但 .cmd
已“更正”为当 set
成功时将 errorlevel
设置为 0。
这并没有让我感到惊讶,尽管我之前从未测试过这个特定点...
以下信息来自我的个人经历。据我所知,这在任何地方都没有记录
通过call subFile.bat
调用的“子程序”就是我所说的内部子程序。它继承 其父级的几个状态,如“echo on/off”等。现在,我知道它也继承了“BAT|CMD”模式。
当然,内部子例程与其父例程共享的最广为人知的值是环境变量。
通过 cmd /C subFile.bat
调用的子例程是 外部子例程 。当它启动时,它有一组新的几个状态的初始值,包括“BAT|CMD”模式。
查看此测试:
start-SubBat.cmd
call ShowErr.bat
cmd /C ShowErr.bat
输出:
Err=0
Err=40
start-SubCmd.bat
call ShowErr.cmd
cmd /C ShowErr.cmd
输出:
Err=40
Err=0
知道什么是“当前模式”的方法非常简单:首先通过 verify other 2>NUL
将错误级别设置为 1(这是 MS 建议的方法),然后执行 set var=1
.如果新的 %errorlevel% 为 1,则处于 BAT 模式;如果为0,则表示您处于CMD模式。
为了完成这个主题,一个“子程序”通过它的名字执行,没有 call
也没有 cmd /C
命令(即只有 subFile.bat
)被称为 overlay :在各个方面替代调用程序
Table 3 在