You have found one of the few instances where the difference between .cmd
and .bat
is important.
The sample you posted works correctly, when you save that code to a file named script.bat
.
script.bat
CHOICE /C YN /N /T 10 /D N /M "Run Report Y or N?"
IF ERRORLEVEL 1 SET REPORT=RunTheReport
IF ERRORLEVEL 2 SET REPORT=DontRunIt
ECHO You chose to run %REPORT%
- When the user presses
Y
the errorlevel is set to 1. The first IF
line matches and sets REPORT=RunTheReport
. The second IF
line does not match, and the end result is Run.
- When the user presses
N
the errorlevel is set to 2. The first IF
line matches and sets REPORT=RunTheReport
. The second IF
line matches and sets REPORT=DontRunIt
. The end result is Don't Run.
In a .bat
file, the IF ERRORLEVEL
ladder will continue and execute every matching SET
line. The last matching SET
will be the one used.
If you save that same code to a file named script.cmd
CMD behaves a little bit differently. One difference is that the SET
command now sets ERRORLEVEL to 0 when it successfully sets a variable.
- When the user presses
Y
the errorlevel is set to 1. The first IF
line matches and sets REPORT=RunTheReport
. The second IF
line does not match, and the end result is Run, just like the .bat
case.
- When the user presses
N
the errorlevel is set to 2. The first IF
line matches, sets REPORT=RunTheReport
, and sets ERRORLEVEL
to 0. The second IF
line then does NOT match. The end result is also Run, which is wrong.
In a .cmd
file, only the first matching SET
line is run.
Therefore, if your file is named with a .cmd
extension, you must reverse the order of the IF ERRORLEVEL
lines, so that the correct one is the only one executed.
script.cmd
CHOICE /C YN /N /T 10 /D N /M "Run Report Y or N?"
IF ERRORLEVEL 2 SET REPORT=DontRunIt
IF ERRORLEVEL 1 SET REPORT=RunTheReport
ECHO You chose to run %REPORT%
There is an easy way to avoid this issue and make your code work in both types of file. The IF ERRORLEVEL N
syntax is deprecated. It is confusing because it matches as greater-than-or-equal, rather than equal. Instead, use the newer IF %errorlevel% EQU N
syntax.
script2.{bat|cmd}
CHOICE /C YN /N /T 10 /D N /M "Run Report Y or N?"
IF %ERRORLEVEL% EQU 1 SET REPORT=RunTheReport
IF %ERRORLEVEL% EQU 2 SET REPORT=DontRunIt
ECHO You chose to run %REPORT%