Why does a non-interactive batch script think I've pressed control-C?
So my batch script is ticking along nicely when suddenly this appears in the output log:
21:27:13.99 c:\apps\w7lab-scripting>some-command
Error 3221225786
^CTerminate batch job (Y/N)?
and the script stops dead.
The batch script is running in session zero, so I know it didn't receive a real control-C, and none of my code calls GenerateConsoleCtrlEvent
so that can't be it. The only clue is that some-command
was communicating with an interactive application at the time, and that application's console received a control-C. The expected behaviour was for some-command
to display the other application's exit code, then exit with the same code. The batch script would have dealt with the error appropriately, if it hadn't stopped dead.
What's going on here?
The magic here is in exit code 3221225786, aka 0xC000013A or STATUS_CONTROL_C_EXIT.
The interactive application received a control-C, and didn't catch it, so as expected, it was aborted with STATUS_CONTROL_C_EXIT. The some-command
application correctly reported this as the remote application's exit code, and passed it back to the batch script.
What I hadn't realized was that cmd.exe
detects control-C in a batch script in exactly this way, by checking whether a child process returns STATUS_CONTROL_C_EXIT. So by returning this error code I was inadvertently stopping the batch script.
This can be demonstrated with a simple batch script:
cmd /c exit 3221225786
echo hello
which, when run, produces
C:\working\test>cmd /c exit 3221225786
^CTerminate batch job (Y/N)?