Skip to main content

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
note

This is useful for creating uninterruptible pauses, but it doesn't allow for a graceful exit.

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 /C list (e.g., 'X'), ERRORLEVEL is set to its index (e.g., 1).
  • If the timeout completes without a keypress, ERRORLEVEL is set to the index of the default choice.
  • If the user presses Ctrl+C, the CHOICE command immediately exits and sets the ERRORLEVEL to 0.

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+C check only happens when the CHOICE command is running. If your script is in the middle of a long, single command (like a ROBOCOPY of 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 CHOICE check in between each chunk.
  • The BREAK Command: An older DOS command, BREAK, can be used to control how cmd.exe handles Ctrl+C. BREAK ON makes cmd.exe check for Ctrl+C more frequently. However, the CHOICE and TIMEOUT methods are more modern and provide more direct control within a script, making BREAK largely 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 /NOBREAK to create a pause during which Ctrl+C is ignored. This is useful for short, critical sections of code.
  • Use the CHOICE command with a timeout as the main delay in your loops to detect a Ctrl+C press. This is the recommended best practice.
  • A Ctrl+C press during a CHOICE command will set %ERRORLEVEL% to 0.
  • Check for this 0 value to trigger a jump to a cleanup routine before your script exits.