如何让GenerateConsoleCtrlEvent与cmd.exe一起使用

时间:2013-09-02 01:35:23

标签: windows winapi cmd console-application windows-console

我正试图让GenerateConsoleCtrlEvent工作。这是我提出的最小例子:

#include <Windows.h>

static BOOL WINAPI handler(DWORD CtrlType)
{
    return TRUE;
}

int main()
{
    if (!SetConsoleCtrlHandler(&handler, TRUE))
    {
        throw 1;
    }

    STARTUPINFO si = {0};
    DWORD dwStartupFlags = 0;
    PROCESS_INFORMATION pi;
    if (!CreateProcess(
        NULL,
        "cmd.exe",
        NULL,
        NULL,
        FALSE,
        dwStartupFlags,
        NULL, // environ
        NULL, // cwd
        &si,
        &pi))
    {
        throw 1;
    }
    CloseHandle(pi.hThread);

    DWORD exitCode;
    while(true)
    {
        switch (WaitForSingleObject(pi.hProcess, 1000 * 10))
        {
          case WAIT_TIMEOUT:
            GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
            //WaitForSingleObject(pi.hProcess, INFINITE);
            break;

          case WAIT_OBJECT_0:
            GetExitCodeProcess(pi.hProcess, &exitCode);
            return exitCode;
        }
    }
    return -1;
}

所以我启动它,输入内容(没有换行符),然后等待10秒钟。调试器显示Ctrl-C事件。控制台显示Ctrl-C无效。

我跟踪了这​​个问题:主cmd.exe线程调用ReadConsoleW。在GenerateConsoleCtrlEvent的测试程序下,这不会返回。按下Ctrl-C会使其返回*lpNumberOfCharsRead==0

GenerateConsoleCtrlEvent使用kernel32!CtrlRoutine启动新主题。如果使用调试器冻结此线程,cmd.exe仍然表现得像按Ctrl-C一样。实际上,如果在返回按键后*lpNumberOfCharsRead==NULL返回时设置ReadConsoleW,则可以欺骗cmd.exe,使其相信已按下Ctrl-C。

cmd.exe在行为上不是唯一的:Python.exe的读取在Ctrl-C时立即返回,但在GenerateConsoleCtrlEvent时不返回。 Python.exe使用ReadFile。 (按下回车键后,Python.exe会注意到KeyboardInterrupt。)

所以问题是:为什么在按下Ctrl-C时ReadConsoleW会立即返回,而在调用GenerateConsoleCtrlEvent时却不会?据我所知,在Windows 7上,按Ctrl-C会发送由conhost.exe读取的消息,该消息与csrss.exe进行通信,NtCreateThreadEx调用kernel32!CtrlRoutine ReadConsoleW。按Ctrl-C时,我没有看到它做任何其他事情。但导致{{1}}返回的原因是什么?

0 个答案:

没有答案
相关问题