为什么非交互式批处理脚本认为我已按下control-C?

时间:2014-08-22 10:21:19

标签: windows batch-file

因此,当输出日志中出现突然出现的情况时,我的批处理脚本正在顺利进行:

21:27:13.99 c:\apps\w7lab-scripting>some-command
Error 3221225786
^CTerminate batch job (Y/N)? 

并且脚本停止了。

批处理脚本在会话0中运行,所以我知道它没有收到真正的control-C,而且我的代码都没有调用GenerateConsoleCtrlEvent所以不能这样做。唯一的线索是some-command当时正在与交互式应用程序进行通信,并且 应用程序的控制台收到了一个控件-C。 some-command的预期行为是显示其他应用程序的退出代码,然后使用相同的代码退出。如果批处理脚本没有停止,那么它将适当地处理错误。

这里发生了什么?

2 个答案:

答案 0 :(得分:13)

这里的神奇之处在于退出代码3221225786,即0xC000013A或STATUS_CONTROL_C_EXIT。

交互式应用程序收到了一个control-C,并没有捕获它,因此正如预期的那样,它被STATUS_CONTROL_C_EXIT中止。 some-command应用程序正确地将此报告为远程应用程序的退出代码,并将其传递回批处理脚本。

我没有意识到,cmd.exe通过检查子进程是否返回STATUS_CONTROL_C_EXIT,以这种方式检测批处理脚本中的control-C。因此,通过返回此错误代码,我无意中停止了批处理脚本。

这可以通过简单的批处理脚本来演示:

cmd /c exit 3221225786
echo hello

,当运行时,产生

C:\working\test>cmd /c exit 3221225786
^CTerminate batch job (Y/N)?

答案 1 :(得分:-2)

或者,可以使用引发残酷的批处理结束(来自https://superuser.com/a/805637)的命令终止批处理会话,这些命令可以是以下任意一种(试图将STDERR馈入STDIN中断):

cd invalidPath 2>&0
vol x 2>&0    
move nonExistentFile 2>&0
set nonExistentVariable 2>&0
dir nonExistentFile 2>&0

因此,子例程可以是:

:SubSelfTerminate
    cd invalidPath 2>&0
exit /b 0

将从主批次中调用为:

call :SubSelfTerminate

注意:子例程中的“退出/ b 0”是无用的,因为它总是会被忽略,但会将子例程标记为结束。