<http://www.netikka.net/tsneti/info/tscmd038.htm>
Copyright © 2003-2010 by Prof. Timo Salmi  
Last modified Sun 22-Aug-2010 14:34:18

 
Assorted NT/2000/XP/.. CMD.EXE Script Tricks
From the html version of the tscmd.zip 1cmdfaq.txt file
To the Description and the Index
 

This page is edited from the 1cmdfaq.txt faq-file contained in my tscmd.zip command line interface (CLI) collection. That zipped file has much additional material, including a number of detached .cmd script files. It is recommended that you also get the zipped version as a companion.

Please see "The Description and the Index page" for the conditions of usage and other such information.



38} How can I set and test the errorlevel within a script file?

Many programs return an errorlevel, which then can be tested for. One of such programs is the familiar C:\WINDOWS\system32\find.exe. For example one could have
  @echo off & setlocal enableextensions
  set var_=Testing
  echo %var_%|find "a">nul
  set el_=%ERRORLEVEL%
  echo el_=%el_%
  endlocal & goto :EOF

The output would be
  C:\_D\TEST>cmdfaq
  el_=1

For one of the applications see Item #42.

EXIT can be used to set the errorlevel. Note the ^2 to avoid it from being mistaken for a handle.
  @echo off & setlocal enableextensions
  echo.@exit /B ^2>tmp$$$.cmd
  call tmp$$$
  for %%e in (0 1 2 3 4 5 6 7 8 9) do (
    if %errorlevel% EQU %%e echo The errorlevel is %%e)
  echo Bye from %0 on %date% at %time%
  for %%f in (tmp$$$.cmd) do if exist %%f del %%f
  goto :EOF

The output will be something like
  D:\TEST>cmdfaq
  The errorlevel is 2
  By from cmdfaq on 19.12.2003 at 8:18:03.21

Another alternative is to utilise gawk:
  @echo off & setlocal enableextensions
  :: Requires G(nu)AWK
  gawk 'BEGIN{exit 2}'
  for %%e in (0 1 2 3 4 5 6 7 8 9) do (
    if %errorlevel% EQU %%e echo The errorlevel is %%e)
  echo Bye from %0 on %date% at %time%
  goto :EOF

The output will be something like
  F:\CMD>d:\test\cmdfaq
  The errorlevel is 2
  By from d:\test\cmdfaq on 19.12.2003 at 8:19:08.69

A wider scale for testing the errorlevel. Note that the errorlevel must be stored before the next SET because also SET sets the errorlevel.
  @echo off & setlocal enableextensions enabledelayedexpansion
  echo.@exit /B ^5>"%temp%\tmp$$$.cmd"
  call "%temp%\tmp$$$"
  set errorlev_=%errorlevel%
  set /a e_=0
  :_loop
    if !errorlev_! EQU %e_% (
      echo The errorlevel is %e_%
      ) else (
      set /a e_+=1
      if %e_% LEQ 255 goto _loop)
  for %%f in ("%temp%\tmp$$$.cmd") do if exist %%f del %%f
  goto :EOF

With Visual Basic Script one can have
  @echo off & setlocal enableextensions
  :: Make a temporary folder
  if not exist c:\mytemp\ mkdir c:\mytemp
  ::
  :: Set the errorlevel

  echo WScript.Quit ^5>c:\mytemp\tmp$$$.vbs
  cscript //nologo c:\mytemp\tmp$$$.vbs
  ::
  for %%e in (0 1 2 3 4 5 6 7 8 9) do (
    if %errorlevel% EQU %%e echo The errorlevel is %%e)
  ::
  :: Clean up

  for %%f in (c:\mytemp\tmp$$$.vbs) do del %%f
  rmdir c:\mytemp
  endlocal & goto :EOF

The output will be
  D:\TEST>cmdfaq
  The errorlevel is 5

Or, written alternatively
  @echo off & setlocal enableextensions
  ::
  :: Build a Visual Basic Script

  set skip=
  set vbs_=%temp%\slice.vbs
  findstr "'%skip%VBS" "%~f0" > "%vbs_%"
  ::
  :: A call returning an errorlevel

  cscript //nologo "%vbs_%"
  ::
  for %%e in (0 1 2 3 4 5 6 7 8 9) do (
    if %errorlevel% EQU %%e echo The errorlevel is %%e)
  ::
  :: Clean up

  for %%f in ("%vbs_%") do if exist %%f del %%f
  endlocal & goto :EOF
  '
  '.......................................................
  'A Visual Basic Script returning an errorlevel

  WScript.Quit 5 'VBS

