Windows package: variable is lost after starting another batch file

I have the following code:

@echo off
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
set FILENAME=testfilename
for /L %%n in (1,0,10) do (
   echo name-before: !FILENAME!
   another-batch-file
   SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
   @echo off
   echo name-after: !FILENAME!
)
@echo on
ENDLOCAL

      

When launched, the following is displayed on the console:

name-before:testfilename
name-after:!FILENAME!

      

The variable is FILENAME

set to "testfilename" and correctly returned to the terminal. However, after executing one more batch file, FILENAME

it cannot be resolved, and "FILENAME" rather than "testfilename" is reflected. I have looked at the batch file that is being called but cannot see any obvious code or settings.

I wonder if there is an obvious problem. Thanks to

+3


source to share


1 answer


Several things can be found here.

  • Some general guidelines when debugging a batch file: Remove the line echo off

    at the top. It's amazing what you can find out when you don't suppress your debug information.

  • It's almost always wrong to use it setlocal

    inside a loop. Each call allocates resources for a complete copy of the environment block, which you do not call endlocal

    to free.

As far as echoing variables goes, I cannot reproduce the behavior you described. When I run your code, I get an name-before: !FILENAME!

echo. This outputs correctly when I use the keyword CALL

described below.

I suspect the main problem is with the way you call "other-batchfile" without using the CALL keyword. In general, you never want to run a batch file directly from another batch file. The second batch completely replaces the first, and no further lines from the outer batch will be executed. In fact, it functions like an EXIT statement.



:: This line executes
set foo=1

:: Now run another batch file
other.cmd

:: This line never executes, because this batch was canceled when
:: the other started running
set foo=2

      

The solution is to use a keyword CALL

to run another batch file. Then the current one will continue execution as soon as it is done.

:: Now run another batch file
CALL other.cmd

:: This line runs as normal
set foo=2

      

In your code, this is hard to tell because the loop continues until the current statement ( for /L

) completes, but your last endlocal

and anything else in the file will not execute.

+3


source







All Articles