Reached the maximum set recursion level - setlocal
Read a few bits, but try your best to figure it out. Basically, you need to use Setlocal with deferred expansion on and off to use and manage variables with exclamation marks. An example of this code is below. A section of code can loop through a session, and at some point (I believe 32?) I get a "Maximum level of recursion localization" error.
I did a little familiarity with Endlocal but can't figure out how to use it. My concern is that some parts of the code are extracting from the surrounding code (e.g.% _emuExts%) the environment vars, while there are some vars in the extract that I want to use outside the extract (e.g.% startfile% and% lauchfile2% ). Hope this makes some sense!
My question is really about where to put any EndLocal to ensure that it can use variables from "around" the code, and also set variables that can be used outside of the "local" bit. To be honest, we are trying to conceptualize ideas around "local" and "levels of recursion".
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 loops through the current directory, through the values specified in% _emuExts%, and sets% launchfile% to the extension of the "priority" extension (rightmost extension). Some filenames have exclamation marks - hence the delayed switch. Then it shuts down "!" for "{-exc -}"
Apologies - may be obvious to you guys - but hard to get a head on. Thanks to
source to share
Rather than complicating the code with all SETLOCALs, is it possible to change the code so you don't have to defer expansion? I don't see any code above that requires it. Of course the code is missing. Maybe we should look at this. If you must set SETLOCAL multiple 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. For this you can do something like this endlocal & set MyVar=%MyVar%
. This works because at load time the entire string is parsed and% MyVar% is expanded. The runtime behavior is to then set this value to a new variable (of the same or a different name, of your choice) outside the localized code.
source to share
Thanks guys! I'm an amateur, so my solution is probably not the most eloquent, but it worked! Most of my scripts work with setlocalexpantion enabled. Several things helped solve this problem:
- Treating setlocal + endlocal as parentheses - closing any setlocal with matching endlocal
- If you need to "pass" the set variable "inside" these pareheses to the rest of the script using endlocal with a tunneling method
- Detecting that if you are endlocal the script reverts to its previous "setlocal" state (i.e. no need to re-enable delayed expansion via set after "closed" disable)
So the 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....
source to share
To manipulate exclamation marks in file names, use a procedure call as in the following example. Note setlocal
and endlocal
are like parentheses, so they should always be chained together. By doing this, you never reach the maximum level of setlocal recursion ...
@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
source to share