サービスでデスクトップと対話が行えない

こんにちは、Windows プラットフォーム サポートの栗山です。

今回は、サービス プログラムからデスクトップと対話が行えず、マウスやキーボードによる操作ができないという現象について、ご紹介いたします。
なお、ご紹介する内容は Windows 10リリース時から変更はありませんが、よくお問い合わせをいただきますので情報公開をさせていただきます。

自社にて開発されているサービス プログラムのご参考としていただけますと幸いです。

[現象]
①サービス プログラムから GUI アプリケーションを起動後、タスクバーへ「対話型サービスの検出」のアイコンが表示されるのでクリックする。 → 「対話型サービスの検出」画面が表示される。     

②「対話型サービスの検出」ダイアログの「⇒メッセージの表示」文字列をクリックする。
→ 下記の画面に切り替わる。

③上記画面で、マウス、キーボードでの操作ができない。
  (しばらく時間が経つと、自動的に元の画面に戻る)

 ※Windows 7/8.1 などは、以下のようにここでコマンドプロンプトを使い、プログラムと対話できます。(Windows 10/Windows Server 2016 では、それができません。)

[詳細]
この事象は、Windows 10 および Windows Server 2016 における想定された動作です。
理由としては、サービスが直接デスクトップと対話することがセキュリティ上推奨していないものであり、それに伴って OS にデザイン変更が加えられたためです。

また、具体的なスケジュールは決定しておりませんが、将来的には Interactive Services Detection サービスそのものが OS 上から削除される予定です。

- 補足
Interactive Services Detection サービスとは、ユーザー/デスクトップ  (セッション 1 以降) がシステム サービス (セッション 0) との対話を可能にするためのサービスです。
かつて、Windows XPやWindows Server 2003/2003 R2では、ローカル コンソールからログオンするユーザーは、システム サービスが実行されるのと同じ「セッション 0」にログオンしていました。
しかしながら、それはシステム サービスの実行上、セキュリティのリスクが高まったため、Windows Vista では、この「セッション 0」が「セッション 1 以降」と分離されました。
この分離された「セッション 0」 と 「セッション 1 以降」 を緩和的に対話できるようにしたのが、” Interactive Services Detection サービス” です。
緩和的とはいえ、サービスがデスクトップと対話できることに変わりはないため、やがてはこのサービスも削除される予定です。

- 参考情報
Title : Impact of Session 0 Isolation on Services and Drivers in Windows (English)
URL : https://msdn.microsoft.com/en-us/library/windows/hardware/dn653293(v=vs.85).aspx
概要 : この記事では、サービスがセッション 0 によって実行されることで、セキュリティのリスクが高まることについて言及しております。

Title : Interactive Services (English)
URL : https://msdn.microsoft.com/ja-jp/library/windows/desktop/ms683502(v=vs.85).aspx
概要 : この記事では、Interactive Services によって、サービスがユーザーと対話できることについてセキュリティのリスクが高まること、およびサービスがユーザーと対話できることを推奨していないことについて言及しております。

上記の実装変更によるこの現象を回避するには、提供されているアプリケーションの実装を変更する必要があります。
詳細は以下のアプローチをご参照ください。

[アプリケーション側からのアプローチ]
具体的には、2 つの方法が有効です。

1) あらかじめデスクトップ上に常駐プログラムをスタートアップとして登録をしておき、サービスからの要求が来た場合に、常駐アプリ側から CreateProcess() を呼び出し、アプリケーションを起動する方法です。
こちらの方法の利点ですが、プロセス生成部分が非常にシンプルな構成をすることができますので、保守性に優れた方法です。
また、サービスとクライアント間の通信にて名前付きパイプを利用したものになりますと、以下に公開されているサンプルがお役に立ちますので、ご評価をいただくことも容易です。

Title : Simple Service (English)
URL : https://github.com/Microsoft/Windows-classic-samples/tree/master/Samples/Win7Samples/winbase/service

2) サービスアプリケーションから、CreateProcessAsUser() の呼び出しを行い、デスクトップ上でプロセスを起動する方法です。
本実装についてのアウトラインにつきましては、以下のドキュメントに記載がある方法です。

Title : Windows Vista® および Windows Server® 2008 アプリケーション互換性解説書
URL : https://msdn.microsoft.com/ja-jp/library/aa480152.aspx

- 抜粋 -
Windows Vista® および Windows Server® 2008 に対応した解決策の活用
リモート プロシージャ コール (RPC) や名前付きパイプなどのクライアント メカニズムまたはサーバー メカニズムを使用して、サービスおよびアプリケーション間で通信を行います。
WTSSendMessage 関数を使用して、ユーザーのデスクトップに簡単なメッセージ ボックスを作成します。これにより、サービスはユーザーに通知を送信し、簡単な応答を要求できます。
複雑な UI の場合は、CreateProcessAsUser 関数を使用してユーザーのセッションでプロセスを作成します。
サービスで使用可能なイベントやマッピングされたメモリなどの名前付きオブジェクトには、明示的にLocal\ または Global\ のいずれかの名前空間を指定します。

Title : CreateProcessAsUser() windowstations and desktops (English)
URL : https://support.microsoft.com/ja-jp/help/165194/createprocessasuser-windowstations-and-desktops

Windows Platform 担当 : 栗山