Question

J'ai écrit un petit service (Win32 complet) et j'aimerais savoir s'il est possible d'en exécuter plusieurs instances lorsque plusieurs utilisateurs sont connectés.

En gros, supposons que nous ayons UserA et UserB pour UserA, le service se connecterait en tant que " domain \ UserA " et pour UserB, le service se connecterait en tant que " domain \ UserB " - Ceci est du même exécutable bien sûr. Je peux modifier l’ouverture de session de manière dynamique à l’aide de la fonction ChangeServiceConfig (), mais cela semble le changer à l’échelle du système, alors que je voudrais que chaque utilisateur ait sa propre copie du service ne fonctionnant que pour lui.

Merci d'avance pour tous les pointeurs.

Était-ce utile?

La solution

Les services Win32 sont conçus pour s’appliquer à l’ensemble du système et commencent à s'exécuter avant que tout utilisateur soit connecté. Si vous souhaitez que quelque chose s'exécute utilisateur par utilisateur, il est probablement préférable de le concevoir comme une application normale et de l'exécuter à partir de Le groupe de démarrage de l'utilisateur.

Autres conseils

Est-il possible que le service crée des processus enfants qui adoptent ensuite les informations d'identification de l'utilisateur (ou commencent avec eux)? De cette façon, vous êtes toujours limité à une seule instance du service, mais il est capable de faire ses tâches par utilisateur tout de même. Le service Planificateur de tâches de Windows exécute les opérations IIRC.

Tout le concept d’un service est qu’il est démarré avant même que tout utilisateur soit connecté. Ainsi, même si cela était possible, vous ne seriez pas en mesure de choisir entre utilisateurA et utilisateurB lorsque le service démarrera car aucun d’entre eux n’est encore connecté.

Une direction possible serait que le service s'exécute en tant que SYSTÈME. Toutes les quelques minutes, vérifiez si un utilisateur est connecté, s'il usurpe l'identité de cet utilisateur et procédez ainsi.

Oui, cela semble proche (je réponds au commentaire de Greg, mais les commentaires sont trop courts pour correspondre à ma réponse).

Je ne connais pas la liste des utilisateurs au préalable, mais il existe une application de contrôle de l'interface graphique qui serait utilisée pour entrer des paires nom d'utilisateur / mot de passe pour chaque utilisateur. Ainsi, l'utilisateur A se connecterait, lancerait l'application, entrerait ses informations d'identification et le service s'en servirait. En même temps (après que l'utilisateurA s'est déconnecté, mais que le service fonctionne toujours avec les informations d'identification de l'utilisateurA), l'utilisateurB se connecte, utilise l'application et une autre copie du service commence à s'exécuter en tant que utilisateur connecté. Ainsi, les services utilisateurA et utilisateurB sont en même temps actifs.

Est-ce possible?

Vous cherchez probablement à emprunter l'identité des utilisateurs. Découvrez quelques références trouvées lors d’une recherche rapide sur Google ici:

On dirait que vous avez en réalité deux exigences différentes et conflictuelles en ce qui concerne le timing et l'identité.

  1. Exécuter sous chaque utilisateur connecté
  2. Exécuter automatiquement même si aucun utilisateur n'est connecté.

Pas moyen de faire cela trivialement, envisagez plutôt d’envelopper votre programme dans un service; le programme s'exécutera normalement au démarrage de chaque utilisateur (par le biais du dossier de démarrage ou du planificateur de tâches) et en outre créera un service pour exécuter votre application en tant qu'utilisateur système (ou tout autre utilisateur que vous définissez).
Étant donné que vous avez également besoin (vous le mentionnez dans les commentaires) de l'application pour continuer à fonctionner en tant qu'utilisateur final même après sa déconnexion, vous pouvez demander au service de gérer ce processus pour vous.

TOUTEFOIS, cela pourrait ne pas être la meilleure idée, car l'utilisateur est toujours connecté. Cela peut avoir de nombreux effets secondaires, y compris la sécurité, les performances (trop d'utilisateurs connectés en même temps, etc.), etc.

Vous pouvez créer une application de service et une application non-service (normale) et les faire communiquer via IPC (fichier mappé, Pipes, MailSolts, etc.).

De cette manière, vous résolvez tous les problèmes.

REMARQUE: la même application peut se comporter différemment - lors du démarrage en tant que processus et par un utilisateur, mais au final, c'est la même chose, vous avez toujours 2 applications (que vous disposiez d'un seul exécutable).

