As I just find out, SET
's behavior is different for .bat
and for .cmd
. My experiment shows that, SET
's behavior is determined by the startup batch file's extension(.bat or .cmd), NOT by the file extension that SET
statement resides in.
This is such a vague corner of Windows NT CMD batch script engine,
CodePudding user response:
This didn't surprised me, although I never tested this particular point before...
The following information comes from my personal experiences. As far as I know, this is not documented at any place
A "subroutine" called via call subFile.bat
is what I called internal subroutine. It inherits several status from its parent, like the "echo on/off" and others. Now, I know that it also inherits the "BAT|CMD" mode.
Of course, the most known values that an internal subroutine shares with its parent are the environment variables.
A subroutine called via cmd /C subFile.bat
is an external subroutine. When it starts, it have a fresh set of initial values of several status, including the "BAT|CMD" mode.
See this test:
start-SubBat.cmd
call ShowErr.bat
cmd /C ShowErr.bat
Output:
Err=0
Err=40
start-SubCmd.bat
call ShowErr.cmd
cmd /C ShowErr.cmd
Output:
Err=40
Err=0
The way to know what is the "current mode" is very simple: first set the errorlevel to 1 via verify other 2>NUL
(that is the MS suggested method to do that) and then execute set var=1
. If the new %errorlevel% is 1, you are in BAT mode; if it is 0, you are in CMD mode.
Just to complete this topic, a "subroutine" executed via its name with no call
nor cmd /C
commands (i.e. just subFile.bat
) is called overlay: it replaces the calling program in every aspect.
The commands that change the way they modifies the %errorlevel% when they are placed in a BAT or CMD file are briefly described under Table 3 at this answer.
CodePudding user response:
I'd suggest that running .bat
, the set
is leaving errorlevel
unchanged, but this has been "corrected" for .cmd
to setting errorlevel
to 0 as the set
succeeded.