.cmd and .bat file converting return code to an error message
-
02-07-2019 - |
Question
I'm trying to automate a program I made with a test suite via a .cmd file.
I can get the program that I ran's return code via %errorlevel%.
My program has certain return codes for each type of error.
For example:
1 - means failed for such and such a reason
2 - means failed for some other reason
...
echo FAILED: Test case failed, error level: %errorlevel% >> TestSuite1Log.txt
Instead I'd like to somehow say:
echo FAILED: Test case failed, error reason: lookupError(%errorlevel%) >> TestSuite1Log.txt
Is this possible with a .bat file? Or do I have to move to a scripting language like python/perl?
Solution
You can do this quite neatly with the ENABLEDELAYEDEXPANSION
option. This allows you to use !
as variable marker that is evaluated after %
.
REM Turn on Delayed Expansion
SETLOCAL ENABLEDELAYEDEXPANSION
REM Define messages as variables with the ERRORLEVEL on the end of the name
SET MESSAGE0=Everything is fine
SET MESSAGE1=Failed for such and such a reason
SET MESSAGE2=Failed for some other reason
REM Set ERRORLEVEL - or run command here
SET ERRORLEVEL=2
REM Print the message corresponding to the ERRORLEVEL
ECHO !MESSAGE%ERRORLEVEL%!
Type HELP SETLOCAL
and HELP SET
at a command prompt for more information on delayed expansion.
OTHER TIPS
You can do something like the following code. Note that the error level comparisons should be in decreasing order due to a cmd quirk.
setlocal
rem Main script
call :LookupErrorReason %errorlevel%
echo FAILED Test case failed, error reason: %errorreason% >> TestSuite1Log.txt
goto :EndOfScript
rem Lookup subroutine
:LookupErrorReason
if %%1 == 3 set errorreason=Some reason
if %%1 == 2 set errorreason=Another reason
if %%1 == 1 set errorreason=Third reason
goto :EndOfScript
:EndOfScript
endlocal
Not exactly like that, with a subroutine, but you can either populate the a variable with the text using a goto workaround.
It may be easier if this test suite of yours grows quite a bit to use a more powerful language. Perl or even Windows Scripting Host can help you there.
Yes you can use call. Just on a new line have call, and pas the errorcode. This should work, but i have not tested.
C:\Users\matt.MATTLANT>help call
Calls one batch program from another.
CALL [drive:][path]filename [batch-parameters]
batch-parameters Specifies any command-line information required by the
batch program.
SEDIT: orry i may have misunderstood a bit, but you can use IF also
Test your values in reverse order and use the overloaded behaviour of IF:
@echo off
myApp.exe
if errorlevel 2 goto Do2
if errorlevel 1 goto do1
echo Success
goto End
:Do2
echo Something when 2 returned
goto End
:Do1
echo Something when 1 returned
goto End
:End
If you want to be more powerful, you could try something like this (you'd need to replace the %1 with %errorlevel but it's harder to test for me). You would need to put a label for each error level you deal with:
@echo off
echo passed %1
goto Label%1
:Label
echo not matched!
goto end
:Label1
echo One
goto end
:Label2
echo Two
goto end
:end
Here is a test:
C:\>test
passed
not matched!
C:\>test 9
passed 9
The system cannot find the batch label specified - Label9
C:\>test 1
passed 1
One
C:\>test 2
passed 2
Two
You can use the 'IF ERRORLEVEL' statement to do different things based on the return code.
See:
http://www.robvanderwoude.com/errorlevel.html
In response to your second question, I would move to using a scripting language anyway, since Windows batch files are inherently so limited. There are great Windows distributions for Perl, Python, Ruby, etc., so no reason not to use them, really. I personally love doing Perl scripting on Windows.