Courir avec différents comptes est possible. En fait, c'est courant. Voir svchost.exe, qui implémente un ensemble de services de système d’exploitation.

Je ne comprends pas comment vous déterminez quels comptes. Dans une grande entreprise, de nombreux ordinateurs sont configurés pour que plus de 100 000 employés puissent l’utiliser. Vous ne voulez pas exécuter votre service en tant qu'utilisateur connecté, ni pour les 100 000 utilisateurs. Alors pour quels comptes, je dois demander?

Un processus Windows ne peut s'exécuter qu'avec les privilèges d'un seul utilisateur à la fois. Cela s'applique aux services et autres processus. Avec suffisamment de privilèges, il est possible de "changer" de entre différents utilisateurs en utilisant l'emprunt d'identité. Le modèle le plus courant pour ce que vous essayez de faire consiste à avoir une instance d'un service privilégié qui s'enregistre pour connecter / déconnecter des événements et créer des processus enfants en conséquence, chacun d'entre eux empruntant l'identité de l'utilisateur connecté. Le modèle simplifiera également l'interface utilisateur puisque chaque processus s'exécutera sur le bureau de chaque utilisateur, comme s'il s'agissait d'une application normale.

Si vous conservez le code du service privilégié aussi simple que possible, ce modèle présente l'avantage supplémentaire de minimiser la surface d'attaque de votre code. Si un utilisateur détecte un problème de sécurité dans le dossier "s'exécutant en tant qu'utilisateur" Du côté de votre service, il n’ya pas de problème, alors que des problèmes de sécurité dans les services privilégiés peuvent conduire à une élévation des privilèges. En fait, avant Vista, les services privilégiés mettant en œuvre une boucle de traitement de messages Windows étaient vulnérables à un type d'attaque appelé Attaques par bris , dont vous devez être conscient étant donné ce que vous essayez de faire.

Vous voulez que cela fonctionne tout le temps, donc vous voulez un service.

Vous voulez que quelque chose soit suivi pour chaque utilisateur, vous voulez donc une application qui s'exécute dans la session utilisateur et communique avec le service (en utilisant des canaux nommés, DCOM ou tout ce qui vous convient le mieux).

Vous n'avez pas besoin de plusieurs instances de votre service. D'après la description de votre problème, vous avez besoin d'un service capable d'emprunter l'identité des utilisateurs et d'exécuter des tâches en leur nom.

Vous pouvez le faire en implémentant un objet COM hébergé dans un service. Votre application cliente (que l'utilisateur final exécute) appellera CoCreateInstanceEx sur votre CLSID. Cela entraînerait la création d'une nouvelle instance de votre objet COM dans votre service. Ensuite, l'application peut utiliser une méthode sur l'une de vos interfaces pour transmettre les informations d'identification utilisateur collectées à l'objet COM (même si je serais prudent de collecter les informations d'identification et de voir si je peux transmettre le jeton d'utilisateur à la place). L'objet COM qui s'exécute dans le contexte du service peut ensuite appeler LogonUser () pour se connecter à l'utilisateur et l'emprunter l'identité de celui-ci, afin qu'il puisse faire tout ce qui le concerne (par exemple, trouver le dossier appdata local de l'utilisateur :-)). D'autres réponses proposent de bons liens pour emprunter l'identité d'utilisateurs à l'aide d'informations d'identification ou de jetons.

Si vous vous sentez à l'aise avec COM, je vous conseillerais de créer vos objets en multithread (résidant dans le MTA), afin que leur exécution ne soit pas sérialisée par COM. Sinon, le modèle à un seul thread par défaut vous suffira.

L’assistant Visual Studio ATL peut générer le squelette d’un objet COM résidant dans un service. Vous pouvez également en savoir plus sur l'implémentation du service Windows avec ATL ici: http : //msdn.microsoft.com/en-us/library/74y2334x (VS.80) .aspx

Si vous ne connaissez pas du tout COM, vous pouvez utiliser d'autres canaux de communication pour transmettre les informations d'identification à votre service.

Dans tous les cas, une fois que votre service aura obtenu les informations d'identification, tout le travail effectué pour le compte de l'utilisateur devra être exécuté sur un thread d'arrière-plan, afin de ne pas bloquer l'application en cours d'exécution en tant qu'utilisateur.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top