I've written a simple batch file to install a program under Windows 7. There's a maddening bug I'm running into with set /p VAR=PROMPT
:
Input discarded bug
Here's a simple test case:
@echo off
setlocal
if exist "%USERPROFILE%\Documents" (
set /p CONFIRM="Previous version is installed! Continue? (Y/n) "
echo {%CONFIRM%}
)
if exist "%USERPROFILE%\Documents" (
set /p CONFIRM="Previous version is installed! Continue? (Y/n) "
echo {%CONFIRM%}
)
I run it:
Previous version is installed! Continue? (Y/n) n
{}
Previous version is installed! Continue? (Y/n) n
{n}
Notice that when the first set /p
runs, it doesn't actually save my input!
Prompt mangling bug (related?)
I suspect, but am not sure, if this is related to a more obvious bug in set /p
, wherein it truncates the prompt at the first )
if inside the parentheses defining the if
block:
@echo off
if exist "%USERPROFILE%\Documents" (
set /p CONFIRM=Previous version is installed! Continue? (Y/n)
echo {%CONFIRM%}
)
At least this version captures my input, although it mangles the prompt:
Previous version is installed! Continue? (Y/nn
{n}
Workarounds?
Any ideas? Or is set /p
just so buggy that I can't use it?
EDIT: Conclusions
Thanks to the links and tips from @npocmaka, I think I have a better idea what's going on: "parse time" vs. "run time" isn't the same inside a ()
-delimited block as outside. Hence this example:
@echo off
(
set /p CONFIRM=^?
echo {%CONFIRM%}
)
(
set /p CONFIRM=^?
echo {%CONFIRM%}
)
echo {%CONFIRM%}
When run, it's obvious that there's a "delay" in the variables getting the expected values inside the blocks:
?foo
{}
?bar
{foo}
{bar}
Although delayed expansion works, I still believe this behavior is inconsistent with every description I've read of how set /p
is supposed to work, though that's par for the course for batch files. It appears that variables set by set /p
magically escape from parse-time expansion except when they appear inside blocks.
I believe the "prompt mangling" version only works (sorta) because it inadvertently closes the block early, and the batch file processor doesn't complain about the second mismatched )
.