前回に続き今回もデスクトップアプリ開発におけるリスタートマネージャー(Restart Manager)について投稿したいと思います。今回は停止される側の実装が終わった後に動作確認をする方法です。
デスクトップアプリの認定要件
Windows Vista以降に対応しているという宣言しているアプリでも、いまだにリスタートマネージャーに対応していないことが多いです。
アプリのリスタートマネージャーの対応は、Windows Vista以降のデスクトップアプリの認定要件となりました。そのため、Windows Vista以降に対応していると宣言しているアプリは、本来、リスタートマネージャーに対応しているはずです。
アプリの認定条件などは各Windowsにより異なり、以下のような名称がついていました。
- Windows Vista: The OEM Ready Program
- Windows 7: Windows 7 Client Software Logo Program (英語)
- Windows 8/8.1/10: Windows certification (英語)
Windows Vistaに関しては、すでにマイクロソフトのサイトからも情報が削除されたらしく、リンクが見つけられませんでした。
最新の認定の要求事項は、
Certification requirements for Windows Desktop Apps (英語)
に記載があります。
上記のデスクトップアプリの認定要件を実装観点で満たしているかをテストするツールをマイクロソフトは提供しています。Windows App Certification Kitです。このツールでのテストに合格しない限り、マイクロソフトは、アプリが対象のWindowsに対応していると認定してくれません。
要件の中の第4章にリスタートマネージャーの記述があります。抜粋すると、
4. Apps must adhere to system restart manager messages
When users initiate shutdown, they usually have a strong desire to see shutdown succeed; they may be in a hurry to leave the office and just want their computers to turn off. Apps must respect this desire by not blocking shutdown. While in most cases, a shutdown may not be critical, apps must be prepared for the possibility of a critical shutdown.
- 4.1 Your app must handle critical shutdowns appropriately
- In a critical shutdown, apps that return FALSE to WM_QUERYENDSESSION will be sent WM_ENDSESSION and closed, while those that time out in response to WM_QUERYENDSESSION will be terminated.
- 4.2 A GUI app must return TRUE immediately in preparation for a restart WM_QUERYENDSESSION with LPARAM = ENDSESSION_CLOSEAPP(0x1). Console apps can call SetConsoleCtrlHandler to specify the function that will handle shutdown notifications. Service apps can call RegisterServiceCtrlHandlerEx to specify the function that will receive shutdown notifications.
- 4.3 Your app must return 0 within 30 seconds and shut down WM_ENDSESSION with LPARAM = ENDSESSION_CLOSEAPP(0x1). At a minimum, app should prepare by saving any user data and state the information that is needed after a restart.
- 4.4 Console apps that receive the CTRL_C_EVENT notification should shut down immediately 4.5 Drivers must not veto a system shutdown event
**Note: Apps that must block shutdown because of an operation that cannot be interrupted should explain the reason to the user.** Use ShutdownBlockReasonCreate to register a string that explains the reason to the user. When the operation has completed, the app should call ShutdownBlockReasonDestroy to indicate that the system can be shut down.
となります。わかりやすく日本語にすると、
4. アプリはシステムのリスタートマネージャーのメッセージに従わなければなりません
ユーザーがシャットダウンを開始するとき、ユーザーはシャットダウンが成功することを強く希望します。彼らはオフィスを離れるのを急いでおり、コンピュータの電源を早く落としたいだけなのかもしれません。アプリはシャットダウンをブロックしないようにしてこの要求を尊重しなければなりません。また、クリティカルシャットダウンはほとんど発生しないかもしれませんが、アプリはクリティカルシャットダウンの発生可能性に備える必要があります。
- 4.1 アプリはクリティカルシャットダウンを適切に処理する必要があります
- クリティカルシャットダウンでは、WM_QUERYENDSESSIONにFALSEを返したアプリには、WM_ENDSESSIONが送信され、閉じられます。WM_QUERYENDSESSIONに応答せずタイムアウトしたアプリは強制的に終了させられます。
- 4.2 GUIアプリは、WM_QUERYENDSESSION (LPARAM = ENDSESSION_CLOSEAPP (0x1))で再起動の準備をしてすぐにTRUEを返さなければなりません。
- コンソールアプリは、SetConsoleCtrlHandlerを呼び出してシャットダウン通知を処理する関数を指定することができます。
- サービスアプリはRegisterServiceCtrlHandlerExを呼び出して、シャットダウン通知を受け取る関数を指定できます。
- 4.3 GUIアプリはパラメーターがLPARAM = ENDSESSION_CLOSEAPP (0x1) であるWM_ENDSESSIONメッセージに対して30秒以内に0を返し、シャットダウンする必要があります。少なくとも、アプリはユーザーデータとアプリの状態を保存することによって再起動後に必要な情報を準備をする必要があります。
- 4.4 コンソールアプリはCTRL_C_EVENT通知を受け取るすぐにシャットダウンする必要があります
- 4.5ドライバはシステムシャットダウンイベントを拒否してはいけません
- 注:中断できない操作の処理中のためにシャットダウンをブロックする必要があるアプリは、その理由をユーザーに説明する必要があります。 ShutdownBlockReasonCreateを使用して、理由をユーザーに説明する文字列を登録します。ブロックの原因となる操作が完了したら、アプリケーションはShutdownBlockReasonDestroyを呼び出して、システムをシャットダウンできることを示します。
リスタートマネージャーの動作確認に使うツール
リスタートマネージャーの対応状況をテストするツールは、現在であれば、Windows App Certification Kitの中にあります。rmlogotest.exe
という実行ファイルです。このツールは、Windows App Cerification KitはWindows SDKに含まれています。最新のWindows SDKは、Windows 10 SDKとなります。Windows 10 SDKをインストールすると、Windows App Cerification Kitは、
64ビットWindows: C:\Program Files (x86)\Windows Kits\10\App Certification Kit\ 32ビットWindows: C:\Program Files\Windows Kits\10\App Certification Kit\
にインストールされます。このフォルダーの中にrmlogotest.exe
というファイルがあます。使い方は、引数なしで実行すると表示されます。
Usage: RmLogoTest.exe <app/svc process id>
単純にテストしたい実行ファイルを起動し、そのプロセスのプロセスIdを指定するだけです。ただし、テストするときは、管理者権限のコマンドプロンプトでRmLogoTest.exeを起動する必要があります。
動作確認をする
動作確認の手順は以下の通りです。
- 管理者権限のコマンドプロンプトを起動する
- App Certification Kitのフォルダーに移動する
cd C:\Program Files (x86)\Windows Kits\10\App Certification Kit - タスクマネージャーを起動する。「詳細」タブを開く
- テストする対象のプログラムを起動する
- 起動したプログラムのプロセスIDをタスクマネージャーで確認する
- コマンドプロンプトで、RmLogoTest.exe をプロセスIDを引数にして起動する
- 表示されるテスト結果を確認する
です。
手順5のタスクマネージャーでのプロセスID(PID)の確認は、下記の図のようにPIDカラムを確認します。
テストで失敗すると以下のようにLOGO Validation FAILED.
と表示されます。
テストで成功した場合は、LOGO Validation PASSED.
と表示されますが、「アプリを終了するのみ」の場合と、「アプリを再起動する」の場合で、表示が異なります。
上記のようにアプリが再起動した場合は、
Note: One or more applications or services were restarted
というメッセージも表示されます。リスタートマネージャーに対応したというときは、この状態になるのが望ましいです。
実際にFile Package Appのパッケージで動作を確認する
アプリをリスタートマネージャーに対応する
前回の投稿で説明したとおり、File Package Appで作成したパッケージは、おおまかに以下の順番で処理が進みます。
- ファイルの破損チェック。破損していればエラーメッセージを表示して終了する
- 評価版パッケージであれば使用期限のメッセージを表示する
- 進捗ダイアログを表示する(最後まで表示したまま)
- ファイルの展開のために管理者権限が必要であればエレベーションする
- 実行制限の条件をチェックする。実行制限の条件に一致すればエラーメッセージを表示して終了する
- 展開先フォルダーの設定がユーザー選択であればフォルダー選択ダイアログを表示する
- ファイルを展開する
- ファイルを実行する設定であれば、ファイルを実行する
- 作業フォルダーを削除する
- 進捗ダイアログのメッセージを完了に変更する
そして、それぞれの処理手順で以下の対応をしました。
- アプリを終了するのみ
処理手順1, 8, (9), 10 - アプリを再起動する
処理手順2, 3, 4, 5, 6, 7
RmLogoTest.exe
を利用して、上記の各処理手順で挙動を確認したところ、File Package Appのバージョン0.6.2で作成したパッケージは、期待通りの挙動をしました。バージョン0.6.2以前で作成したパッケージは、すべての手順において「アプリを終了するのみ」の挙動となります。
デスクトップアプリの認定要件の中のリスタートマネージャーの要件の詳細と、そのテスト方法について説明しました。
File Package Appのパッケージ作成アプリ部分のリスタートマネージャー対応では、ユーザーの入力したデータが多くあるため、アプリの状態の保存・復元が必須となります。その対応については、実装が完了後、機会があったら説明したいと思います。
次回は、Windows OSのリスタートマネージャーに関する挙動を確認するためのテストツールについて投稿します。