正如我刚刚发现的,SET
的行为对于 .bat
和 .cmd
是不同的。我的实验表明,SET
的行为由启动批处理文件的扩展名(.bat 或 .cmd)决定,而不是由 SET
语句所在的文件扩展名决定。
这是 Windows NT CMD 批处理脚本引擎的一个模糊角落,Ben Hoffstein talks about it a bit .而我想知道,我的结论是否正确?或者,Microsoft 文档是否在某处正式讨论过这个问题?
我也想知道,有没有办法查看,甚至改变当前的模式?bat模式还是cmd模式?如果两者都不是,我必须接受这样一个事实,即我们批处理脚本作者(尤其是将批处理编写为函数时)不能做出任何假设。
下面是我的实验
从 Windows 7 SP1 运行。
淋浴器.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 相同。
启动子命令.bat
call showerr.cmd
开始subbat.cmd
call showerr.bat
结果如下:
最佳答案
这并不让我感到惊讶,尽管我之前从未测试过这个特定点......
以下信息来 self 的个人经历。据我所知,这在任何地方都没有记录
通过 call subFile.bat
调用的“子程序”就是我所说的内部子程序。它继承来自其父级的几种状态,如“回声开/关”等。现在,我知道它也继承了“BAT|CMD”模式。
当然,内部子程序与其父程序共享的最广为人知的值是环境变量。
通过 cmd/C subFile.bat
调用的子程序是一个外部子程序。当它启动时,它有一组新的几个状态的初始值,包括“BAT|CMD”模式。
查看此测试:
开始-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
) 称为覆盖:它替换各个方面的调用程序。
在 this answer 的表 3 中简要描述了当它们被放置在 BAT 或 CMD 文件中时改变它们修改 %errorlevel% 方式的命令。 .
关于batch-file - .bat 和 .cmd 在 ERRORLEVEL 上不同,谁决定 SET 的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71477056/