哪些 cmd.exe 内部命令在成功后将 ERRORLEVEL 清除为 0?
Which cmd.exe internal commands clear the ERRORLEVEL to 0 upon success?
在 Windows 批处理脚本中处理错误的常用方法是使用
if errorlevel 1 ...
或 if %errorlevel% neq 0 ...
。通常人们希望错误处理代码保留 ERRORLEVEL。
我相信所有外部命令总是会导致 ERRORLEVEL 被设置为某个值,因此错误处理代码必须在执行外部命令之前将 ERRORLEVEL 保存在环境变量中。
但是内部命令呢?问题是,一些内部命令在成功时将 ERRORLEVEL 清除为 0,而有些则没有。而且我找不到任何说明哪些命令执行什么操作的文档。
所以问题是,哪些内部命令在成功后将 ERRORLEVEL 清除为 0?这是 不是 关于返回的 ERRORLEVEL 代码的一般问题,但严格来说是关于成功结果的问题。
像What is the easiest way to reset ERRORLEVEL to zero? and Windows batch files: .bat vs .cmd?这样的帖子给出了部分答案。但是我从来没有见过全面的榜单。
注: 多年来我一直对此感到好奇。所以我最终决定 运行 进行一系列实验并得出一个明确的答案。我发布此问答是为了分享我的发现。
此答案基于我 运行 在 Windows 10 下的实验。我怀疑与使用 cmd.exe 的早期 Windows 版本存在差异, 但这是可能的。
另请注意 - 当内部命令遇到错误时,此答案不会尝试记录 ERRORLEVEL 结果(除了有关 DEL 和 ERASE 的一丁点)
不仅命令之间存在差异,而且单个命令的行为也可能不同,具体取决于它是来自命令行的 运行 还是在具有 .bat
扩展名的批处理脚本中,或者来自带有 .cmd
扩展名的批处理脚本。
无论上下文如何,以下命令集都不会在成功后将 ERRORLEVEL 清除为 0,而是保留之前的 ERRORLEVEL:
- 中断
- CLS
- 回声
- 结束本地
- FOR :显然,DO 子句中的命令可能会设置 ERRORLEVEL,但至少一次迭代的成功 FOR 不会自行将 ERRORLEVEL 设置为 0。
- 转到
- IF : 显然,IF 执行的命令可能会设置 ERRORLEVEL,但成功的 IF 不会自行将 ERRORLEVEL 设置为 0。
- 按键
- 暂停
- POPD
- 研发
- REM
- RMDIR
- 转变
- 开始
- 标题
无论上下文如何,下一组命令总是在成功时将 ERRORLEVEL 清除为 0:
- 光盘
- CHDIR
- 颜色
- 复制
- 日期
- DEL:始终清除 ERRORLEVEL,即使 DEL 失败 (除非 运行 没有任何文件参数).
- 目录
- ERASE:始终清除 ERRORLEVEL,即使 ERASE 失败。 (除非 运行 没有任何文件参数).
- MD
- MKDIR
- MKLINK
- 移动
- PUSHD
- 任
- 重命名
- 设置本地
- 时间
- 类型
- VER
- 验证
- 成交量
然后,如果从命令行或在具有 .bat
扩展名的脚本中发出,这些命令不会在成功时清除 ERRORLEVEL,但如果从具有扩展名的脚本发出,则将 ERRORLEVEL 清除为 0 .cmd
扩展名。有关详细信息,请参阅 https://whosebug.com/a/148991/1012053 and https://groups.google.com/forum/#!msg/microsoft.public.win2000.cmdprompt.admin/XHeUq8oe2wk/LIEViGNmkK0J。
- 协会
- DPATH
- FTYPE
- 路径
- 提示
- 设置
最后,有些命令不完全属于前面的任何类别:
CALL :如果调用了 :routine 或批处理脚本,则 ERRORLEVEL 仅由调用的脚本或 :routine 控制。但是,如果 CALLed 命令没有以其他方式设置它,则对命令的任何其他类型的成功 CALL 将始终将 ERRORLEVEL 清除为 0。
示例:call echo OK
.
EXIT :如果在没有 /B
的情况下使用,则 cmd.exe session 终止并且不再有 ERRORLEVEL,只有 cmd.exe return代码。显然 EXIT /B 0
将 ERRORLEVEL 清除为 0,但是没有值的 EXIT /B
会保留先前的 ERRORLEVEL。
我相信这说明了所有内部命令,除非有我遗漏的未记录的命令。
您对 CALL
命令的描述不完整:
CALL : Clears ERRORLEVEL if the CALLed command does not otherwise set it.
Example: call echo OK
.
检查这个小例子:
@echo off
call :setTwo
echo Set two: %errorlevel%
call :preserve
echo Preserve: %errorlevel%
call echo Reset
echo Reset: %errorlevel%
call :subNotExists 2> NUL
echo Sub not exist: %errorlevel%
goto :EOF
:setTwo
exit /B 2
:preserve
echo Preserve
exit /B
输出:
Set two: 2
Preserve
Preserve: 2
Reset
Reset: 0
Sub not exist: 1
CALL
描述应该是这样的:
- CALL:如果 CALLed 命令没有设置它,则清除 ERRORLEVEL。示例:
call echo OK
,但如果调用的命令是子程序,它会保留先前的 ERRORLEVEL。如果调用的子程序不存在,它会将 ERRORLEVEL 设置为 1。
在 Windows 批处理脚本中处理错误的常用方法是使用
if errorlevel 1 ...
或 if %errorlevel% neq 0 ...
。通常人们希望错误处理代码保留 ERRORLEVEL。
我相信所有外部命令总是会导致 ERRORLEVEL 被设置为某个值,因此错误处理代码必须在执行外部命令之前将 ERRORLEVEL 保存在环境变量中。
但是内部命令呢?问题是,一些内部命令在成功时将 ERRORLEVEL 清除为 0,而有些则没有。而且我找不到任何说明哪些命令执行什么操作的文档。
所以问题是,哪些内部命令在成功后将 ERRORLEVEL 清除为 0?这是 不是 关于返回的 ERRORLEVEL 代码的一般问题,但严格来说是关于成功结果的问题。
像What is the easiest way to reset ERRORLEVEL to zero? and Windows batch files: .bat vs .cmd?这样的帖子给出了部分答案。但是我从来没有见过全面的榜单。
注: 多年来我一直对此感到好奇。所以我最终决定 运行 进行一系列实验并得出一个明确的答案。我发布此问答是为了分享我的发现。
此答案基于我 运行 在 Windows 10 下的实验。我怀疑与使用 cmd.exe 的早期 Windows 版本存在差异, 但这是可能的。
另请注意 - 当内部命令遇到错误时,此答案不会尝试记录 ERRORLEVEL 结果(除了有关 DEL 和 ERASE 的一丁点)
不仅命令之间存在差异,而且单个命令的行为也可能不同,具体取决于它是来自命令行的 运行 还是在具有 .bat
扩展名的批处理脚本中,或者来自带有 .cmd
扩展名的批处理脚本。
无论上下文如何,以下命令集都不会在成功后将 ERRORLEVEL 清除为 0,而是保留之前的 ERRORLEVEL:
- 中断
- CLS
- 回声
- 结束本地
- FOR :显然,DO 子句中的命令可能会设置 ERRORLEVEL,但至少一次迭代的成功 FOR 不会自行将 ERRORLEVEL 设置为 0。
- 转到
- IF : 显然,IF 执行的命令可能会设置 ERRORLEVEL,但成功的 IF 不会自行将 ERRORLEVEL 设置为 0。
- 按键
- 暂停
- POPD
- 研发
- REM
- RMDIR
- 转变
- 开始
- 标题
无论上下文如何,下一组命令总是在成功时将 ERRORLEVEL 清除为 0:
- 光盘
- CHDIR
- 颜色
- 复制
- 日期
- DEL:始终清除 ERRORLEVEL,即使 DEL 失败 (除非 运行 没有任何文件参数).
- 目录
- ERASE:始终清除 ERRORLEVEL,即使 ERASE 失败。 (除非 运行 没有任何文件参数).
- MD
- MKDIR
- MKLINK
- 移动
- PUSHD
- 任
- 重命名
- 设置本地
- 时间
- 类型
- VER
- 验证
- 成交量
然后,如果从命令行或在具有 .bat
扩展名的脚本中发出,这些命令不会在成功时清除 ERRORLEVEL,但如果从具有扩展名的脚本发出,则将 ERRORLEVEL 清除为 0 .cmd
扩展名。有关详细信息,请参阅 https://whosebug.com/a/148991/1012053 and https://groups.google.com/forum/#!msg/microsoft.public.win2000.cmdprompt.admin/XHeUq8oe2wk/LIEViGNmkK0J。
- 协会
- DPATH
- FTYPE
- 路径
- 提示
- 设置
最后,有些命令不完全属于前面的任何类别:
CALL :如果调用了 :routine 或批处理脚本,则 ERRORLEVEL 仅由调用的脚本或 :routine 控制。但是,如果 CALLed 命令没有以其他方式设置它,则对命令的任何其他类型的成功 CALL 将始终将 ERRORLEVEL 清除为 0。
示例:call echo OK
.EXIT :如果在没有
/B
的情况下使用,则 cmd.exe session 终止并且不再有 ERRORLEVEL,只有 cmd.exe return代码。显然EXIT /B 0
将 ERRORLEVEL 清除为 0,但是没有值的EXIT /B
会保留先前的 ERRORLEVEL。
我相信这说明了所有内部命令,除非有我遗漏的未记录的命令。
您对 CALL
命令的描述不完整:
CALL : Clears ERRORLEVEL if the CALLed command does not otherwise set it. Example:
call echo OK
.
检查这个小例子:
@echo off
call :setTwo
echo Set two: %errorlevel%
call :preserve
echo Preserve: %errorlevel%
call echo Reset
echo Reset: %errorlevel%
call :subNotExists 2> NUL
echo Sub not exist: %errorlevel%
goto :EOF
:setTwo
exit /B 2
:preserve
echo Preserve
exit /B
输出:
Set two: 2
Preserve
Preserve: 2
Reset
Reset: 0
Sub not exist: 1
CALL
描述应该是这样的:
- CALL:如果 CALLed 命令没有设置它,则清除 ERRORLEVEL。示例:
call echo OK
,但如果调用的命令是子程序,它会保留先前的 ERRORLEVEL。如果调用的子程序不存在,它会将 ERRORLEVEL 设置为 1。