1

I'm using a batch script to automatically run some simulations and record data. However, because this is for the purposes of testing, I routinely get error messages that pop up from the batch script because there was a bug in the simulation software. I'd like to add in a couple of different things into the script, both of which I'm extremely fuzzy on the implementation, hence my question.

1st, I'd like to put in a script that will cause an entry to become null when an error message pops up.

I have a loop that looks like this

for /f "delims=_" %%J IN ('forfiles /p "%%F" /m *.ext/c "cmd /c echo @path"')  DO (
    set start=!time!
    start "PROGRAM"  /D "c:\Path\to\the\PROGRAM" /Wait program -r  %%J  

    rem This loop uses a regular expression to find the database name from the .ext file
    rem and sets it to a variable.
    for /f "tokens=3 delims=<>" %%a in  ('findstr "<Name>ABCDir" "%%~fJ"') do set name=%%a

set end=!time!

rem The following two loops convert start time and end time to centiseconds.
rem The time variable will be converted to minutes inside a sql query so that floats are possible.
for /F "tokens=1-4 delims=:.," %%a in ("!start!") do (
        set /a "start=(((%%a*60)+1%%b %% 100)*60+1%%c %% 100)*100+1%%d %% 100"
    )       

for /F "tokens=1-4 delims=:.," %%a in ("!end!") do (
        set /a "end=(((%%a*60)+1%%b %% 100)*60+1%%c %% 100)*100+1%%d %% 100"
    )

rem Calculate the elapsed time by subtracting values
set /A elapsed=end-start

sqlcmd -S SERVER -d DATABASE -v Var1 = "!name!" Var2 = "%variable2%" Var3 = !elapsed! Var4 = %variable4% -i "\\path\to\the\query\Insert.sql"
)

So I'd like so that everytime an error message pops up, the script starts running the next file and changes the !elapsed! variable to null.

But I would like to also add in a script that will echo what the errorlevel is that pops up. I've seen one method of doing this is like this:

@ECHO OFF
IF ERRORLEVEL 1 SET ERRORLEV=1
IF ERRORLEVEL 2 SET ERRORLEV=2
IF ERRORLEVEL 3 SET ERRORLEV=3
IF ERRORLEVEL 4 SET ERRORLEV=4
   •
   •
   •
IF ERRORLEVEL 254 SET ERRORLEV=254
IF ERRORLEVEL 255 SET ERRORLEV=255
ECHO ERRORLEVEL = %ERRORLEV%

but there seems like there should be a more efficient way to do this like with a loop that counts up errorlevel i set errorlev = i where i=0 and goes to n.

I really appreciate any insight you guys can offer.

1
  • would this work placed inside the loop? set /A elapsed=end-start echo Elapsed Time: !elapsed! IF !ERRORLEVEL! GTR 0 echo Error Level !ERRORLEVEL! Occurred. IF !ERRORLEVEL! GTR 0 set elapsed=NULL Commented Jan 21, 2015 at 20:17

1 Answer 1

2

Firstly, if all you want to do is conditional execution based on the zero or non-zero exit code of "PROGRAM", use && and || to designate code blocks for success or fail like this:

for /f "delims=_" %%J IN ('forfiles /p "%%F" /m *.ext/c "cmd /c echo @path"')  DO (
    set start=!time!
    start "PROGRAM"  /D "c:\Path\to\the\PROGRAM" /Wait program -r  %%J && (

        rem program exited status 0 (success)

        rem This loop uses a regular expression to find the database name from the .ext file
        rem and sets it to a variable.
        for /f "tokens=3 delims=<>" %%a in  ('findstr "<Name>ABCDir" "%%~fJ"') do set name=%%a

        set end=!time!

        rem The following two loops convert start time and end time to centiseconds.
        rem The time variable will be converted to minutes inside a sql query so that floats are possible.
        for /F "tokens=1-4 delims=:.," %%a in ("!start!") do (
            set /a "start=(((%%a*60)+1%%b %% 100)*60+1%%c %% 100)*100+1%%d %% 100"
        )       

        for /F "tokens=1-4 delims=:.," %%a in ("!end!") do (
            set /a "end=(((%%a*60)+1%%b %% 100)*60+1%%c %% 100)*100+1%%d %% 100"
        )

        rem Calculate the elapsed time by subtracting values
        set /A elapsed=end-start

        sqlcmd -S SERVER -d DATABASE -v Var1 = "!name!" Var2 = "%variable2%" Var3 = !elapsed! Var4 = %variable4% -i "\\path\to\the\query\Insert.sql"

    ) || (

        rem Program exited status non-zero (fail)
        set "elapsed="
        rem Continue looping to next result of forfiles

    )
)

See this page for more on this sort of conditional execution.

Regarding echoing the errorlevel, it's already in %ERRORLEVEL%. You don't have to use a series of if ERRORLEVEL statements to set it. Try this on the command-line:

cmd /c exit /b 5
echo %ERRORLEVEL%

It should echo 5.

One other note, although I'm not sure you still need it knowing what you know now, if ERRORLEVEL N checks if %ERRORLEVEL% is greater than or equal to N. So if ERRORLEVEL 5 would return true if %ERRORLEVEL% is 8. For this reason, series of if ERRORLEVEL commands are usually written in descending order.

if ERRORLEVEL 3 (
    do stuff
) else if ERRORLEVEL 2 (
    do something else
) else etc...
Sign up to request clarification or add additional context in comments.

11 Comments

Okay, after reading up on conditional execution, I'm convinced this is the best way, but I'm just not following the logic. Can you explain logically why you put the && and || specifically where you did?
oh and just to make sure I follow the second part, I should just need to add an echo %ERRORLEVEL% to my script because the errorlevel is always stored in that variable? I'm using enabledelayedexpansion in my script for the variables set in the loop, should I use !ERRORLEVEL! instead of %ERRORLEVEL%?
It evaluates to expression && success || fail. I think more specifically, (expression && (success code block)) || (fail code block), which is why "fail" doesn't come before "success". Otherwise, && success would always be true. This syntax is commonly used to check whether a string exists in another string, like ping -n 1 host | find "TTL=" >NUL && success || fail. In that example, find sets errorlevel 0 if found, 1 if not found. Re: second part, yes, just add echo Program exited with status code %ERRORLEVEL% wherever you want it echoed.
I apologize for not responding, other matters at work have kept me away from this task for a few days. I'm not sure the conditional execution is what I'm looking for. I don't want the program to either execute or not execute based on whether the last iteration ran successfully or not. I want to have a line so that if an error code shows up, then it changes the value of a variable to null.
So just leave out the && ( code block ) part and do start program etc. || set "elapsed=". You can later test whether start program was unsuccessful with if not defined elapsed if you wish. If you prefer, you can start program etc on one line, then the next line if errorlevel 1 set "elapsed=". It's 6 of one, half a dozen of the other, really. Both styles perform identical actions.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.