質問

小さなサービス (プレーン Win32) を作成しましたが、複数のユーザーがログオンしているときにそのサービスの複数のインスタンスを実行できるかどうかを知りたいです。

基本的に、UserA と UserB があるとします。UserA のサービスは「domain\UserA」としてログオンし、UserB のサービスは「domain\UserB」としてログオンします。もちろん、これは同じ実行可能ファイルからのものです。ChangeServiceConfig() 関数を使用してログオンを動的に変更できますが、システム全体で変更されるようですが、各ユーザーが自分専用のサービスの独自のコピーを実行できるようにしたいと考えています。

ご指摘がございましたらよろしくお願いいたします。

役に立ちましたか?

解決

Win32 サービスはシステム全体に適用されるように設計されており、ユーザーがログインする前に実行を開始します。ユーザーごとに何かを実行したい場合は、通常のアプリケーションとして設計し、ユーザーのスタートアップ グループから実行する方がよいでしょう。

他のヒント

おそらくサービスに子プロセスを作成させ、その子プロセスがユーザーの資格情報を採用する (またはその資格情報を使用して開始する) ことは可能でしょうか?この方法では、サービスのインスタンスは 1 つに制限されますが、ユーザーごとのジョブはすべて同じように実行できます。Windows タスク スケジューラ サービスである IIRC がこれを行います。

サービスの全体的な概念は、ユーザーがログオンする前にサービスが開始されるということです。したがって、これが可能だったとしても、サービスの開始時に userA と userB のどちらもまだログオンしていないため、どちらかを選択することはできません。


考えられる方向としては、サービスを SYSTEM として実行し、ログインしているユーザーがいるかどうかを数分ごとに確認し、そのユーザーになりすましてこの処理を実行するというものです。

はい、それは近いように思えます (私はグレッグからのコメントに答えていますが、コメントが短すぎて私の返信に収まりません)。

ユーザーのリストは事前にわかりませんが、各ユーザーのユーザー名とパスワードのペアを入力するために使用される GUI 制御アプリケーションがあります。したがって、userA はログオンしてアプリケーションを実行し、資格情報を入力すると、サービスはそれを使用します。同時に (userA がログオフした後でも、サービスは userA の資格情報で実行中です) userB がログオンしてアプリを使用し、サービスの別のコピーが userB にログオンした状態で実行を開始します。したがって、userA サービスと userB サービスが同時に実行されます。

それは可能ですか?

おそらくユーザーになりすまそうとしているのでしょう。ここで簡単な Google 検索で見つけた参考文献をいくつか確認してください。

タイミングとアイデンティティに関して、実際には 2 つの異なる矛盾する要件があるように思えます。

  1. ログインしている各ユーザーとして実行
  2. ユーザーがログインしていなくても自動的に実行されます。

これを簡単に行う方法はありません。代わりに、プログラムをサービスにラップすることを検討してください。プログラムは各ユーザーの起動時に (起動フォルダーまたはタスクスケジューラー経由で) 通常どおり実行されます。 加えて アプリをシステム ユーザー (または定義した他のユーザー) として実行するサービスを作成します。
エンドユーザーがログアウトした後もアプリを実行し続ける必要があるため (コメントでこれについて言及しています)、サービスにこのプロセスを管理させることができます。

ただし、ユーザーは依然として実質的にログインしているため、これは最良のアイデアではない可能性があります。これにより、セキュリティ、パフォーマンス (一度にログインするユーザーが多すぎるなど) など、多くの副作用が生じる可能性があります。

サービス アプリケーションと非サービス (通常) アプリケーションを作成し、それらを IPC (マップされたファイル、パイプ、MailSolts など) 経由で通信させることができます。あなたがそれを名付けます)。

そうすればすべての問題は解決します。

注記:同じアプリケーションでも、プロセスとして開始した場合とユーザーによって開始された場合では動作が異なることがありますが、最終的には同じことです。アプリケーションが 2 つあることに変わりはありません (実行可能ファイルが 1 つしかない場合でも)。

