How to Implement a Yes/No/Cancel Three-Option Prompt in Batch Script
Simple dual-choice prompts (Yes/No) are ubiquitous, but often you need a third option: Cancel. While "No" might mean "Don't do this, but keep going," "Cancel" usually means "Abort the entire script immediately." Providing this third choice prevents users from being "trapped" in a logic loop they didn't intend to enter.
In this guide, we will demonstrate how to use the choice command to implement a professional three-option prompt.
Method 1: The Native CHOICE Command (Recommended)
The choice command is the standard way to handle multi-option inputs in Windows. It is fast, handles errors automatically, and doesn't require the user to press Enter.
Implementation Script
@echo off
setlocal
echo.
echo Save configuration changes before exiting?
echo.
:: /c YNC (Options: [Y]es, [N]o, [C]ancel)
:: /m "Select an option: " (Custom prompt message)
:: /n (Do not display the choice keys in the prompt)
choice /c YNC /n /m "Select [Y]es, [N]o, or [C]ancel: "
:: Errorlevel values correspond to the order of choices in /c:
:: Errorlevel 1 = Y (first choice)
:: Errorlevel 2 = N (second choice)
:: Errorlevel 3 = C (third choice)
if %errorlevel% equ 3 goto :cancel_action
if %errorlevel% equ 2 goto :no_action
if %errorlevel% equ 1 goto :yes_action
:yes_action
echo.
echo [SAVING] Configuration saved.
goto :end
:no_action
echo.
echo [SKIP] Proceeding without saving.
goto :end
:cancel_action
echo.
echo [ABORT] Operation canceled by user.
pause
exit /b 1
:end
echo.
echo Script finished.
endlocal
pause
How choice errorlevels work:
- The
errorlevelis set to the 1-based index of the selected choice in the/cstring. - For
/c YNC,Y= 1,N= 2,C= 3. - The
if errorlevel Nsyntax checks whether the errorlevel is greater than or equal to N. This meansif errorlevel 1matches all values 1, 2, and 3, which is not what you want. The correct approach is to check for equality (if %errorlevel% equ N) or to check from highest to lowest:if errorlevel 3 goto :cancel_actionif errorlevel 2 goto :no_actionif errorlevel 1 goto :yes_action
Adding a Timeout and Default Choice
For unattended scripts, you can add a timeout that defaults to "Cancel" after a set number of seconds:
choice /c YNC /t 10 /d C /n /m "Select [Y]es, [N]o, or [C]ancel (auto-cancel in 10s): "
/t 10: Wait 10 seconds for input./d C: Default toC(Cancel) if no key is pressed.
Method 2: The SET /P Method (Legacy/Custom)
If you need the user to type out full words or handle custom characters that choice doesn't support, you can use set /p. This method is more flexible but requires manual input validation.
Implementation Script
@echo off
setlocal enabledelayedexpansion
:prompt
set "userInp="
set /p "userInp=Install Update? (Yes / No / Cancel): "
:: Clear leading/trailing spaces
for /f "tokens=* delims= " %%a in ("!userInp!") do set "userInp=%%a"
:: Use IF /I for case-insensitive matching
if /i "!userInp!"=="Yes" goto :yes_action
if /i "!userInp!"=="No" goto :no_action
if /i "!userInp!"=="Cancel" goto :cancel_action
:: Handle invalid input
echo Invalid selection. Please type "Yes", "No", or "Cancel".
goto :prompt
:yes_action
echo.
echo [INSTALL] Starting update...
goto :end
:no_action
echo.
echo [SKIP] Update skipped.
goto :end
:cancel_action
echo.
echo [ABORT] Operation canceled by user.
pause
exit /b 1
:end
echo.
echo Script finished.
endlocal
pause
Improvements over the original:
- Input trimming: Added
for /f "tokens=* delims= "to remove leading and trailing spaces from the input, preventing issues like" Yes"or"Cancel "from failing the comparison. - Case-insensitive matching: Used
if /ito handle variations likeyes,YES,Yes, etc. - Input loop: Added a
:promptloop to re-ask the question if the input is invalid, rather than silently falling through to the end of the script.
Comparisons: Choice vs. Set /P
| Feature | choice | set /p |
|---|---|---|
| User Effort | Single key (no Enter). | Type word + Enter. |
| Validation | Automatic (rejects other keys). | Manual if checks required. |
| Speed | Highly efficient. | Slower for the user. |
| Complexity | Simple indices (1, 2, 3). | String comparisons. |
| Timeout Support | Yes (/t flag). | No. |
| Case Sensitivity | Case-insensitive by default. | Requires /i flag in if statements. |
Verdict: Use choice for almost all scenarios. It is more robust, prevents typos, and supports timeouts. Use set /p only when you need the user to type arbitrary text or when you must support Windows versions prior to Vista (which lack the choice command).
Best Practices
- Logical Order: Follow the industry standard "Yes, No, Cancel" order. Users are conditioned to look for these in this sequence.
- Explicit Labels: Always provide a
gotofor each choice. Do not rely on "falling into" the next section of code, as this leads to "spaghetti" logic that is hard to debug and maintain. - Default with Timeout: For administrative scripts, consider adding a timeout to your
choicecommand:choice /c YNC /t 10 /d C /m "...". This ensures that if no one is at the desk, the script defaults to "Cancel" for safety. - Confirm the Abort: If the user selects "Cancel" on a major operation, show a final "Operation Aborted" message so they know exactly why the script stopped.
- Use
/nto Hide Choice Keys: The/nflag preventschoicefrom displaying the available keys in the prompt (e.g.,[Y,N,C]?). This allows you to write a cleaner, more custom prompt message. - Exit with Error Code on Cancel: When the user cancels, use
exit /b 1(or another non-zero value) to signal failure to the calling process. This is important for scripts that are part of larger automation chains.
Conclusion
A three-option prompt provides a level of interactive granular control that simple Yes/No toggles lack. By using the choice command to facilitate Yes/No/Cancel inputs, you empower your users to manage their workflows with confidence, allowing them to save, skip, or safely abort processes as needed. This leads to a more professional and user-friendly automation tool.