How to Handle User Interrupts (Ctrl+C) in a Batch Script
By default, when a user presses Ctrl+C in a command prompt window, the running batch script is halted, and the user is presented with the Terminate batch job (Y/N)? prompt. If they press Y, the script stops dead. This is a problem for any script that needs to perform a "cleanup" operation before it exits, such as deleting temporary files or logging a final status. An abrupt termination leaves this cleanup work undone.
A robust script needs to be able to "catch" or "handle" this Ctrl+C interrupt, allowing it to run a special block of code before it finally exits. This guide will teach you the two primary methods for managing Ctrl+C: a simple way to ignore the interrupt, and a more powerful way to detect it and run custom cleanup code using the CHOICE command.
The Default Behavior: Terminate batch job (Y/N)?
This is the standard behavior. If a script is in the middle of executing a command or is paused, pressing Ctrl+C will trigger this prompt. This is an "all or nothing" choice for the user and gives the script no control over its own termination.
Method 1: Ignoring Ctrl+C with TIMEOUT /NOBREAK
Sometimes, you have a critical section of your script that you do not want the user to be able to interrupt. The TIMEOUT command's /NOBREAK switch is perfect for this. When used, it creates a pause during which Ctrl+C is completely ignored.
This script runs a loop that cannot be stopped with Ctrl+C.
@ECHO OFF
ECHO --- Critical Process Running ---
ECHO This loop cannot be interrupted by Ctrl+C.
:Loop
ECHO Doing some very important work at %TIME%...
REM Pause for 5 seconds. During this time, Ctrl+C is ignored.
TIMEOUT /T 5 /NOBREAK > NUL
GOTO :Loop
This is useful for creating uninterruptible pauses, but it doesn't allow for a graceful exit.
Method 2 (Recommended): Detecting Ctrl+C with CHOICE
This is the most powerful and flexible method. It allows you to create a script that runs normally but, if the user presses Ctrl+C, it can detect the interrupt and jump to a special "cleanup" section of code before exiting. This is made possible by a special feature of the CHOICE command.
For example, this script runs a loop but checks for a Ctrl+C press every second. If detected, it jumps to a cleanup routine.
@ECHO OFF
ECHO --- Running a monitored process ---
ECHO Press Ctrl+C at any time to exit gracefully.
:MainLoop
ECHO Process is running...
REM Use CHOICE with a 1-second timeout as our main delay.
REM It waits for the user to press 'X' (a dummy choice).
CHOICE /C X /N /T 1 /D X > NUL
REM --- This is the interrupt check ---
IF "%ERRORLEVEL%"=="0" GOTO :UserInterrupted
GOTO :MainLoop
:UserInterrupted
ECHO.
ECHO [!!] Ctrl+C detected! Running cleanup routine...
REM (Your cleanup commands, like DEL %TEMP_FILE%, go here)
ECHO Cleanup complete. Exiting now.
GOTO :EOF
How the CHOICE Detection Method Works (ERRORLEVEL 0)
The CHOICE command uses %ERRORLEVEL% to report which key the user pressed. It has a special, built-in behavior for Ctrl+C:
- If the user presses a valid key from the
/Clist (e.g., 'X'),ERRORLEVELis set to its index (e.g., 1). - If the timeout completes without a keypress,
ERRORLEVELis set to the index of the default choice. - If the user presses
Ctrl+C, theCHOICEcommand immediately exits and sets theERRORLEVELto0.
This provides a unique and reliable signal that we can check for. The line IF "%ERRORLEVEL%"=="0" is a precise way of asking, "Was the last command interrupted by Ctrl+C?"
5. Common Pitfalls and How to Solve Them
-
Interrupting During a Long Command: The
Ctrl+Ccheck only happens when theCHOICEcommand is running. If your script is in the middle of a long, single command (like aROBOCOPYof a huge file), it cannot be gracefully interrupted by this method. The check will only occur after the long command finishes.- Solution: For long-running processes, break them into smaller chunks if possible, with a
CHOICEcheck in between each chunk.
- Solution: For long-running processes, break them into smaller chunks if possible, with a
-
The
BREAKCommand: An older DOS command,BREAK, can be used to control howcmd.exehandlesCtrl+C.BREAK ONmakescmd.execheck forCtrl+Cmore frequently. However, theCHOICEandTIMEOUTmethods are more modern and provide more direct control within a script, makingBREAKlargely unnecessary for this purpose.
6. Practical Example: A Robust Cleanup-on-Exit Script
This is the most common use case. The script creates a temporary file and must ensure that this file is deleted, whether the script finishes normally or is aborted by the user.
@ECHO OFF
SETLOCAL
SET "TempFile=%TEMP%\my_script_%RANDOM%.tmp"
ECHO --- Main Application ---
ECHO Creating temporary file: %TempFile%
ECHO "This is temporary data" > "%TempFile%"
ECHO.
ECHO The main process is now running. Press Ctrl+C to stop it.
ECHO.
:MainLoop
ECHO Working...
REM Use CHOICE as a 1-second, interruptible pause.
CHOICE /C X /N /T 1 /D X > NUL
IF "%ERRORLEVEL%"=="0" GOTO :Cleanup
GOTO :MainLoop
:Cleanup
ECHO.
ECHO --- Interrupted by user. Cleaning up... ---
IF EXIST "%TempFile%" (
DEL "%TempFile%"
ECHO Temporary file deleted.
)
GOTO :EOF
REM This script is designed so that normal completion is not yet reachable,
REM but in a real script, you would have an exit condition that also
REM calls GOTO :Cleanup to ensure the file is always deleted.
Conclusion
Handling Ctrl+C interrupts is the mark of a truly robust and professional batch script. It ensures that your script can perform critical cleanup tasks and exit gracefully instead of being abruptly terminated.
- Use
TIMEOUT /NOBREAKto create a pause during whichCtrl+Cis ignored. This is useful for short, critical sections of code. - Use the
CHOICEcommand with a timeout as the main delay in your loops to detect aCtrl+Cpress. This is the recommended best practice. - A Ctrl+C press during a
CHOICEcommand will set%ERRORLEVEL%to0. - Check for this
0value to trigger a jump to a cleanup routine before your script exits.