2

Trying to automate some DOSBox scripting for an old program, I wanted to use the exit code usually in errorlevel to control the program flow.

The input is given in a hello_db.bat file:

@echo off
set msg=Hello
echo %msg%
dir
echo errorlevel = %errorlevel%

Then DOSBox is called with dosbox hello_db.bat.

The output is:

Hello
{Listing from dir}
errorlevel = 

So the %errorlevel% expanded to an empty string instead of the exit code from the dir command, where as the first msg variable could expand correctly.

How can I make DOSBox expand the errorlevel correctly in the script?

Short answer based on through answer by @phuclv:

The requirement was to insert a pause after the command if not OK (errorlevel != 0), so ended up doing:

set errorany=0
:: Command is inserted here...
if errorlevel 1 set errorany=1

:: Make pause if not OK
if %errorany%==1 pause

2 Answers 2

3

Because %ERRORLEVEL% is not a variable in MS-DOS. It's DR-DOS and cmd-specific. They're very different things

%ERRORLEVEL%

In COMMAND.COM of DR-DOS 7.02 and higher, this pseudo-variable returns the last error level returned by an external program or the RETURN command, f.e. "0".."255". See also the identically named pseudo-variable %ERRORLEVEL% under Windows and the IF ERRORLEVEL conditional command.

https://en.wikipedia.org/wiki/Environment_variable#DOS

Like %DATE% or many other variables, they're new features of cmd.exe and require command extension to be enabled

If Command Extensions are disabled, the following dynamic variables will be not accessible:

%CD% %DATE% %TIME% %RANDOM% %ERRORLEVEL% %CMDEXTVERSION% %CMDCMDLINE% %HIGHESTNUMANODENUMBER%

https://ss64.com/nt/syntax-variables.html

If you turn off command extension for DOS compatibility you'll lose access to those variables on Windows cmd.exe


If you have to stick with MS-DOS and its command.com then the only way to get errorlevel is to use if errorlevel in descending order

...
if errorlevel 4 set errorlvl=4
if errorlevel 3 set errorlvl=3
if errorlevel 2 set errorlvl=2
if errorlevel 1 set errorlvl=1

Fortunately if you really have to deal with all 255 error codes then you don't actually have to write 255 lines of code. But it's still rather long so see [§] below if you're interested

If you can install alternative shells (by setting SHELL=\path\to\shell.com in config.sys) then there are some 3rd party shells with an errorlevel variable. For example the famous 4DOS has %_?

Most internal 4DOS commands set errorlevel values. 4DOS has internal variables for external program exit code (%?), reason for external program termination (%??), exit code last internal command (%_?) and last DOS error (%_SYSERR). Since 4DOS is able to determine values equal, less than, less or equal, greater, greater or equal, unequal to another value, it's easy to catch specific errors:

IF "%_?" NE "" GOSUB ERR_HANDLER
:ERR_HANDLER
IF %_? == 1 ...
IF %_? == 2 ...
...
RETURN

The ON ERROR... command is also available to catch (and recover from) errors.


§ How to check for every possible errorlevel:

@ECHO OFF
REM Reset variables
FOR %%A IN (1 10 100) DO SET ERR%%A=

REM Check error level hundredfolds
FOR %%A IN (0 1 2) DO IF ERRORLEVEL %%A00 SET ERR100=%%A
IF %ERR100%==2 GOTO 200
IF %ERR100%==0 IF NOT "%1"=="/0" SET ERR100=

REM Check error level tenfolds
FOR %%A IN (0 1 2 3 4 5 6 7 8 9) DO IF ERRORLEVEL %ERR100%%%A0 SET ERR10=%%A
IF "%ERR100%"=="" IF %ERR10%==0 SET ERR10=

:1
REM Check error level units
FOR %%A IN (0 1 2 3 4 5) DO IF ERRORLEVEL %ERR100%%ERR10%%%A SET ERR1=%%A
REM Modification necessary for errorlevels 250+
IF NOT ERRORLEVEL 250 FOR %%A IN (6 7 8 9) DO IF ERRORLEVEL %ERR100%%ERR10%%%A SET ERR1=%%A
GOTO End

:200
REM In case of error levels over 200 both
REM tenfolds and units are limited to 5
REM since the highest DOS error level is 255
FOR %%A IN (0 1 2 3 4 5) DO IF ERRORLEVEL 2%%A0 SET ERR10=%%A
IF ERR10==5 FOR %%A IN (0 1 2 3 4 5) DO IF ERRORLEVEL 25%%A SET ERR1=%%A
IF NOT ERR10==5 GOTO 1

:End
REM Clean up the mess and show results
SET ERRORLEV=%ERR100%%ERR10%%ERR1%
FOR %%A IN (1 10 100) DO SET ERR%%A=
ECHO ERRORLEVEL  %ERRORLEV%

Credit: https://www.robvanderwoude.com/errorlevel.php

1
  • 1
    Thanks a lot for the through answer; that is greatly appreciated :-) I have added a condensed solution to my question, to make it easier to apply for other that drop by. Commented Oct 30, 2019 at 20:30
1

You should not attempt to use %ERRORLEVEL%, as that is more recent than DOS, as @phuclv states. Instead, use the older IF ERRORLEVEL n construct, which tests for whether the error level is n or greater. This means that you should test possible error levels in descending order:

IF ERRORLEVEL 5 ...  
IF ERRORLEVEL 4 ...  
IF ERRORLEVEL 3 ...
...

You should read the section on Detecting Errorlevel at Errorlevel at SS64, paying specific attention to the beginning where it discusses compatibility with DOS.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .