web-dev-qa-db-ja.com

WindowsサービスはGUIアプリケーションをどのように実行できますか?

アプリケーションをリモートで実行および停止できるWindowsサービスを作成しました。これらのアプリケーションはCreateProcessを使用して実行されますが、ほとんどのアプリケーションはバックエンド処理のみを実行するため、これは機能します。最近、GUIを現在のログインユーザーに提示するアプリケーションを実行する必要があります。サービスが現在アクティブなデスクトップを見つけてその上でGUIを実行できるようにするには、C++でコーディングする方法を教えてください。

43
sep

Roger Lipscombeの答え、 WTSEnumerateSessions を使用して適切なデスクトップを見つけ、次に CreateProcessAsUser を使用してそのデスクトップでアプリケーションを起動します(デスクトップのハンドルを一部として渡します- [〜#〜] startupinfo [〜#〜] structure)は正しいです。

しかし、私は 強く これをしないことをお勧めします。多くのアクティブユーザーがいるターミナルサーバーホストなどの一部の環境では、どのデスクトップが「アクティブな」デスクトップであるかを判断するのは簡単ではなく、不可能な場合もあります。

しかし、最も重要なことは、アプリケーションが突然ユーザーのデスクトップに表示される場合、これは非常に悪いタイミングで発生する可能性があります(ユーザーが単にそれを期待していないか、セッションが開始されていないときにアプリを起動しようとしているため)まだ完全に初期化されていない、シャットダウンのプロセスなど)。

より一般的なアプローチは、グローバルスタートアップグループにサービスの小さなクライアントアプリへのショートカットを配置することです。その後、このアプリはすべてのユーザーセッションと共に起動し、ユーザーの資格情報、セッション、デスクトップをジャグリングすることなく、他のアプリを(必要に応じて)起動して使用できます。

また、管理者はこのショートカットを必要に応じて移動/無効にすることができます。これにより、他のWindowsアプリで使用される標準から逸脱しないため、アプリケーションの展開がはるかに容易になります。

52
mdb

別のユーザーコンテキストで実行されているGUIプログラムを開くことは、一般的に Shatter Attack として知られるセキュリティ脆弱性であるため、短い答えは「あなたはしません」です。

次のMSDN記事をご覧ください: Interactive Services 。サービスがユーザーと対話するためのオプションを提供します。

要するに、次のオプションがあります。

  • WTSSendMessage関数を使用して、ユーザーのセッションにダイアログボックスを表示します。

  • 個別の非表示GUIアプリケーションを作成し、CreateProcessAsUser関数を使用して、対話ユーザーのコンテキスト内でアプリケーションを実行します。名前付きパイプなど、プロセス間通信(IPC)の何らかの方法を介してサービスと通信するようにGUIアプリケーションを設計します。サービスはGUIアプリケーションと通信して、GUIをいつ表示するかを通知します。アプリケーションは、ユーザーインタラクションの結果をサービスに返し、サービスが適切なアクションを実行できるようにします。 IPCは、適切なアクセス制御リスト(ACL)を使用しない限り、ネットワーク経由でサービスインターフェイスを公開できます。

    このサービスをマルチユーザーシステムで実行する場合は、アプリケーションを次のキーに追加して、各セッションで実行されるようにします:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run。アプリケーションがIPCに名前付きパイプを使用する場合、サーバーは各パイプにセッションIDに基づいた一意の名前を付けることで、複数のユーザープロセスを区別できます。

16
mlarsen

WTSEnumerateSessionsおよびCreateProcessAsUser。

6
Roger Lipscombe

数人がWTSEnumerateSessionsとCreateProcessAsUserを提案しました。ログインしている1人のユーザーのみをターゲットにしたいので、WTSGetActiveConsoleSessionIdを提案する人がいないのはなぜでしょうか。

ただし、CreateProcessAsUserを提案するのは正しい人もいます。あなたが言った方法で普通の古いCreateProcessを呼び出すと、アプリケーションのGUIはユーザーの特権の代わりにサービスの特権で実行されます。

5

セッション0、インタラクティブサービス、WindowsサービスがWindows 7またはWindows Vistaのデスクトップとの対話をサービスに許可するという問題

この記事を読むことができます http://www.codeproject.com/KB/Vista-security/SubvertingVistaUAC.aspx

私はここでそれがWindows 7で動作していると説明してみてください

2
mtaskopru

Win2Kでは、XPおよびWin2K3は、コンソールユーザーがセッション0でログオンします。これは、サービスが存在するセッションです。サービスが対話型として構成されている場合、UIを表示できますユーザーのデスクトップ上。

ただし、Vistaでは、セッション0でログオンできるユーザーはいません。サービスのUIを表示するには少し注意が必要です。 WTSEnumerateSessions APIを使用してアクティブなセッションを列挙し、コンソールセッションを見つけて、そのユーザーとしてプロセスを作成する必要があります。もちろん、それを行うにはトークンまたはユーザー資格情報も必要です。このプロセスの詳細については、こちらをご覧ください こちら

1
Franci Penov

重要なサービスは、Windows Vista以降、ユーザーと直接対話できません。したがって、「対話型サービスの使用」というタイトルのセクションで説明した手法は、新しいコードでは使用しないでください。

これは、 http://msdn.Microsoft.com/en-us/library/ms683502(VS.85).aspx から取得されます

0
Stéphane

ログインしているユーザーが1人だけである限り、そのユーザーのデスクトップに自動的に表示されます。

とにかく、サービスでexeを起動するときは非常に注意してください。

Exeを含むフォルダーへの書き込みアクセスが制限されていない場合、ユーザーはそのexeを他のプログラムに置き換えることができ、システムはシステム権限で実行されます。たとえば、cmd.exe(すべてのWindowsシステムで利用可能)を取り上げます。次回サービスがexeを起動しようとすると、システム権限を持つコマンドシェルが取得されます...

0
Treb

サービスからGUIを起動すると、現在アクティブなデスクトップに表示されます。

ただし、サービスのアクセス許可を調整した場合のみ: デスクトップと対話する を許可する必要があります。

0
mkoeller