2021.4.15
INASOFT
/トップ/マウスふるふる ダウンロード/WebHelp/ヘルプトップ
OS終了拒絶方法
本ソフトには、スクリーン セーバー/スリープモードへ入ることを防ぐほかに、OSの終了(再起動・ログオフを含む)をなるべく拒否するようにする機能も搭載しています(シャットダウン抑止機能)。
メインのウィンドウプロシージャに次のように書くと、このプログラムが動作中はOSの終了をなるべく拒否するようになります。
(Windows XPまでは、WM_QUERYENDSESSIONにreturn 0;するだけでOS終了拒否できましたが、Windows Vista以降でOS終了拒否をするには、ShutdownBlockReasonCreate() APIで拒否理由をOSに伝える必要が生じました)
case WM_QUERYENDSESSION: // Windowsセッションの終了予告 if ( /* シャットダウンさせたくない場合 */ ) { // Windows Vista以降なら、シャットダウン中止の理由付けが必要 ShutdownBlockReasonCreate(hWnd, _T("シャットダウン抑止機能が有効")); return 0; // OS終了不可 } else { // Windows Vista以降なら、ShutdownBlockReasonCreateの解除 ShutdownBlockReasonDestroy(hWnd); return 1; // OS終了可能 } case WM_ENDSESSION: // Windowsセッションの終了 if (wParam == TRUE) { // 緊急で終了 DestroyWindow(hWnd); } else { // OS終了の拒否に成功 } break;
今回は、WM_QUERYENDSESSIONの中に書く方法を採りましたが、必ずしもここに書く必要はなく、シャットダウンを拒否したい処理に入る箇所でShutdownBlockReasonCreate() APIを呼び出し、シャットダウンを拒否したい処理から出る箇所でShutdownBlockReasonDestroy() APIを呼び出すのでも構いません。

ところで、このプログラムをWindows XP以前のOS上でも動作させたい場合であっても、ShutdownBlockReasonCreate()、ShutdownBlockReasonDestroy() APIを呼び出すコードを書いただけで、プログラム自体が起動不可となります。if分でOSバージョンの条件分岐をさせていたとしてもダメです。
もし、Windows XPでも起動したい場合は、ShutdownBlockReasonCreate()、ShutdownBlockReasonDestroy() APIが利用可能な場合のみ、関数ポインタ経由で呼び出すようなプログラムを作成する必要があります。
// シャットダウンブロックの理由登録関数の定義 BOOL altShutdownBlockReasonCreate(HWND hWnd, LPCWSTR strReason) { typedef BOOL (WINAPI *PF_ShutdownBlockReasonCreate)(HWND, LPCWSTR); PF_ShutdownBlockReasonCreate pfShutdownBlockReasonCreate = NULL; HMODULE hDLL = LoadLibrary("User32.dll"); BOOL bRes = 0; if ( hDLL ) { pfShutdownBlockReasonCreate = (PF_ShutdownBlockReasonCreate)::GetProcAddress(hDLL, "ShutdownBlockReasonCreate"); if (pfShutdownBlockReasonCreate) { bRes = pfShutdownBlockReasonCreate(hWnd, strReason); } FreeLibrary( hDLL ); } return bRes; } // シャットダウンブロックの理由解除関数の定義 BOOL altShutdownBlockReasonDestroy(HWND hWnd) { typedef BOOL (WINAPI *PF_ShutdownBlockReasonDestroy)(HWND); PF_ShutdownBlockReasonDestroy pfShutdownBlockReasonDestroy = NULL; HMODULE hDLL = LoadLibrary("User32.dll"); BOOL bRes = 0; if ( hDLL ) { pfShutdownBlockReasonDestroy = (PF_ShutdownBlockReasonDestroy)::GetProcAddress(hDLL, "ShutdownBlockReasonDestroy"); if (pfShutdownBlockReasonDestroy) { bRes = pfShutdownBlockReasonDestroy(hWnd); } FreeLibrary( hDLL ); } return bRes; } // プログラム本体 : : : case WM_QUERYENDSESSION: // Windowsセッションの終了予告 if ( /* シャットダウンさせたくない場合 */ ) { // Windows Vista以降なら、シャットダウン中止の理由付けが必要 altShutdownBlockReasonCreate(hWnd, _T("シャットダウン抑止機能が有効")); return 0; // OS終了不可 } else { // Windows Vista以降なら、ShutdownBlockReasonCreateの解除 altShutdownBlockReasonDestroy(hWnd); return 1; // OS終了可能 } case WM_ENDSESSION: // Windowsセッションの終了 if (wParam == TRUE) { // 緊急で終了 DestroyWindow(hWnd); } else { // OS終了の拒否に成功 } break; : : :
なお、プログラミングせずとも、これと同じことは、例えば「メモ帳」を開き、「名前を付けて保存」ダイアログを開きっぱなしにしておくなどでも可能です。
WM_QUERYENDSESSIONは、システムから終了確認のために送信されるメッセージですので、「Windowsの終了と共に自プログラムも終了したい」という目的のために、ここでDestroyWindow() APIで自ウィンドウを閉じる必要はありません。終了処理は、その後にシステムから送信されるWM_ENDSESSIONで行えばよいです。
注意点としては、WM_QUERYENDSESSIONにreturn 0;を返却したり、ShutdownBlockReasonCreate() APIで理由文字列を提示したとしても、必ずしもOS終了を止められるとは限りません。ユーザーの選択だったり、シャットダウンのオプションで「強制」が付けられたりしていた場合は、終了させられてしまいます。また、システムが不安定でOSが意図せず再起動・シャットダウンしてしまうような場合もあり得ます。
Windows 10以降では、ユーザーの意図でシャットダウンする場合というよりも、強制的なWindows Updateの適用で、ユーザーの意図に反してシャットダウンされることが多いように思います。そういった場合にも、このAPIの活用が見込まれます。
おまけページの目次へ戻る
目次へ
※このページは、ソフトウェアに付属のヘルプファイルをWeb用に再構築したものです。大部分に自動変換を施しているため、一部は正しく変換しきれずに表示の乱れている箇所があるかもしれませんが、ご容赦下さい。また、本ドキュメントはアーカイブドキュメントであり、内容は、右上の作成日付の時点のものとなっております。一部、内容が古くなっている箇所があるかと思いますが、あらかじめご了承下さい。
※このページへは、自由にリンクしていただいてかまいません。
■このページに関するご意見をお待ちしております → フィードバックページ