Monday, March 11, 2013

ERROR LEVEL

Errorlevels

The correct name for errorlevels would be return codes.
But since the DOS command to determine the return code is IF ERRORLEVEL, most people use the name errorlevel.

Errorlevels are not a standard feature of every command.
A certain errorlevel may mean anything the programmer wanted it to.
Most programmers agree that an errorlevel 0 means the command executed successfully, and an errorlevel 1 or higher usually spells trouble.
But there are many exceptions to this general rule.

IF ERRORLEVEL construction has one strange feature, that can be used to our advantage: it returns TRUE if the return code was equal to or higher than the specified errorlevel.

This means most of the time we only need to check IF ERRORLEVEL 1 ... and this will return TRUE for every non-zero return code.

In Windows NT 4/2000/XP this may sometimes fail, since some executables return negative numbers for errorlevels!
However, this can be fixed by using the following code to check for non-zero return codes:
IF %ERRORLEVEL% NEQ 0 ...
Use the code above wherever you would have used IF ERRORLEVEL 1 ... in the "past".

To determine the exact return code the previous command returned, we could use a construction like this:

@ECHO OFF
IF ERRORLEVEL 1 SET ERRORLEV=1
IF ERRORLEVEL 2 SET ERRORLEV=2
IF ERRORLEVEL 3 SET ERRORLEV=3
IF ERRORLEVEL 4 SET ERRORLEV=4



IF ERRORLEVEL 254 SET ERRORLEV=254
IF ERRORLEVEL 255 SET ERRORLEV=255
ECHO ERRORLEVEL = %ERRORLEV%
This is perfectly OK if we only have to check, say, 15 consecutive errorlevels.
If we need to check every errorlevel, though, there are better alternatives.

In Windows NT 4 (and 2000?) this won't work, since the SET command itself will set an errorlevel (usually 0)!
(As I learned from Charles Long, in XP the SET command no longer sets an errorlevel itself.)
However, Windows NT 4 and later make it easy by storing the latest errorlevel in the environment variable ERRORLEVEL:
ECHO.%ERRORLEVEL%
will display the errorlevel.

This blog entry by Batcheero explains perfectly why you should never SET the ERRORLEVEL variable.

The safest way to use errorlevels for all DOS versions is the reverse order check.
Start checking the highest errorlevel that can be expected, then check for the one below, etcetera:
IF ERRORLEVEL 255 GOTO Label255
IF ERRORLEVEL 254 GOTO Label254



IF ERRORLEVEL 2 GOTO Label2
IF ERRORLEVEL 1 GOTO Label1
GOTO Label0

:Label255
(commands to be executed at errorlevel 255)
GOTO End





:Label1
(commands to be executed at errorlevel 1)
GOTO End

:Label0
(commands to be executed at errorlevel 0, or no errorlevel)

:End

This will result in many more lines of batch code, but at least it will work in any DOS version.
In DOS for the rest of us, we can use FOR loops to determine the 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%


No comments: