2

If I don't set enabledelayedexpansion on, the variable value inside if block not immediately changed until going outside. But if I set it on, x will be reset back to previous value on next command.

setlocal enabledelayedexpansion
if defined x (
    set yes=
    set /p yes=Do you want to reset?
    if !yes! == y set x=
)
if not defined x set /p x=X:

All that I want is just I don't want

  1. Value changed back on next command
  2. Value not changed immediately

Thank you @Mofi for the answer. Your solutions worked but I have to remove the setlocal EnableExtensions DisableDelayedExpansion first which I have to find out why. So the lesson is we cannot immediately read the new value of a variable that just set within the same command including inside an expansion block without EnableDelayedExpansion. And EnableDelayedExpansion must be enabled and ended locally to not mess with global variable. I take the one with goto but I use call and exit instead.

stackunderflow
  • 1,492
  • 1
  • 23
  • 53

1 Answers1

2

One simple solution is using choice instead of set /P.

@echo off
setlocal EnableExtensions DisableDelayedExpansion
if defined x (
    %SystemRoot%\System32\choice.exe /C NY /N /M "Do you want to reset? [N/Y]"
    if errorlevel 2 set "x="
)
if not defined x set /P "x=X: "
endlocal

The command CHOICE is available by default since Windows Vista and for Windows server versions since Windows server 2003. CHOICE removes always all normal spaces and horizontal tabs on both sides of the prompt text and then appends automatically a space after prompt text.

A really safe solution with set /P working for any user input without using delayed environment variable expansion is as follows with N as default which is used on user does not input anything at all.

@echo off
setlocal EnableExtensions DisableDelayedExpansion
if not defined x goto PromptForX

set "yes=N"
set /P "yes=Do you want to reset? [N/Y] "
rem Remove all double quotes from user input string.
set "yes=%yes:"=%"
rem Has the user entered just one or more double quotes?
if not defined yes goto PromptForX
rem Now it is safe to compare the strings which cannot result anymore in a
rem syntax error caused by user input or doing something completely different
rem than the string comparison if the user input a command line which would
rem have changed this IF command line to a completely different command line.
if /I "%yes%" == "y" set "x="

:PromptForX
if not defined x set /P "x=X: "
endlocal

Command SET does not append a space to prompt text. The prompt text must be with space at end defined in the batch file.

Another safe solution using set /P with usage of delayed expansion is:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
if defined x (
    set "yes=N"
    set /P "yes=Do you want to reset? [N/Y] "
    setlocal EnableDelayedExpansion
    if /I !yes! == y (endlocal & set "x=") else endlocal
)
if not defined x set /P "x=X: "
endlocal

First the previous environment is restored with endlocal and next set "x=" is executed by Windows command processor to undefine this environment variable in this local environment on user entered really y or Y while just previous environment is restored on user entered anything else or has not entered something at all. See also Single line with multiple commands using Windows batch file for more information about the operator &.

I recommend to read also this answer for details about the commands SETLOCAL and ENDLOCAL and what happens in background on each execution of these two commands.

For a full explanation of the three solutions read my answer on:
How to stop Windows command interpreter from quitting batch file execution on an incorrect user input?

Note: Change the last line from just endlocal to endlocal & set "x=%x%" in all three batch files if the environment variable x should be defined with new value also outside the demo batch files.

To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.

  • choice /?
  • echo /?
  • endlocal /?
  • goto /?
  • if /?
  • rem /?
  • set /?
  • setlocal /?
Mofi
  • 46,139
  • 17
  • 80
  • 143