Reputation: 56679
We have a file1.cmd calling file2.cmd calling file3.cmd.
file3.cmd returns a failure as: exit /b 1
But in file2.cmd we seem to "lose" this failure code. The %ERRORLEVEL% variable is being listed as 0 instead of 1.
Any ideas?
Upvotes: 0
Views: 699
Reputation: 70933
Usual problems that can be found:
Setting the errorlevel variable to a value
set errorlevel=0
echo test | find "x" > nul 2>nul
echo %errorlevel%
Here the errorlevel will be set (the find
operation has failed) but the value echoed to console will be 0. errorlevel
is a dynamic variable and setting a value to it blocks the access to the dynamic value. errorlevel
value should not be set with the set
command.
If it is necessary to set errorlevel you can
exit n
or exit /b n
cmd /c exit n
in both cases with n
the numeric value to set in the errorlevel
To clear the errorlevel you can use: ver>nul
Variable expansion
if 1==1 (
echo test | find "x" > nul 2>nul
if %errorlevel%==1 echo failed
)
When the batch parser reaches a line or a block of lines (lines enclosed in parenthesis), it replaces all the read operations on variables with the value inside the variable before execute the line/block. So, if a variable changes its value inside the line/block, the new value can no be retrieved from inside the same line/block. The read operation does not exist, it was replaced with the initial value.
Delayed expansion can be enabled, allowing to change (where needed) the syntax from %var%
to !var!
, indicating to the parser that the read operation must be delayed until the command executes
setlocal enabledelayedexpansion
if 1==1 (
echo test | find "x" > nul 2>nul
if !errorlevel!==1 echo failed
)
But for any of the two previous cases, there is an alternative. The batch language includes a construct to test for errorlevel that is not affected by assigned values or variable expansion
if errorlevel n .....
This construct will be evaluated to true for any errorlevel greater or equal to n
. For this reason, when using this construct and testing for different error levels, it is necessary to test for errorlevel
from greater to lower values
if errorlevel 3 (
....
) else if errorlevel 2 (
....
) else if errorlevel 1 (
....
) else (
....
)
In the cases where the only check is if errorlevel is set or not, this construct can be abreviated using conditional execution
command && ( .... ) || ( .... )
where the commands after the &&
are executed when the errorlevel is not set, and the commands after ||
are executed when the errorlevel is set
Upvotes: 1