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 を無視または処理するこの属性は、子プロセスによって継承されます。
戻り値
関数が成功すると、戻り値は 0 以外になります。
関数が失敗した場合は、0 を返します。 詳細なエラー情報を得るには、GetLastError を呼び出します。
解説
この関数により、WM_QUERYENDSESSION によってメッセージ ポンプを備えたグラフィカル アプリケーションに提供されるのと似た通知が、コンソール アプリケーションやサービスに提供されます。 また、この関数はグラフィカル アプリケーションから使用することもできますが、WM_QUERYENDSESSION からの通知より前に到着する保証はありません。
各コンソール プロセスには、Ctrl+C および Ctrl+Break シグナルを処理するアプリケーション定義の HandlerRoutine 関数の、独自のリストがあります。 また、ユーザーがコンソールを閉じたり、ログオフしたり、システムをシャットダウンしたりしたときに、システムによって生成されるシグナルも、ハンドラー関数によって処理されます。 初期状態では、各プロセスのハンドラーの一覧には、ExitProcess 関数を呼び出す既定のハンドラー関数だけが含まれています。 コンソール プロセスによって SetConsoleCtrlHandler 関数が呼び出されてハンドラー関数の追加または削除が行われても、他のプロセスのハンドラー関数の一覧には影響しません。 コンソール プロセスが何らかの制御シグナルを受け取ると、そのハンドラー関数が、最後に登録されたものが最初に呼び出される順序で、いずれかのハンドラーが TRUE
を返すまで呼び出されます。 どのハンドラーからも TRUE
が返されない場合は、既定のハンドラーが呼び出されます。
AttachConsole、AllocConsole、または FreeConsole を呼び出すと、クライアント プロセスでコントロール ハンドラーのテーブルが初期状態にリセットされます。 アタッチされたコンソール セッションが変更されたときに、ハンドラーを再登録する必要があります。
コンソール プロセスの場合、通常、Ctrl+C と Ctrl+Break のキーの組み合わせは、シグナルとして扱われます (CTRL_C_EVENT と CTRL_BREAK_EVENT)。 キーボード フォーカスのあるコンソール ウィンドウが Ctrl+C または Ctrl+Break を受け取ると、通常、そのコンソールを共有するすべてのプロセスにシグナルが渡されます。
Ctrl+Break は常にシグナルとして扱われますが、3 つの方法で通常の Ctrl+C の動作を変更して、ハンドラー関数が呼び出されないようにすることができます。
- SetConsoleMode 関数を使用すると、コンソールの入力バッファーの ENABLE_PROCESSED_INPUT モードを無効にして、Ctrl+C がシグナルではなくキーボード入力として報告されるようにすることができます。
- NULL および TRUE 引数を使用して SetConsoleCtrlHandler を呼び出すと、呼び出し元プロセスで Ctrl+C シグナルが無視されます。 この属性は、子プロセスによって継承されますが、既存のプロセスに影響を与えることなく、任意のプロセスで有効または無効にすることができます。
- コンソール プロセスがデバッグ中で、Ctrl+C シグナルが無効にされていない場合は、システムによって DBG_CONTROL_C 例外が生成されます。 この例外はデバッガーのためにのみ生成されるので、アプリケーションで例外ハンドラーを使用してそれを処理しないでください。 デバッガーによって例外が処理された場合、アプリケーションで Ctrl+C を認識することはありませんが、1 つだけ例外があり、アラート可能な待機が終了します。 デバッガーによって例外がハンドルされずに渡されると、Ctrl+C がコンソール プロセスに渡され、前に説明したようにシグナルとして扱われます。
コンソール プロセスでは、GenerateConsoleCtrlEvent 関数を使用して、Ctrl+C または Ctrl+Break シグナルを、コンソール プロセス グループに送信できます。
ユーザーがコンソールを閉じるか、ログオフするか、システムをシャットダウンすると、終了前にプロセスでクリーンアップを実行できるように、システムによって CTRL_CLOSE_EVENT、CTRL_LOGOFF_EVENT、および CTRL_SHUTDOWN_EVENT シグナルが生成されます。 コンソール関数、またはコンソール関数を呼び出す C ランタイム関数は、前に説明した 3 つのシグナルの処理中は、確実に動作しない可能性があります。 これは、プロセス シグナル ハンドラーを実行する前に、一部またはすべての内部コンソール クリーンアップ ルーチンが呼び出される場合があるためです。
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 の関数を直接呼び出していないコンソール アプリケーションでも、シェル関数などの関数を呼び出し、その中で gdi32.dll または user32.dll の関数が呼び出されている場合は、やはりこの動作が発生します。
このような状況でユーザーがサインアウトしたとき、またはデバイスがシャットダウンしたときにイベントを受け取るには、コンソール アプリケーションで非表示のウィンドウを作成し、その非表示ウィンドウで受け取った WM_QUERYENDSESSION および WM_ENDSESSION ウィンドウ メッセージを処理します。 非表示ウィンドウを作成するには、CreateWindowEx メソッドを呼び出し、dwExStyle パラメーターを 0 に設定します。 この例については、以下にリンクされた基本的なハンドラーの例に含まれています。
例
例については、「コントロール ハンドラー関数の登録」を参照してください。
要件
サポートされている最小のクライアント | Windows 2000 Professional [デスクトップ アプリのみ] |
サポートされている最小のサーバー | Windows 2000 Server [デスクトップ アプリのみ] |
ヘッダー | ConsoleApi.h (WinCon.h 経由、Windows.h をインクルード) |
ライブラリ | Kernel32.lib |
[DLL] | Kernel32.dll |
Unicode 名と ANSI 名 |