Sign up ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I am using the following loop in a batch file to individually call 'functions' in the file starting by displaying text and finishing with an errorlevel check and display.

Calling the loop function uses 2 variables..

  1. the sub function name to be called
  2. the text to echo on screen for user ease

This is what those calling lines look like

call :loop BackupDatabase "Taking database backup"
call :loop StopBGService "Stopping the background service"

This is the loop function itself

    echo %~2
    call :%~1

        ECHO Executing %~2 failed
        ECHO Error Level: %ERRORLEV%

        set /p ans=Do you want to retry %~2 [y/n]^>
        if "%ans%"== "y" goto :retry
        if "%ans%"== "Y" goto :retry

Below you would find the functions that are called by each loop

    Perform database backup commands

    Perform stop background service commands

The problem I am having is when a "loop" goes wrong the script should ask if a retry is required, the very first time this happens, if you enter "n" it still retries? I've read over the loop script over and over and can't tell why this is. If anyone can fix this it would be a great help, or if someone can point out a better way of doing what I am trying to achieve.

share|improve this question
Did you try using choice instead of set? –  Karan Jul 3 '13 at 17:23

1 Answer 1

up vote 2 down vote accepted

The problem is that the Windows Command Prompt / Command-Line Interpreter (CLI), known as CMD.EXE, has a bug (well, I’m sure Microsoft thinks that it’s a feature) wherein, when it reads a block construct like IF … ( … ) or a FOR loop, it interprets all %variable_name% variables immediately, before the loop is executed.  In your example, if ans is null when you enter the IF %ERRORLEVEL% NEQ 0 ( … ) block, then all occurrences of %ans% inside that block evaluate to null, even if you change ans inside the block.  You can see this if you leave ECHO on (or turn it back on just before IF %ERRORLEVEL% NEQ 0).

The fix is to tell CMD to allow variables to be expanded at the right time, when the statements referring to them are executed.  You do this by adding

setlocal enabledelayedexpansion

somewhere near the beginning of your batch file, and changing your user-dialog code to look like

    set /p ans=Do you want to retry %~2 [y/n]^>
    if "!ans!" == "y" goto :retry
    if "!ans!" == "Y" goto :retry

using the !variable_name! form to activate the delayed expansion.  See SET /? and SETLOCAL /? for more information.

share|improve this answer
That's perfect, thanks Scott. Could you see any reason why not to include setlocal enabledelayedexpansion by default to all my batch scripts, and then use the !variable_name! notation when required? –  Ghandi Manning Jul 4 '13 at 9:48
Hmm. I vaguely recall having a batch file once that needed delayedexpansion turned off, but it was doing something unusual. It’s probably a pretty good idea to turn it on all the time. –  Scott Jul 11 '13 at 16:25
It doesn't seem to be causing me any problems, so I'll leave it off in this script or any others that require it to correctly use the FOR loop. If I were to have a script where it would cause an issue I would switch it off before the FOR loop and back on again after the FOR loop. –  Ghandi Manning Aug 2 '13 at 13:21
@GhandiManning: Be careful of that. Did you look at SETLOCAL /?? You “switch off” a SETLOCAL by saying ENDLOCAL –– and that erases any variables that you set since the SETLOCAL, puts you back in the directory you were in before the SETLOCAL, and maybe some other things. –  Scott Aug 2 '13 at 19:02
Thanks, I will bare that in mind. As it stands the script doesn't require ENDLOCAL so I won't encounter those problems. –  Ghandi Manning Aug 8 '13 at 11:11

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.