.bat和.cmd在ERRORLEVEL上的区别,是谁确定了SET的行为?

3

我刚刚发现,SET.bat.cmd中的行为是不同的。我的实验表明,SET的行为由启动批处理文件的扩展名(.bat或.cmd)决定,而不是由SET语句所在的文件扩展名决定。

这是Windows NT CMD批处理脚本引擎的一个模糊角落,Ben Hoffstein稍微提到了一下。我想知道,我的结论是否正确?或者,在Microsoft文档中正式讨论了这个问题吗?

我还想知道,有没有办法检查或甚至更改当前的模式?是.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相同。

start-subcmd.bat

启动子命令的批处理文件。

call showerr.cmd

start-subbat.cmd

call showerr.bat

以下是结果:

结果如下:

输入图像描述

输入图像描述

2个回答

3

尽管我以前从未测试过这个特定的点,但这并不让我感到惊讶...

以下信息来自我的个人经验。据我所知,这些信息没有在任何地方记录

通过 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,然后执行 set var=1。如果新的 %errorlevel% 为1,则表示您处于BAT模式;如果为0,则表示您处于CMD模式。

补充一下,通过名称执行“子例程”而没有callcmd /C命令(即只有subFile.bat),称为覆盖:它在所有方面都替换了调用程序。

当命令被放置在BAT或CMD文件中时,会修改它们如何修改%errorlevel%的命令,简要描述在表3此答案中。


0
我建议运行 .bat 文件时,set 命令不会改变 errorlevel 的值,但是这个问题在 .cmd 文件中已经被“修正”,即当 set 命令成功执行后,errorlevel 的值被设置为 0。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接