SetConsoleCtrlHandler 函数

从调用进程的处理程序函数列表中添加或删除应用程序定义的 HandlerRoutine 函数

如果未指定处理程序函数,则该函数将设置可继承的属性,该属性确定调用进程是否忽略 Ctrl+C 信号。

语法

BOOL WINAPI SetConsoleCtrlHandler(
  _In_opt_ PHANDLER_ROUTINE HandlerRoutine,
  _In_     BOOL             Add
);

参数

HandlerRoutine [in, optional]
指向应用程序定义的要添加或删除的 HandlerRoutine 函数的指针。 此参数可以为 NULL

Add [in]
如果此参数为 TRUE,则添加处理程序;如果 FALSE,则删除处理程序

如果 HandlerRoutine 参数为 NULL,TRUE 值会使调用进程忽略 Ctrl+C 输入,而 FALSE 值会还原 Ctrl+C 输入的正常处理过程。 此属性(忽略或处理 Ctrl+C)由子进程继承。

返回值

如果该函数成功,则返回值为非零值。

如果函数失败,则返回值为零。 要获得更多的错误信息,请调用 GetLastError

注解

此函数为控制台应用程序和服务提供的通知与 WM_QUERYENDSESSION 通过消息泵为图形应用程序提供的通知类似。 你还可从图形应用程序中使用此函数,但不保证它会在 WM_QUERYENDSESSION 的通知之前到达。

每个控制台进程都有自己的应用程序定义的 HandlerRoutine 函数的列表,这些函数可处理 Ctrl+CCtrl+Break 信号。 处理程序函数还处理用户关闭控制台、注销或关闭系统时由系统生成的信号。 最初,每个进程的处理程序列表仅包含调用 ExitProcess 函数的默认处理程序函数。 控制台进程通过调用 SetConsoleCtrlHandler 函数(该函数不影响其他进程的处理程序函数列表)来添加或删除其他处理程序函数。 当控制台进程收到任何控制信号时,将基于最后一次注册的首次调用,调用其处理程序函数,直到其中一个处理程序返回 TRUE 为止。 如果所有处理程序均未返回 TRUE,则调用默认处理程序。

调用 AttachConsoleAllocConsoleFreeConsole 会将客户端进程中的控件处理程序表重置为其初始状态。 当附加的控制台会话更改时,必须重新注册处理程序。

对于控制台进程,Ctrl+CCtrl+Break 键组合通常被视为信号(CTRL_C_EVENT 和 CTRL_BREAK_EVENT)。 当具有键盘焦点的控制台窗口收到 Ctrl+CCtrl+Break 时,该信号通常会传递到共享该控制台的所有进程。

CTRL+BREAK 始终被视为信号,但可通过阻止调用处理程序函数的三种方式,来更改典型的 CTRL+C 行为:

  • SetConsoleMode 函数可为控制台的输入缓冲区禁用 ENABLE_PROCESSED_INPUT 模式,因此 Ctrl+C 会被报告未键盘输入而不是信号
  • 如果使用 NULL 和 TRUE 参数调用 SetConsoleCtrlHandler,则会导致调用进程忽略 Ctrl+C 信号。 此属性由子进程继承,但只要不影响现有进程,任何进程都可启用或禁用此属性。
  • 如果正在调试控制台进程并且尚未禁用 CTRL+C 信号,则系统将生成 DBG_CONTROL_C 异常。 此异常仅为优化调试器引发,并且应用程序不应使用异常处理程序来处理该异常。 如果由调试器处理异常,应用程序将不会注意到 Ctrl+C,但有一个例外:可报警等待将终止。 如果调试器传递未经处理的异常,则 CTRL+C 会被传递到控制台进程并视为信号,如前文所述。

控制台进程可使用 GenerateConsoleCtrlEvent 函数将 Ctrl+CCtrl+Break 信号发送到控制台进程组

用户关闭控制台、注销或关闭系统时,系统将生成 CTRL_CLOSE_EVENT、CTRL_SHUTDOWN_EVENT 和 CTRL_SHUTDOWN_EVENT 信号,以便进程可以在终止之前进行清理。 在处理前面提到的三种信号中的任何一种时,控制台函数或调用控制台函数的任何 C 运行时函数可能无法可靠地运行。 原因是在执行处理信号处理程序之前,可能已调用部分或全部内部控制台清理例程。

Windows 7、Windows 8、Windows 8.1 和 Windows 10:

如果控制台应用程序加载 gdi32.dll 或 user32.dll 库,则调用 SetConsoleCtrlHandler 时指定的 HandlerRoutine 函数不会针对 CTRL_LOGOFF_EVENT 和 CTRL_SHUTDOWN_EVENT 事件进行调用。 操作系统会将加载 gdi32.dll 或 user32.dll 的进程识别为 Windows 应用程序而不是控制台应用程序。 此行为也适用于不直接调用 gdi32.dll 或 user32.dll 中的函数的控制台应用程序,但会调用函数(如 Shell 函数),并在 gdi32.dll 或 user32.dll 中依次调用函数。

若要接收有关用户注销或关闭设备的事件,请在控制台应用程序中创建一个隐藏的窗口,然后处理隐藏窗口收到的 WM_QUERYENDSESSIONWM_ENDSESSION 窗口消息。 可通过调用 CreateWindowEx 方法并将 dwExStyle 参数设置为 0 来创建隐藏窗口。 下面链接的基本处理程序示例中包含了一个这样的示例。

示例

相关示例,请参阅注册控件处理程序函数

要求

   
最低受支持的客户端 Windows 2000 Professional [仅限桌面应用]
最低受支持的服务器 Windows 2000 Server [仅限桌面应用]
Header ConsoleApi.h (via WinCon.h, include Windows.h)
Kernel32.lib
DLL Kernel32.dll
Unicode 和 ANSI 名称

另请参阅

控制台控件处理程序

控制台函数

ExitProcess

GenerateConsoleCtrlEvent

GetConsoleMode

HandlerRoutine

SetConsoleMode