Posted by: tfabris
Are all the things on the web wrong about delayed expansion? - 19/07/2017 23:50
In a DOS batch file you are supposed to be able to do this:
setlocal enabledelayedexpansion
... and then any variables that fall inside IF statements or FOR loops in the batch file are supposed to evaluate more like a real computer program instead of being the same value throughout the local scope of the IF or FOR.
All the docs I see on the web (such as https://ss64.com/nt/delayedexpansion.html ) say that I can optionally use either exclamation marks or percent signs to surround the variable name that I want to evaluate with delayed expansion.
None of them say that I *must* use exclamation marks on the delayed-expansion variables.
But in my tests it indeed looks like I must use the exclamation marks.
When I run the test below, the results from the percent-sign version of the test gets incorrect results, as if I had not done "setlocal enabledelayedexpansion", whereas the exclamation-mark version works as expected.
file: testExitError.cmd
Anyone know why?
setlocal enabledelayedexpansion
... and then any variables that fall inside IF statements or FOR loops in the batch file are supposed to evaluate more like a real computer program instead of being the same value throughout the local scope of the IF or FOR.
All the docs I see on the web (such as https://ss64.com/nt/delayedexpansion.html ) say that I can optionally use either exclamation marks or percent signs to surround the variable name that I want to evaluate with delayed expansion.
None of them say that I *must* use exclamation marks on the delayed-expansion variables.
But in my tests it indeed looks like I must use the exclamation marks.
When I run the test below, the results from the percent-sign version of the test gets incorrect results, as if I had not done "setlocal enabledelayedexpansion", whereas the exclamation-mark version works as expected.
file: testExitError.cmd
Code:
@echo off :: Turn on delayed expansion, the behavior of which is the thing we want to test here today. setlocal enabledelayedexpansion :: Create sub-file for the test cases to call. set subFileName=testExitErrorSubFile.cmd echo @echo off > "%~dp0%subFileName%" echo echo Testing delayed expansion, testing %%2 expecting %%1 >> "%~dp0%subFileName%" echo exit /B %%2 >> "%~dp0%subFileName%" :: Call all the test cases and get the output. :: -------------------------------------------------------- :: expected result value to test :: -------------------------------------------------------- call :TestExitError zero 0 call :TestExitError nonzero 1 call :TestExitError zero 0 call :TestExitError nonzero 2 call :TestExitError zero 0 call :TestExitError nonzero -1 call :TestExitError zero 0 call :TestExitError nonzero -2 call :TestExitError zero 0 call :TestExitError nonzero 65535 call :TestExitError zero 0 call :TestExitError nonzero -532462766 call :TestExitError zero 0 :: End of program pause goto:eof :: The workhorse test subroutine :TestExitError :: To test this properly, I must nest the actual test inside an IF statement :: so that the delayed expansion can make a difference. Without this outer :: IF statement, it doesn't matter if I use delayed expansion or not. IF "Hello"=="Hello" ( call "%~dp0%subFileName%" %1 %2 IF !ERRORLEVEL! NEQ 0 ( echo Result with exclamations: testing %2 result is nonzero ) ELSE ( echo Result with exclamations: testing %2 result is zero ) call "%~dp0%subFileName%" %1 %2 IF %ERRORLEVEL% NEQ 0 ( echo Result with percent signs: testing %2 result is nonzero ) ELSE ( echo Result with percent signs: testing %2 result is zero ) ) echo: goto:eof
Anyone know why?