windows batch errorlevel with if - windows

In the below script even if errorlevel is 0, Its going to if condition "if errorlevel 1"
#echo off
if exist servers.txt goto :continue
echo servers.txt file is missing
exit
:continue
set instance=%username:~2%
setlocal enabledelayedexpansion
for /f "delims=" %%i in (servers.txt) do (
pushd \\%%i\D$\%instance%\Hyperion\oracle_common 2>nul
if not errorlevel 1 (
echo %%i
echo **********************************
set ORACLE_HOME=!CD!
echo ORACLE_HOME is !ORACLE_HOME!
D:
FOR /D /r D:\%instance%\Hyperion %%a in ("jdk160_*") DO CD %%a
set JAVA_HOME=!CD!
echo JAVA_HOME is !JAVA_HOME!
echo D:\%instance%\Hyperion\oracle_common\oui\bin\setup.exe -jreLoc !JAVA_HOME! -silent -attachHome ORACLE_HOME=!ORACLE_HOME! ORACLE_HOME_NAME="REMOTE_EPM"
D:\%instance%\Hyperion\oracle_common\oui\bin\setup.exe -jreLoc !JAVA_HOME! -silent -attachHome ORACLE_HOME=!ORACLE_HOME! ORACLE_HOME_NAME=REMOTE_EPM
echo error code is:%errorlevel%
if errorlevel 2 (
echo unable to attach remote server %%i ORACLE_HOME to inventory
pause
exit
)
cd D:\%instance%\Hyperion\oracle_common\OPatch
if errorlevel 1 (
echo Failed to locate OPatch location D:\%instance%\Hyperion\oracle_common\OPatch
pause
exit
)
echo current: !CD!
opatch.bat lsinv | find "applied on"
D:\%instance%\Hyperion\oracle_common\oui\bin\setup.exe -jreLoc !JAVA_HOME! -silent -detachHome ORACLE_HOME=!ORACLE_HOME! ORACLE_HOME_NAME="REMOTE_EPM"
if errorlevel 1 (
echo Error: unable to detach remote server %%i ORACLE_HOME from inventory
pause
exit
)
popd
pause
) else (
echo ORACLE_HOME is Not found: \\%%~i\D$\%instance%\Hyperion\oracle_common
)
pause
)
endlocal
Output is:
vmhodwbrep9.oracleoutsourcing.com
**********************************
ORACLE_HOME is Y:\pwbre7\Hyperion\oracle_common
JAVA_HOME is D:\pwbre7\Hyperion\jdk160_35
D:\pwbre7\Hyperion\oracle_common\oui\bin\setup.exe -jreLoc D:\pwbre7\Hyperion\jdk160_35 -silent -attachHome ORACLE_HOME=Y:\pwbre7\Hyperion\oracle_common ORACLE_HOME_NAME="REMOTE_EP
M"
error code is:0
unable to attach remote server vmhodwbrep9.oracleoutsourcing.com ORACLE_HOME to inventory
Press any key to continue . . .

Unless command extensions are enabled, you cannot easily access ERRORLEVEL in an echo statement.
Also keep in mind that you must check your conditions in reverse because...:
IF ERRORLEVEL 1 ....
checks to see if ERRORLEVEL is greater than or equal to one. So, a series of tests would be:
IF ERRORLEVEL 5 ....
IF ERRORLEVEL 4 ....
IF ERRORLEVEL 3 ....
IF ERRORLEVEL 2 ....
IF ERRORLEVEL 1 ....
Finally, recognize that in an IF statement, %errorlevel% is *not* the same asERRORLEVEL`. You don't try it this way, but another answer does.

change
echo error code is:%errorlevel%
if errorlevel 2 (
to
call echo error code is:%%errorlevel%%
if errorlevel 2 (
OR, preferably since you have invoked delayedexpansion,
echo error code is:!errorlevel!
if errorlevel 2 (
With your current code, the entirity from
if not errorlevel 1 (
to the single ) before the endlocal line is one block statement.
Within a block statement (a parenthesised series of statements), the entire block is parsed and then executed. Any %var% within the block will be replaced by that variable's value at the time the block is parsed - before the block is executed - the same thing applies to a FOR ... DO (block).
Hence, since the block starts with
if not errorlevel 1 (
then %errorlevel% will be replaced by the value of errorlevel at the time the if is encountered, that is 0, so your echo will be replaced by echo error code is:0
Two common ways to overcome this are 1) to use setlocal enabledelayedexpansion and use !var! in place of %var% to access the changed value of var or 2) to call a subroutine to perform further processing using the changed values.
Note therefore the use of CALL ECHO %%var%% which displays the changed value of var. CALL ECHO %%errorlevel%% displays, but sadly then RESETS errorlevel.
note that last statement
CALL ECHO %%errorlevel%%` displays, but sadly then RESETS errorlevel.
So your errorlevel would now be displayed correctly, but would be reset to 0 by the call.

