3

When running the following batch file I would expect the program to return from the func routine and display the 'end program' message. Instead, the program seems to hang when pressing a key after the pause command is executed in the for loop. Replacing exit /b with goto :eof seems to have the same effect.

@echo off

echo start program
call :func
echo end program
pause
exit /b

:func
echo start func
for /l %%l in () do (
  echo start loop
  pause
  exit /b
  echo end loop
)
echo end func
exit /b

Expected output:

start program
start func
start loop
Press any key to continue...
end program
Press any key to continue...

I would like to avoid using goto-label as an infinite loop. With the following loop, the iteration message is only displayed once:

:test
for /l %%l in (1,1,3) do (
  echo iteration: %%l
  exit /b
)
exit /b

What would be the appropriate way to use an infinite loop inside a routine and still be able to return to the caller?

Ross Ridge
  • 38,414
  • 7
  • 81
  • 112
303
  • 2,417
  • 1
  • 11
  • 25
  • I'm not sure I follow, the term infinite is specific, if it is continuous how can it return? – Compo Feb 21 '17 at 20:52
  • @Compo: The `exit /b` is *supposed* to end the loop, but it seems not to work with `/L` loops – abelenky Feb 21 '17 at 21:08
  • 2
    The idea is to return from the function call inside the for loop when a specific condition is met. In batch file scripting you cannot influence the condition of the for loop from within its body. I've also found out that there is no straight-forward way to break from an infinite loop while avoiding the use of goto-label. Refer to the following DosTips topic for more information: http://www.dostips.com/forum/viewtopic.php?f=3&t=2707 – 303 Feb 21 '17 at 21:12
  • 2
    [jeb answered this here](http://stackoverflow.com/a/5488111/6811411) the only way to exit an infinite loop, is a sole exit also leaving the cmd session. –  Feb 21 '17 at 21:13
  • 1
    The problem is that the loop actually finishes, even when there is an `exit /B` or a `goto` in its body, although in such cases the body is no longer executed; try something `for /L %%I in (0,1,999999) do @(echo Body & exit /B)`, and you will notice that the batch file needs quite some time to quit, although the body is executed once only, because the loop iterates to the end in the background)... – aschipfl Feb 21 '17 at 22:03

1 Answers1

2

In the reply # 7 at the linked DosTips topic you may read this phrase: "There is no way to break a FOR /L loop in the same CMD context, so I used a trick to export the cycle to a new CMD that can be broken via an EXIT command, and the execution return to the caller code". That is:

@echo off
if "%~1" neq "" goto %1

echo start program
cmd /C "%~F0" :func
echo end program
pause
exit /b

:func
echo start func
for /l %%l in () do (
  echo start loop
  pause
  exit
  echo end loop
)
echo end func
exit /b

You may read a further description of this point at The ultimate while loop DosTips topic.

Aacini
  • 65,180
  • 12
  • 72
  • 108