Maximum setlocal recursion level reached - setlocal

10,536

Solution 1

Rather than complicating the code with all the SETLOCALs, can the code be modified so that you don't need to to enable delayed expansion? I don't see any code above that requires it. Granted there is code missing. Maybe we should look at that. If you must SETLOCAL numerous times,there is a technique called 'tunneling' that allows you to pass variables that are local in one section of code to another section of code. To do that you can do something like thisendlocal & set MyVar=%MyVar%. This works because at load time the entire line is parsed and %MyVar% is expanded. The run time behavior is to then set that value into a new variable (of same or different name, as you choose) outside the localized code.

Solution 2

Thanks fellas! I'm an amateur, so my solution probably not the most eloquent, but it worked! The majority of my script runs with setlocalexpantion enabled. A few things helped solve this:

  • Treating setlocal + endlocal as 'parentheses' - closing any setlocal with matching endlocal
  • If needing to 'pass' a variable set 'within' these paretheses to the rest of the script, using the endlocal with the tunnelling method
  • Finding that if you endlocal, the script returns to the previous 'setlocal' state (i.e. no need to re-enable delayed expansion via set following 'closed' disable)

So, final, working code:

:: Example of var contents:
set _emuExts=cue bin iso
:: Problem code:
Setlocal DisableDelayedExpansion
for %%e in (%_emuExts%) do (
        echo Extention: %%e 
        for /F "delims=" %%a in ('dir /b *.%%e') do (               
                set launchfile=%%~na.%%e
                echo Launchfile this iteration: [%%~na.%%e]%_log1%
            )
        echo Next iteration......
    )
echo Final Launchfile: "%launchfile%" %_log1%
set launchfile2=%launchfile:!={-exc-}%
echo Launchfile with replace: %launchfile2%%_log1%
endlocal & (
        set "launchfile=%launchfile%"
        set "launchfile2=%launchfile2%"
    )
:: .....more code  
Setlocal DisableDelayedExpansion
set "_FinalemuCmd=%_FinalemuCmd:{-exc-}=!%"
echo after replace and no delayed: %_FinalemuCmd%%_log1%
pause
echo 
start /wait "" "%_emuExe%" %_FinalemuCmd%
::ping -n 3 localhost  > nul
endlocal
:: ...continues....

Solution 3

To manage exclamation marks in file names use a procedure call as in next example. Note setlocal and endlocal are like some kind of parentheses so should be always coupled together. Doing that you never reach the maximum setlocal recursion level...

@echo off
@SETLOCAL enableextensions enabledelayedexpansion
  set "launchfile="
  for /f %%G in ('dir /b *.enu') do (
    SETLOCAL disabledelayedexpansion
      Call :exclamsub "%%~dpnxG"
    ENDLOCAL
  )
@ENDLOCAL
goto :eof

:exclamsub
@echo off
  set "launchfile=%~1"
  @echo %1 ^[%launchfile%^]
goto :eof
Share:
10,536
stigzler
Author by

stigzler

Updated on June 23, 2022

Comments

  • stigzler
    stigzler almost 2 years

    Read a few bits, but struggling to get my head around this. Basically, having to use Setlocal with enable and disable delayed expansion to use and manipulate variables with exclamation marks in. Example of this code below. The code section can be cycled through many times in a session, and at some point (I believe it's 32?) I get a "Maximum setlocal recursion level reached" error.

    I've read a little about Endlocal, but can't get my head around how to use it. My worry is that some parts of the code extract (below) use environment vars from the surrounding code (e.g. %_emuExts%) whilst there are some vars set in the extract that I want to use outside the extract (e.g. %launchfile% and %lauchfile2%). Hope that makes some kinda sense!

    My question is really around where to put any EndLocal to ensure that can use variables from 'around' the code and also set variables that can be used outside of the 'local' bit. To be honest - struggling to conceptualize the ideas around 'local' and 'recursion levels'

    The code:

    :: Example of var contents:
    set _emuExts=cue bin iso
    :: Problem code:
    Setlocal DisableDelayedExpansion
    for %%e in (%_emuExts%) do (
            echo Extention: %%e 
            for /F "delims=" %%a in ('dir /b *.%%e') do (               
                    set launchfile=%%~na.%%e            
                    echo Launchfile this iteration: [%%~na.%%e]%_log1%
                )
            echo Next iteration......
        )
    echo Final Launchfile: "%launchfile%" %_log1%
    set launchfile2=%launchfile:!={-exc-}%
    echo Launchfile with replace: %launchfile2%%_log1%
    setlocal enabledelayedexpansion
    :: .....more code   
    Setlocal DisableDelayedExpansion
    set "_FinalemuCmd=%_FinalemuCmd:{-exc-}=!%"
    start /wait "" "%_emuExe%" %_FinalemuCmd%
    setlocal enabledelayedexpansion
    :: ...continues....
    

    Functionally, this cycles through the present dir via the extentions specified in %_emuExts% and sets %launchfile% to the 'priority' file extension (rightmost extension). Some filenames have exclamation marks in - hence the delayed expansion switching. It then switches out "!" for "{-exc-}"

    Apologies - may be obvious to you guys - but hard to get head round. Thanks