4

を使用してWindowsサービス内からプロセスを実行しています

ProcessStartInfo processStartInfo = new ....
Process.Start(processStartInfo);

問題は、ローカル システム アカウントでサービスを実行すると問題なく実行されるのに、プログラムのウィンドウが表示されないことです。ユーザー資格情報をサービス プロパティに入力しようとしましたが、[デスクトップとの対話をサービスに許可する] チェックボックスが無効になります。

サービスから呼び出してアプリを実行する必要があり、アプリのウィンドウを表示する必要があります。

お願い助けて。

アップデート。ユーザー名、パスワード、ドメインを取得する Process.Start の過負荷バージョンを使用すると、プログラムがデスクトップにプルされます。しかし、今では 1 つの資格情報でアプリを起動しますが、別のユーザーのデスクトップでそれを示しています。どうして?

UPD2: アイデアがあります。Sysinternals Suite の psexec.exe を使用できます。しかし、問題は、「管理者として」静かに開始する必要があることです。そして、私は方法がわかりません。つまり、既に管理者権限を持っている場合でも、手動で「管理者として実行」と言って、UAC を確認してから準備が整う場合があります。UACを使わずに何かを静かに実行する方法がわかりません....

UPD3: 親愛なる主よ。私はそのことを持っている !ついに。

Ok。当初、問題は実際にセッション 0 の分離にありました。そのため、サービスから開始できる中間アプリを構築する必要がありました。次に、そのアプリが RPC を介してアプリケーションを開始し、デスクトップに表示することを想定しています。中間層アプリを構築する代わりに、psexec ツールを使用することにしました (とにかく、RPC を介して、必要なとおりに動作します)。そして、そのツールを LOCAL SYSTEM アカウントで使用しようとすると、何らかの理由で機能しませんでした。そして、私は気づきました-その理由は、MSがすべてのpstoolに入れているEULAポップアップダイアログであり、ボタンをクリックしてダイアログをローカルシステムアカウントで確認することは不可能でした. したがって、解決策は、レジストリ HKU.DEFAULT\Software\Sysinternals\PsExec に DWORD 値 EulaAccepted = 1 でキーを作成することです。

万歳、今それは動作します! しかし!次に、現在ログインしているユーザーの画面にプログラムを表示する必要があります。そのためには、セッション ID が必要です。

問題は、現在ログインしているユーザーのセッション ID を取得する方法です。まだ誰もログインしていない場合はどうなりますか? それはどのようなセッション ID でしょうか?

UPD4: それだけです! 私はそれを手に入れました!

[DllImport("Kernel32.dll", EntryPoint = "WTSGetActiveConsoleSessionId")] public static extern int WTSGetActiveConsoleSessionId();

君たちありがとう!

4

4 に答える 4

4

WTSGetActiveConsoleSessionId(ターミナルサービスAPIから)を使用して、アクティブなコンソールセッションIDを取得できます。WinXP / Win2K3以降でのみ使用できますが、Win2K以前のセッションIDに0をハードコーディングできるため、問題ありません。PInvokeの署名は次のとおりです。

[DllImport("Kernel32.dll", SetLastError = true)]
[return:MarshalAs(UnmanagedType.U4)]
public static extern int WTSGetActiveConsoleSessionId ( );

ユーザーのセッションでプロセスを起動する限り、ここで私が与えた答えを参照できます。基本的に、4つのAPIを呼び出す必要があります。WTSGEtConsoleSessionId、WTSQueryUserToken、DuplicateTokenEx、次にCreateProcessAsUserであり、WinXP/Win2K3以降を実行しているすべてのマシンで機能します。

于 2010-09-04T05:58:52.500 に答える
3

1 つの解決策は、3 番目のプロセスを仲介として機能させ、RPC/名前付きパイプを介してアプリを起動するように指示することです。

プロセス:

  • Windows サービス
  • 仲介申請
  • 実行したいアプリ

shim は、通信エンドポイント (名前付きパイプ、WCF エンドポイント) を作成し、それをリッスンします。先に進むようにというメッセージを受け取ると、実行したいアプリを起動します。

次に、Windows サービスがアプリを起動する必要がある場合、エンドポイント (名前付きパイプ、WCF エンドポイント) を見つけて開き、メッセージを送信してアプリを起動します。次に、中間アプリケーションがビジネスを開始するプロセスを処理し、Windows サービスにあるような制限はありません。

この中間プロセスをログオンで開始すると、準備完了です。

これは、デスクトップと対話するテストを実行する必要がある場合の Microsoft テスト エージェント/コントローラーの動作に似ています。

于 2010-07-07T17:35:51.873 に答える
2

これは中間プロセスなしで実行できますが、500 行以上のコードが必要です。基本的に、現在ログオンしているユーザーとして 2 番目のプロセスを起動します。Vista/7 の場合、このユーザーは独自の winlogon プロセスを持ち、XP の場合はエクスプローラー プロセスを持ちます。実行中のプロセスのプライマリ トークン、環境ブロック、セキュリティ属性、およびスレッド セキュリティ属性を取得し、そのすべての情報を使用して Windows API 関数 CreateProcessAsUser を呼び出し、正しいウィンドウ ステーション (通常は「WinSta0\Default」) も選択する必要があります。 」)。これはすべて実行可能ですが、2 番目のプロセスと IPC の別の提案でより良い時間を過ごすことができます.

于 2010-07-07T18:06:05.213 に答える
1

WindowsXP よりも新しいものでこれを試している場合、これは機能しません。これは、セッション 0 分離と呼ばれる Vista / Windows 7 で導入された新機能によるものです。http://msdn.microsoft.com/en-us/library/bb756986.aspxサービスによって起動されたアプリをユーザーのデスクトップに表示することはできません。

于 2010-07-07T17:17:24.250 に答える