Related

If statement in batch file - user chooses option

New to batch/sql files. Thanks for you help.
What im trying to do:
user picks option 1, runs my sql file.
user picks 2, exits program.
user enters nothing or invalid option, ECHO "invalid option".
Problem: anything I type will exit my program. What am I doing wrong?
ECHO 1 - Show Report
ECHO 2 - Exit
SET choice=""
SET /P input=Your choice:
IF "%input%"=="1" (
GOTO :sql file
) ELSE (
IF "%input%"=="2" (
GOTO :Exit
)
) ELSE (
IF "%input%"=="" (
ECHO Invalid option chosen.
)
)
PAUSE
Just use the choice command, its instructions are available by entering choice /? at the Command Prompt.
#ECHO OFF
ECHO 1 - Show Report
ECHO 2 - Exit
CHOICE /C 12 /M "Your choice"
IF ERRORLEVEL 2 GOTO :EOF
REM This line is your SQL report code
PAUSE
If you still wanted to use, what in your case I believe is the wrong Set /P input method, then something like this should be relatively robust, given that your end user is free to enter whatever they like as input, mischievous or harmful intent included:
#ECHO OFF
ECHO 1 - Show Report
ECHO 2 - Exit
:GETInput
SET "input="
SET /P "input=Your choice: "
2>&1 SET input | FINDSTR /XR "input=[12]" 1>NUL || (
ECHO Invalid option chosen
GOTO GETInput
)
IF %input% EQU 2 GOTO :EOF
REM This line is your SQL report code
PAUSE
There is one extract closing bracket [Line #12] inside nested if..else. Also, as far as i know, your label :sql file should not contain space and you must declare it inside the batch file (Same for label :Exit)
I did few changes in your code to make it work
#echo off
:Main
cls
ECHO 1 - Show Report
ECHO 2 - Exit
SET choice=""
SET /P input=Your choice:
IF "%input%"=="1" (
GOTO :SQLReport
) ELSE IF "%input%"=="2" (
GOTO :EOF
) ELSE (
ECHO.
ECHO Invalid option chosen.
pause
GOTO :Main
)
:SQLReport
ECHO.
ECHO Running SQL Report...
GOTO :EOF
:EOF

Batch script error level is not getting reset [duplicate]

This question already has answers here:
ERRORLEVEL inside IF
(2 answers)
ERRORLEVEL vs %ERRORLEVEL% vs exclamation mark ERRORLEVEL exclamation mark
(1 answer)
Closed 3 years ago.
I am writing a small BAT file where it will search for "FAIL" Keyword followed by PASS - if none is found then take it as an error:
echo
set "topLevel=%cd%"
If [%1]==[] exit /B 1
If [%2]==[] exit /B 1
If [%3]==[] exit /B 1
If [%4]==[] exit /B 1
findstr /? >NUL 2>&1 || exit /B 1
set "arg1=%1"
set "arg2=%2"
set "arg3=%3"
set "arg4=%4"
set /a errno=0
if not exist %arg3% exit /B 1
if not exist %arg2%\%arg1% exit /B 1
set "logfile=%arg1:.=_%"
copy /y/v %arg2%\%arg1% %arg3%\%arg4%.%logfile%.res || exit /B 1
findstr /I /C:"FAIL" /I /C:"UNKNOWN" %arg3%\%arg4%.%logfile%.res
if %errorlevel% EQU 0 (
set /a errno=2
) ELSE (
REM MAKE SURE THAT THE SCRIPT DID NOT CRASH HENCE NEITHER PASS OR FAIL WILL BE LISTED
findstr /I /C:"PASS" %arg3%\%arg4%.%logfile%.res
if %errorlevel% NEQ 0 (
set /a errno=2
)
)
cd %topLevel%
exit /B %errno%
When I run with sample data I get below output:
..............................................
C:\agent\_work\30\s1>copy /y/v C:\output\test.log C:\agent\_work\30\s1\tttt.test_log.res || exit /B 1
1 file(s) copied.
C:\agent\_work\30\s1>findstr /I /C:"FAIL" /I /C:"UNKNOWN" C:\agent\_work\30\s1\tttt.SystemWalk_log.res
C:\agent\_work\30\s1>if 1 EQU 0 (set /a errno=2 ) ELSE (
REM MAKE SURE THAT THE SCRIPT DID NOT CRASH HENCE NEITHER PASS OR FAIL WILL BE LISTED
findstr /I /C:"PASS" C:\agent\_work\30\s1\tttt.test_log.res
if 1 NEQ 0 (set /a errno=2 )
)
PASSED
PASSED
PASSED
PASSED
PASSED
C:\agent\_work\30\s1>cd C:\agent\_work\30\s1
C:\agent\_work\30\s1>exit /B 2
C:\agent\_work\30\s1>echo %ERRORLEVEL%
2
Actually cause it has found "PASS" string and no "FAIL" ones - so the error level should be 0 - how can I fix the issue?
if %errorlevel% NEQ 0 (
should be
if errorlevel 1 (
Standard delayedexpansion issue - you need to invoke delayedexpansion [hundreds of SO articles about that - use the search feature] in order to display or use the run-time value of any variable that's changed within a parenthesised series of instructions (aka "code block").
Within a block statement (a parenthesised series of statements), the entire block is parsed and then executed. Any %var% within the block will be replaced by that variable's value at the time the block is parsed - before the block is executed - the same thing applies to a FOR ... DO (block).
Hence, IF (something) else (somethingelse) will be executed using the values of %variables% at the time the IF is encountered.
Two common ways to overcome this are 1) to use setlocal enabledelayedexpansion and use !var! in place of %var% to access the changed value of var or 2) to call a subroutine to perform further processing using the changed values.
IF ERRORLEVEL n is TRUE if errorlevel is n or greater than n. IF ERRORLEVEL 0 is therefore always true. IF NOT ERRORLEVEL 1 is a test for errorlevel=0. So is IF %ERRORLEVEL%==0, except that the former can be used within a block but the latter cannot.

ERRORLEVEL in FOR /F Command Loop Returns Unexpected Result

I am trying to log the output of net stop while also capturing its ERRORLEVEL.
Based on this question, I attempted the following from within a nested subroutine:
set /a loopIndex=0
for /F "usebackq delims=" %%i in (`net stop %SERVICE_NAME%`) do (
if !loopIndex! EQU 0 if !errorlevel! EQU 1 set statementError=1
set /a loopIndex+=1
call :logMessage "%%i"
)
echo statementError: %statementError%
However, this does not work, throwing 1 even when net stop succeeds.
Is this possible without a temp file? If not, what would a temp file solution look like?
As #drruruu asked in this question :
Is this possible without a temp file?
Yes, it's possible without a temp file. By sending ERRORLEVEL to STDOUT in the IN clause and parse it in the LOOP clause. And it could be done with delayed expansion too.
For convenience, here is an example. It's somewhat a FINDSTR wrapper that search for a string in the batch itself. It covers all the common cases where you need to know what was going wrong, where and why :
Error in the DO () clause (aka the loop) and get the corresponding exit code
Error in the IN () clause and get the corresponding exit code
Error directly at the FOR clause (wrong syntax, bad delimiters, etc.)
The following script simulates theses situations with FINDSTR and flags as parameters :
The first parameter is the string to search.
The second parameter is a 0/1 flag to simulate an error not related to FINDSTR in the loop.
The third parameter is a way to simulate an error on the FOR clause itself (not on IN nor LOOP)
The fourth parameter is a way to test a FINDSTR which exit 255 when the file to search does not exist. Sadly, FINDSTR exit with 1 when it can't find a string in the file/files, but also exit with 1 when it can't find any files.. With the fourth parameter, we simulate a situation where FINDSTR exit with 255 when it can't find the file.
#echo off
SETLOCAL ENABLEEXTENSIONS
IF ERRORLEVEL 1 (
ECHO Can't use extensions
EXIT /B 1
)
SETLOCAL ENABLEDELAYEDEXPANSION
IF ERRORLEVEL 1 (
ECHO Can't use delayed expansion
EXIT /B 1
)
REM The string to search
SET "LOCALV_STRING=%1"
REM The file to search. Myself.
SET "LOCALV_THIS=%0"
REM Store the exit code for the LOOP
SET "LOCALV_ERR="
REM Store the exit code for the IN
SET "LOCALV_RET="
REM Flag to stop parsing output for error simulation
SET "LOCALV_END="
REM To get the exit code of the IN clause, we get it through expansion with a second FOR loop using the well known CALL expansion and send it on STDOUT in the form "__<code>"
FOR /F "%~3tokens=*" %%M IN ('FINDSTR "!LOCALV_STRING!" "!LOCALV_THIS%~4!" ^
^& FOR /F %%A IN ^("ERRORLEVEL"^) DO #CALL ECHO __%%%%A%%') DO (
SET "LOCALV_TMP=%%~M"
REM Simulate that something goes wrong with FINDSTR I/O
IF NOT EXIST "!LOCALV_THIS!%~4" (
SET "LOCALV_RET=255"
SET LOCALV_END=1
)
IF "!LOCALV_END!" == "" (
REM SImulate a problem in the loop
IF "%2" == "1" (
(CMD /C EXIT /B 127)
SET LOCALV_END=1
) ELSE (
IF NOT "!LOCALV_TMP:~0,2!" == "__" ECHO Found: !LOCALV_TMP!
)
)
IF "!LOCALV_TMP:~0,2!!LOCALV_RET!" == "__" SET "LOCALV_RET=!LOCALV_TMP:__=!"
)
SET "LOCALV_ERR=!ERRORLEVEL!"
REM LOCALV_ERR get the exit code from the last iteration of the for loop
REM LOCALV_RET get the exit code from the IN command of the for loop
REM Sadly, FINDSTR exit with 1 if it did not find the string, but also with 1 if it could not found the file. To simulate a proper handling of exit code for
REM abnormal hardware/software situation, %2 is used to force a 255 exit code
REM If LOCALV_RET is not defined, this means the FOR...ECHO__.. wasn't executed, therefore there is a pb with the FOR LOOP
IF "!LOCALV_RET!" == "" (
ECHO Something went wrong with FOR...
EXIT /B 1
)
REM If LOCALV_RET is defined, this means the FOR...ECHO__.. was executed and the last loop operation has parsed the FINDSTR exit code, LOCALV_RET get its exit code
REM If LOCALV_RET is defined but LOCALV_ERR is not "0", something went wrong in the loop (I/O error, out of memory, wathever you could think), the problem is not FINDSTR
IF NOT "!LOCALV_ERR!" == "0" (
ECHO Error in the loop while searching "!LOCALV_STRING!" in "!LOCALV_THIS!", exit code !LOCALV_RET!. Loop exit code : !LOCALV_ERR!.
EXIT /B 4
)
REM If LOCALV_RET is "0", FINDSTR got matching strings in the file, if "1", FINDSTR don't find any matching string, if anything else, FINDSTR got a problem like failed I/O.
REM If LOCALV_RET is "0" and LOCALV_ERR is "0", everything is ok.
IF "!LOCALV_RET!" == "0" (
ECHO Success.
EXIT /B 0
)
REM If LOCALV_RET is "1" and LOCALV_ERR is "0", FINDSTR failed to find the string in the file "or" failed to find file, for the latter we simulate that FINDSTR exit with 255 .
IF "!LOCALV_RET!" == "1" (
ECHO FINDSTR failed to find "!LOCALV_STRING!" in "!LOCALV_THIS!", exit code !LOCALV_RET!. Loop exit code : !LOCALV_ERR!.
EXIT /B 2
)
REM If LOCALV_RET isn't "0" nor "1" and LOCALV_ERR is "0", FINDSTR failed to do the job and LOCALV_RET got the exit code.
ECHO FINDSTR: Houst^W OP, we've got a problem here while searching "!LOCALV_STRING!" in "!LOCALV_THIS!", exit code !LOCALV_RET!. Loop exit code : !LOCALV_ERR!.
EXIT /B 3
Script output :
Normal operation, no error simulation.
PROMPT>.\for.bat FOR 0 "" ""
Found: FOR /F "%~3tokens=*" %%M IN ('FINDSTR "FOR" ""
Found: ^& FOR /F %%A IN ^("ERRORLEVEL"^) DO #CALL ECHO __%%%%A%%') DO (
Found: REM If LOCALV_RET is not defined, this means the FOR...ECHO__.. wasn't executed, therefore there is a pb with the FOR LOOP
Found: ECHO Something went wrong with FOR...
Found: REM If LOCALV_RET is defined, this means the FOR...ECHO__.. was executed and the last loop operation has parsed the FINDSTR exit code, LOCALV_RET get its exit code
Success.
Normal operation, no error simulation, with a string that FINDSTR can't find in the file.
PROMPT>.\for.bat ZZZ 0 "" ""
FINDSTR failed to find "ZZZ" in ".\for.bat", exit code 1. Loop exit code : 0.
Simulate an error in the LOOP clause, not related to FINDSTR.
PROMPT>.\for.bat FOR 1 "" ""
Error in the loop while searching "FOR" in ".\for.bat", exit code 0. Loop exit code : 127.
Simulate an error in the FOR clause at start with an unknow "delimstoken" option.
PROMPT>.\for.bat FOR 0 "delims" ""
delimstokens=*" was unexpected.
Something went wrong with FOR...
Simulate FINDSTR exiting 255 if it can't find the file.
PROMPT>.\for.bat FOR 1 "" "ERR"
FINDSTRĀ : Can't open
FINDSTR: HoustW OP, we've got a problem here while searching "FOR" in ".\for.bat", exit code 255. Loop exit code : 0.
The FOR /F command executes NET STOP in a new cmd.exe process. FOR /F processes stdout, but that is it. There is no way for the main script to see any variable values that the FOR /F command might create, as they are gone once the sub-process terminates.
The simplest and most efficient solutions use a temporary file. I'm assuming NET STOP has two possible error codes - Success = 0, and Error = 1. So the simplest solution is to simply create a temporary error signal file if there was error.
The following demonstrates the concept in a generic way:
#echo off
del error.flag 2>nul
for /f "delims=" %%A in ('net stop %SERVICE_NAME% ^|^| echo error>error.flag') do (
...
)
if exist error.flag (
echo There was an error
del error.flag
)
You could just as easily put the error test within the DO() code if desired.
While #dbenham's answer is suitable for cases where %ERRORLEVEL% returns a binary value, I was not able to confirm or deny if the returned exit codes for net stop are in fact binary and so opted for an n-ary solution.
As per #dbenham's
DOS tips forum post:
FOR /F "delims=" %%i IN ('net stop MyService 2^>^&1 ^& CALL ECHO %%^^ERRORLEVEL%%^>error.level') DO (
CALL :logMessage "%%i"
)
FOR /F "delims=" %%i IN (error.level) DO (SET /A statementError=%%i)
DEL error.level
IF %statementError% NEQ 0 ()
Breaking down the statement parsing:
net stop MyService 2^>^&1 ^& CALL ECHO %%^^ERRORLEVEL%%^>error.level
net stop MyService 2>&1 & CALL ECHO %^ERRORLEVEL%>error.level
echo %ERRORLEVEL%>error.level
Here, CALL is used specifically to delay parsing of %ERRORLEVEL% until execution of ECHO.

IF, CALL, EXIT and %ERRORLEVEL% in a .bat

Can anyone please help me understand the behaviour of %ERRORLEVEL% variable and why it's not being set after a CALL while being inside an IF, i.e. the ECHO %ERRORLEVEL%.2 line?
#ECHO OFF
SET ERRORLEVEL
VERIFY > NUL
ECHO %ERRORLEVEL%.0
IF ERRORLEVEL 1 ECHO SNAFU
IF %ERRORLEVEL% == 0 (
ECHO %ERRORLEVEL%.1
CALL :FOO
ECHO %ERRORLEVEL%.2
IF ERRORLEVEL 42 ECHO 42.3
)
GOTO :EOF
:FOO
EXIT /B 42
GOTO :EOF
STDOUT
C:\Users\Ilya.Kozhevnikov\Dropbox>foo.bat
Environment variable ERRORLEVEL not defined
0.0
0.1
0.2
42.3
However, without IF the %ERRORLEVEL% variable is set as expected.
#ECHO OFF
SET ERRORLEVEL
VERIFY > NUL
ECHO %ERRORLEVEL%.0
IF ERRORLEVEL 1 ECHO SNAFU
REM IF %ERRORLEVEL% == 0 (
ECHO %ERRORLEVEL%.1
CALL :FOO
ECHO %ERRORLEVEL%.2
IF ERRORLEVEL 42 ECHO 42.3
REM )
GOTO :EOF
:FOO
EXIT /B 42
GOTO :EOF
STDOUT
C:\Users\Ilya.Kozhevnikov\Dropbox>foo.bat
Environment variable ERRORLEVEL not defined
0.0
0.1
42.2
42.3
When the cmd parser reads a line or a block of lines (the code inside the parenthesis), all variable reads are replaced with the value inside the variable before starting to execute the code. If the execution of the code in the block changes the value of the variable, this value can not be seen from inside the same block, as the read operation on the variable does not exist, it was replaced with the value in the variable
To solve it, you need to enable delayed expansion, and, where needed, change the syntax from %var% to !var!, indicating to the parser that the read operation needs to be delayed until the execution of the command.
#ECHO OFF
setlocal enabledelayedexpansion
SET ERRORLEVEL
VERIFY > NUL
ECHO %ERRORLEVEL%.0
IF ERRORLEVEL 1 ECHO SNAFU
IF %ERRORLEVEL% == 0 (
ECHO !ERRORLEVEL!.1
CALL :FOO
ECHO !ERRORLEVEL!.2
IF ERRORLEVEL 42 ECHO 42.3
)
GOTO :EOF
:FOO
EXIT /B 42
GOTO :EOF
MC ND answered the question already well.
Here is an alternative code showing both: expanded and delayed expansion of ERRORLEVEL.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
VERIFY > NUL
ECHO !ERRORLEVEL!.0 delayed
ECHO %ERRORLEVEL%.0 expanded
IF ERRORLEVEL 1 ECHO SNAFU
IF !ERRORLEVEL! == 0 (
ECHO !ERRORLEVEL!.1 delayed
ECHO %ERRORLEVEL%.1 expanded
CALL :FOO
ECHO !ERRORLEVEL!.2 delayed
ECHO %ERRORLEVEL%.2 expanded
)
ENDLOCAL
GOTO :EOF
:FOO
EXIT /B 42
GOTO :EOF
Microsoft describes the behavior of delayed expansion in help of command set which can be read in a command prompt window after entering set /? or help set

Windows Batch For Loop: having trouble with the following code

set checker=0
for %%a in (%namelist%) do (
:startLoop
findstr "completed" %%a_Logs.txt
IF ERRORLEVEL 1 (
IF %checker%==120 (
set checker=0
goto endLoop
)
set /a checker=%checker%+1
#ping 127.0.0.1 -n 1 -w 1000 > nul
findstr "ERROR" %%a_Logs.txt
IF ERRORLEVEL 1 (
echo Waiting 1 second before rechecking (Max 2 mins)
echo time elapsed %checker% seconds
echo.
goto startLoop
)
findstr "ERROR" %%a_Logs.txt
IF NOT ERRORLEVEL 1 (
echo ERROR: %%a Error found
goto endLoop
)
)
findstr "completed" %%a_Logs.txt
IF NOT ERRORLEVEL 1 (
echo %%a completed
)
:endLoop
)
The above piece of code is to do the following:
Parse the variable namelist(where the contents are separated by spaces)
Check if "completed" is present in the %%a_Logs.txt file
If it is present, then iteration over, If it is not, then check for the string "ERROR" in same file
If ERROR is present, then output ERROR MSG and end iteration
If ERROR is not found, keep rechecking for the next 120 seconds before ending iteration
I keep getting the following output
FINDSTR: Cannot open %a_Logs.txt
You are attempting to GOTO a label within a FOR loop - that simply doesn't work. The moment a FOR loop executes GOTO, the loop is terminated, and the FOR context is lost. So your %%a FOR variable is no longer defined. A similar issue happens with IF statements, as described at (Windows batch) Goto within if block behaves very strangely.
You also have a problem when you attempt to expand %checker% within the same parenthesized code block that sets the value. That expansion occurs at parse time, and the entire block is parsed at once. So the value you see will always be the value that existed before the block was entered. The solution is to enable delayed expansion and use !checker! instead of %checker%.
Personally, I would probably make significant changes to your code. But I believe the following minimal changes can make your code work, assuming there are no other bugs:
enable delayed expansion
Move your DO loop code to a routine outside of the loop, and then have the loop CALL that routine with %%a as a parameter. CALL does not break the loop.
Substitute %1 for %%a in the routine
Substitute exit /b for goto endLoop. Also put exit /b at end of the routine
Make sure the code does not fall into the routine when the FOR loop finishes. I used a GOTO after the FOR loop
Substitute !checker! for %checker%
EDIT -The ) in the ECHO statement must be escaped
Here is the modified code (untested)
setlocal enableDelayedExpansion
set checker=0
for %%a in (%namelist%) do call :startLoop %%a
goto continue
:startLoop
findstr "completed" %1_Logs.txt
IF ERRORLEVEL 1 (
IF !checker!==120 (
set checker=0
exit /b
)
set /a checker=checker+1
#ping 127.0.0.1 -n 1 -w 1000 > nul
findstr "ERROR" %1_Logs.txt
IF ERRORLEVEL 1 (
echo Waiting 1 second before rechecking (Max 2 mins^)
echo time elapsed !checker! seconds
echo.
goto startLoop
)
findstr "ERROR" %1_Logs.txt
IF NOT ERRORLEVEL 1 (
echo ERROR: %1 Error found
exit /b
)
)
findstr "completed" %1_Logs.txt
IF NOT ERRORLEVEL 1 (
echo %1 completed
)
exit /b
:continue
I think the labels inside your for loop are messing it up. I just tried it moving the contents of the loop into a separate "subroutine" and that gets rid of the error you mention.
Try this:
set checker=0
for %%a in (foo bar baz) do (
call :loop %%a
)
goto :eof
:loop
set basename=%1
:startLoop
findstr "completed" %basename%_Logs.txt
IF ERRORLEVEL 1 (
IF %checker%==120 (
set checker=0
goto endLoop
)
set /a checker=%checker%+1
#ping 127.0.0.1 -n 1 -w 1000 > nul
findstr "ERROR" %basename%_Logs.txt
IF ERRORLEVEL 1 (
echo Waiting 1 second before rechecking (Max 2 mins)
echo time elapsed %checker% seconds
echo.
goto startLoop
)
findstr "ERROR" %basename%_Logs.txt
IF NOT ERRORLEVEL 1 (
echo ERROR: %basename% Error found
goto endLoop
)
)
findstr "completed" %basename%_Logs.txt
IF NOT ERRORLEVEL 1 (
echo %basename% completed
)
:endLoop
goto :eof

Resources