異なるアカウントでの実行も可能です。実際、これはよくあることです。一連の OS サービスを実装する svchost.exe を参照してください。

どのアカウントをどのように判断するのか理解できません。大企業では、100,000 人以上の従業員全員が使用できるように多数の PC がセットアップされています。ログインしたユーザーとしてサービスを実行したくはありませんし、100,000 ユーザー全員に対してサービスを実行することもできません。それでは、どのアカウントについて尋ねなければなりませんか?

Windows プロセスは、一度に 1 人のユーザーの権限でのみ実行できます。これはサービスやその他のプロセスに当てはまります。十分な権限があれば、偽装を使用して異なるユーザー間を「切り替える」ことが可能です。あなたが行おうとしている最も一般的なパターンは、ログイン/ログアウトイベントを登録し、それに応じて子プロセスを作成する特権サービスのインスタンスを 1 つ用意し、それぞれがログインしているユーザーになりすますことです。このパターンでは、各プロセスが通常のアプリケーションであるかのように各ユーザーのデスクトップで実行されるため、UI も簡素化されます。

特権サービスのコードをできるだけ単純にしておくと、このパターンには、コードの攻撃対象領域が最小限に抑えられるという追加の利点もあります。ユーザーがサービスの「ユーザーとして実行」側でセキュリティ上の問題を発見した場合、それは問題ではありませんが、特権サービスのセキュリティ上の問題は特権昇格につながる可能性があります。実際、Vista より前の Windows メッセージ処理ループを実装する特権サービスは、次のような種類の攻撃に対して脆弱でした。 シャッター攻撃, 、やろうとしていることを考えると、これに注意する必要があります。

これを常に実行したいので、サービスが必要です。

各ユーザーを追跡するものが必要なので、ユーザー セッションで実行され、(名前付きパイプや DCOM などの要件に合ったものを使用して) サービスと通信するアプリケーションが必要です。

サービスの複数のインスタンスは必要ありません。問題の説明からすると、必要なのは、ユーザーになりすましてユーザーに代わってジョブを実行できる 1 つのサービスであるようです。

これを行うには、サービスでホストされる COM オブジェクトを実装します。クライアント アプリケーション (エンド ユーザーが実行する) は、CLSID で CoCreateInstanceEx を呼び出します。これにより、サービス内に COM オブジェクトの新しいインスタンスが作成されます。その後、アプリケーションはインターフェイスの 1 つでメソッドを使用して、収集したユーザー資格情報を COM オブジェクトに渡すことができます (ただし、資格情報の収集には慎重になり、代わりにユーザー トークンを渡すことができるかどうかを確認することになります)。サービスのコンテキストで実行されている COM オブジェクトは、LogonUser() を呼び出してユーザーをログオンし、ユーザーになりすますことができるため、ユーザーに代わってあらゆる操作を行うことができます (ユーザーのローカル appdata フォルダーの検索など :-))。他の回答には、資格情報またはトークンを使用してユーザーになりすますことへの良いリンクがあります。

COM に慣れている場合は、オブジェクトの実行が COM によってシリアル化されないように、オブジェクトをマルチスレッド (MTA 内に存在する) として作成することをお勧めします。そうでない場合は、デフォルトのシングル スレッド モデルで十分です。

Visual Studio ATL ウィザードは、サービス内に存在する COM オブジェクトのスケルトンを生成できます。ATL を使用した Windows サービスの実装については、ここで読むこともできます。 http://msdn.microsoft.com/en-us/library/74y2334x(VS.80).aspx

COM についてまったく知らない場合は、他の通信チャネルを使用して資格情報をサービスに渡すことができます。

いずれの場合も、サービスが資格情報を取得したら、ユーザーとして実行中のアプリケーションをブロックしないように、ユーザーに代わってすべての作業をバックグラウンド スレッドで実行する必要があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top