Actually, an XP srcipt can return an errorlevel without any additional tricks as demonstrated below
  @echo off & setlocal enableextensions
  set cmdfile_="temp $$$.cmd"
  echo @exit /b ^2>%cmdfile_%
  call %cmdfile_%
  for %%e in (0 1 2 3 4 5 6 7 8 9) do (
    if %errorlevel% EQU %%e echo The errorlevel is %%e)
  for %%f in (%cmdfile_%) do if exist %%f del %%f
  endlocal & goto :EOF

The output will be
  D:\TEST>cmdfaq
  The errorlevel is 2

Is there any reason why echo The errorlevel is %errorlevel% wouldn't accomplish the same, even showing errorlevels above 9?

Of course, if the echoing is all that is wished for. But that is not the essence here. The point is that one may wish to cover a certain range or levels, and one may wish to take action depending one the level. That is why the more involved formulation. But, indeed one can simply write
  whateverCommand
  echo %%errorlevel%%=%errorlevel%



One important consideration in testing an errorlevel is to do it immediately after a command, that is without any other intervening commands that might affect the errorlevel results.

Furthermore, there are some common mistakes that are made with the errorlevels. From the days of MS-DOS the following, now optional format is familiar to some of the readers
  if ERRORLEVEL number DoWhatever
The above specifies a true condition only if the previous program run by CMD.EXE returned an exit code equal to or greater than number. That is easily misunderstood or forgotten. For example, consider
  @echo off & setlocal enableextensions
  dir /a:d C:\|findstr /c:"No such folder"
  echo %%errorlevel%%=%errorlevel%
  if errorlevel 0 echo The errorlevel is 0
  endlocal & goto :EOF

The output will be
  C:\_D\TEST>cmdfaq
  %errorlevel%=1
  The errorlevel is 0
That happens because ERRORLEVEL 0 always is true.

In the XP scripting it is more clear to write
  @echo off & setlocal enableextensions
  dir /a:d C:\|findstr /c:"No such folder"
  echo %%errorlevel%%=%errorlevel%
  if %errorlevel% EQU 0 echo The errorlevel is 0
  endlocal & goto :EOF

The output will be
  C:\_D\TEST>cmdfaq
  %errorlevel%=1

Another potential source of confusion is setting the errorlevel directly with set. It is not advisable to do that. For example
  @echo off & setlocal enableextensions
  set errorlevel=0
  dir /a:d C:\|findstr /c:"No such folder"
  echo %%errorlevel%%=%errorlevel%
  endlocal & goto :EOF

The output will be
  C:\_D\TEST>cmdfaq
  %errorlevel%=0 (when it is rather expected to be 1)

Yet another common mistake involves misunderstading or ignoring delayed variable expansion (the principle is not limited to errorlevels, but is typical in for and if constructs). Consider
  @echo off
  setlocal enableextensions enabledelayedexpansion
  set cmdfile_=%temp%\tmpcmd.cmd
  echo @exit /b ^2>"%cmdfile_%"
  if "%OS%"=="Windows_NT" (
    call "%cmdfile_%"
    echo errorlevel=%errorlevel%)
  if "%OS%"=="Windows_NT" (
    call "%cmdfile_%"
    echo errorlevel=!errorlevel!)
  for %%f in ("%cmdfile_%") do if exist %%f del %%f
  endlocal & goto :EOF

The output will be
  C:\_D\TEST>cmdfaq
  errorlevel=0
  errorlevel=2
Where only the latter is correct.



If for some reason you wish to use the old DOS errorlevel cumbersome errorlevel testing syntax, the following demonstration might be of help.
  @echo off & setlocal enableextensions
  set cmdfile_=%temp%\tmpcmd.cmd
  ::
  echo @exit /b ^2>"%cmdfile_%"
  ::
  echo.
  call "%cmdfile_%"
  if errorlevel 3 if not errorlevel 4 echo The errorlevel is exactly 3
  if errorlevel 2 if not errorlevel 3 echo The errorlevel is exactly 2
  if errorlevel 1 if not errorlevel 2 echo The errorlevel is exactly 1
  if errorlevel 0 if not errorlevel 1 echo The errorlevel is exactly 0
  echo.
  ::
  call "%cmdfile_%"
  if errorlevel 3 echo The errorlevel is at least 3
  if errorlevel 2 echo The errorlevel is at least 2
  if errorlevel 1 echo The errorlevel is at least 1
  if errorlevel 0 echo The errorlevel is at least 0
  ::
  for %%f in ("%cmdfile_%") do if exist %%f del %%f
  endlocal & goto :EOF

The output will be
  C:\_D\TEST>cmdfaq
 
  The errorlevel is exactly 2
 
  The errorlevel is at least 2
  The errorlevel is at least 1
  The errorlevel is at least 0

References/Comments: (If a Google message link fails try the links within the brackets.)
  Google Groups Dec 21 2003, 9:10 pm [M]
  Google Groups 3 Jul 2008 16:40:10 +0200 [M] [T]
  Google Groups 4 Jul 2008 15:01:21 +0800 [T]