21

I have a batch file that is a wrapper around an installer. This batch file checks the error level returned by the installer and prints accordingly.

I noticed that if I execute set ERRORLEVEL=0 in a command prompt right before kicking off the batch file (in the same command window/environment), the installer never messes with the errorlevel and my batch script always returns passed. I would assume %ERRORLEVEL% is a variable defined by Windows and is used specifically to print out errors from programs and scripts and that using the variable in a batch file or something else would be 'at your own risk' because it could be changed at any moment by another process.

From what it seems like, when I set errorlevel in the given environment, it then somehow terminates the use of errorlevel as a holder of the exit code. Does anyone know why this is? To me its just weird unexpected behavior. Any information on the subject would be greatly appreciated!

1

7 Answers 7

20

You are redefining the system variable into a regular one. When you do this, the system will not use it until the command session is closed.

The best way would be to use

exit /b 0

in another batch file and call it from your primary script. Where the number 0 is your wanted errorlevel. Either that or use a command that resets the errorlevel for you, such as echo, findstr etc.

For example the following commands would all set ERRORLEVEL to 0 within your batch-file:

VERIFY > nul

cmd /c "exit /b 0"

ver > nul     
5
  • 2
    Almost correct. You can get the "system" to use the dynamic ERRORLEVEL simply by undefining any user defined value using set "errorlevel="
    – dbenham
    Sep 23, 2013 at 19:41
  • Why does Windows allow someone to redefine a system variable into a regular one? Do both definitions still exist, its just echo and other such commands now point to the regular one? So programs could still be updating the system variable, its just not accessible through the command prompt?
    – user972276
    Sep 23, 2013 at 19:55
  • 1
    "Either that or use a command that resets the errorlevel for you, such as echo, findstr etc." The echo command does not reset the errorlevel variable.
    – antred
    May 11, 2015 at 14:33
  • 1
    As others have said, if the errorlevel variable has been "manually" set by the user/batch with "set errorlevel=0", the errorlevel variable will no longer reflect the exit code, but you can still access the exit code with if errorlevel do something. Jul 9, 2016 at 7:32
  • (1) A more general question is “How do I set ERRORLEVEL to some arbitrary value, such as 42?”  cmd /c exit 42 seems to be the best answer to that. (2) As dbenham points out, you don’t need the /b or the quotes. Feb 19, 2020 at 1:18
16

You should never assign your own value to dynamic system variables like ERRORLEVEL, PATH, CD, DATE, TIME, etc. Doing so will prevent code from seeing the dynamic value. You can restore the dynamic value by simply undefining the user defined value. For example:

set "errorlevel="

If you want to force the errorlevel to 0, then you can use this totally non-intuitive, but very effective syntax: (call ). The space after call is critical. If you want to set the errorlevel to 1, you can use (call). It is critical that there not be any space after call.

(call)
echo %errorlevel%
(call )
echo %errorlevel%

A more intuitive, but less convenient method to set the errorlevel is to use a dedicated subroutine in a batch file:

call :setErr 1
echo %errorlevel%
call :setErr 0
echo %errorlevel%
exit /b

:setErr
exit /b %1

Or if on the command line, you could use

cmd /c exit 1
echo %errorlevel%
cmd /c exit 0
echo %errorlevel%
11

I personally use this:

cd .

Works even in unix shell.

1
  • But, this one might be a bit faster: type nul>nul Because Process Monitor shows QueryDirectory calls on cd . PS: cd . has another nice side effect in the unix shell. It does restore recreated working directory in the terminal if it has been opened before the erase.
    – Andry
    Feb 28, 2020 at 3:50
7

This is the only thing I have found that works.

call (exit /b 0)

Needed it in a script which uses 3rd party script that detects ERRORLEVEL, but is not resetting error level its self properly.

0
2

Here are some other ways to reset the ErrorLevel state, which even work in MS-DOS (at least for version 6.22):

more < nul > nul

rem // The `> nul` part can be omitted in Windows but is needed in MS-DOS to avoid a line-break to be returned:
sort < nul > nul

The following methods work in MS-DOS only:

command /? > nul

fc nul nul > nul

For the sake of completeness, this sets the ErrorLevel state to 1, valid for both Windows and MS-DOS:

< nul find ""
2

These will also work: (Sets errorlevel to 1)

Method 1

color 00

Method 2

echo A | find "B"

You can also use this to set errorlevel 1-26:

echo Your errorlevel<sup>th</sup> character between A-Z | choice /c:Enter A-Z here /n
3
  • Regarding method 1. Using "color 00" to set, or "color" to reset the ERRORLEVEL status does work - except when a script is being redirected to a file. For instance if foo.bat contains a color command to reset the ERRORLEVEL it will not work if you call foo.bat > file.txt In this case the color command, with or without arguments, will only set ERRORLEVEL. This might be useful perhaps for determining if a script output is being redirected.
    – Rod Dewell
    Oct 18, 2021 at 13:53
  • @RodDewell, at least on my W11 22H2 machine, I see no difference in the effect of color 00 when a redirection is applied. However, with color - which is to be avoided as a means of resetting ERRORLEVEL to 0, because it has side effects (resetting colors) - there is a difference: when a batch file is called from outside cmd.exe, an argument-less color call seemingly always fails and sets the exit code to 1. Verify by running the following from the Run dialog (WinKey+R): cmd /v /c "color 12 & color & echo !ERRORLEVEL! & pause"
    – mklement0
    May 3, 2023 at 1:09
  • Wasif, the choice.exe workaround is intriguing, but if you're going to create a child process anyway, you can just use cmd /c exit 5, for instance, which places no restrictions on what exit code you can set.
    – mklement0
    May 3, 2023 at 1:11
0

User aschipfl gave best answer, to complete it, using smallest function FIND:

This line will set ERRORLEVEL to 1, in DOS or later:

<nul find ""
if errorlevel 1 echo ERRORLEVEL is 1 or more

This line will set ERRORLEVEL to 0, in DOS or later:

echo a |find "a" >nul
if errorlevel==0 echo No Error
4
  • <nul (find "" && echo/zOk || echo/nO zOk! ) & (echo/a | find "a") >nul && echo/zOk || echo/nO zOk! Results: nO zOk! line 1 and zOk! line 2...,
    – Io-oI
    Dec 12, 2023 at 1:36
  • Io-oI, parenthesis on first part of your statement and echo is confusing. Easier is (which will give NO and YES as intended): <nul find "" && echo YES || echo NO & (echo a | find "a") >nul && echo YES || echo NO
    – isidroco
    Dec 13, 2023 at 13:36
  • The main advantage of this is that it also works on w9x (tested) and FIND is one of the lightest functions. ie: Under win9x copy will not set errorlevel.
    – isidroco
    Dec 13, 2023 at 13:38

You must log in to answer this question.

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