I'm trying to create a batch file that performs different 'choice' command based on the version of Windows being executed on. The choice command's syntax is different between Windows 7 and Windows XP.
Choice command returns a 1 for Y and 2 for N. The following command returns the correct error level:
Windows 7:
choice /t 5 /d Y /m "Do you want to automatically shutdown the computer afterwards "
echo %errorlevel%
if '%errorlevel%'=='1' set Shutdown=T
if '%errorlevel%'=='2' set Shutdown=F
Windows XP:
choice /t:Y,5 "Do you want to automatically shutdown the computer afterwards "
echo %ERRORLEVEL%
if '%ERRORLEVEL%'=='1' set Shutdown=T
if '%ERRORLEVEL%'=='2' set Shutdown=F
However, when it is combined with a command to detect the Windows OS version, errorlevel returns 0 before AN after the choice command in both my Windows XP and Windows 7 blocks of code.
REM Windows XP
ver | findstr /i "5\.1\." > nul
if '%errorlevel%'=='0' (
set errorlevel=''
echo %errorlevel%
choice /t:Y,5 "Do you want to automatically shutdown the computer afterwards "
echo %ERRORLEVEL%
if '%ERRORLEVEL%'=='1' set Shutdown=T
if '%ERRORLEVEL%'=='2' set Shutdown=F
echo.
)
REM Windows 7
ver | findstr /i "6\.1\." > nul
if '%errorlevel%'=='0' (
set errorlevel=''
echo %errorlevel%
choice /t 5 /d Y /m "Do you want to automatically shutdown the computer afterwards "
echo %errorlevel%
if '%errorlevel%'=='1' set Shutdown=T
if '%errorlevel%'=='2' set Shutdown=F
echo.
)
As you can see, I even tried clearing the errorlevel var before executing the choice command, but errorlevel remains at 0 after the choice command is executed.
Any tips? Thanks!
By default when a command line execution is completed it should either return zero when execution succeeds or non-zero when execution fails. When a batch script returns a non-zero value after the execution fails, the non-zero value will indicate what is the error number.
In Microsoft Windows and MS-DOS, an errorlevel is the integer number returned by a child process when it terminates. Errorlevel is 0 if the process was successful. Errorlevel is 1 or greater if the process encountered an error.
To test for a specific ERRORLEVEL, use an IF command with the %ERRORLEVEL% variable. n.b. Some errors may return a negative number. If the batch file is being executed as a scheduled task, then exiting with an error code will be logged as a failed task. You can monitor the event log to discover those failures.
You have run across a classic problem - You are attempting to expand %errorlevel%
within a parenthesized block of code. That form of expansion occurs at parse time, but the entire IF construct is parsed at once, so the value of %errorlevel%
will not change.
The solution is simple - delayed expansion. You need SETLOCAL EnableDelayedExpansion
at the top, and then use !errorlevel!
instead. Delayed expansion occurs at execution time, so then you are able to see the changes to the value within the parentheses.
The help for SET (SET /?
) describes the problem and the solution with regards to a FOR statement, but the concept is the same.
You have other options.
You can move the code from within the body of the IF
to labeled sections of code without parentheses, and use GOTO
or CALL
to access the code. Then you can use %errorlevel%
. I don't like this option because CALL
and GOTO
are relatively slow, and the code is less elegant.
Another option is to use IF ERRORLEVEL N
instead of IF !ERRORLEVEL!==N
. (See IF /?
) Because IF ERRORLEVEL N
tests if errorlevel is >= N, you need to perform your tests in descending order.
REM Windows XP
ver | findstr /i "5\.1\." > nul
if '%errorlevel%'=='0' (
choice /t:Y,5 "Do you want to automatically shutdown the computer afterwards "
if ERRORLEVEL 2 set Shutdown=F
if ERRORLEVEL 1 set Shutdown=T
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With