web-dev-qa-db-fra.com

Comment un service Windows peut-il exécuter une application graphique?

J'ai écrit un service Windows qui me permet d'exécuter et d'arrêter des applications à distance. Ces applications sont exécutées à l'aide de CreateProcess, et cela fonctionne pour moi car la plupart d'entre elles n'effectuent que le traitement du backend. Récemment, je dois exécuter des applications présentant une interface utilisateur graphique pour le journal actuel de l'utilisateur. Comment coder en C++ pour permettre à mon service de localiser le bureau actuellement actif et d'exécuter l'interface graphique sur celui-ci?

43
sep

La réponse de Roger Lipscombe, utiliser WTSEnumerateSessions pour trouver le bureau de droite, puis CreateProcessAsUser pour démarrer l'application sur ce bureau (vous lui transmettez le handle du bureau dans le cadre du STARTUPINFO structure) est correcte.

Cependant, je voudrais fortement recommande de ne pas le faire. Dans certains environnements, tels que les hôtes Terminal Server avec de nombreux utilisateurs actifs, il n'est pas facile de déterminer quel poste de travail est «actif», voire même impossible.

Mais surtout, si une application apparaît soudainement sur le bureau d'un utilisateur, cela peut très bien se produire à un mauvais moment (soit parce que l'utilisateur ne s'y attend tout simplement pas, soit parce que vous essayez de lancer l'application alors que la session n'est pas terminée. pas encore tout à fait initialisé, en train de fermer, ou autre chose).

Une approche plus classique consisterait à créer un raccourci vers une petite application client pour votre service dans le groupe de démarrage global. Cette application sera ensuite lancée avec chaque session d'utilisateur et pourra être utilisée pour démarrer d'autres applications (si vous le souhaitez) sans jongler avec les informations d'identification de l'utilisateur, les sessions et/ou les ordinateurs de bureau.

En outre, les administrateurs peuvent déplacer/désactiver ce raccourci à leur guise, ce qui facilitera grandement le déploiement de votre application, car il ne s'écarte pas des normes utilisées par d'autres applications Windows ...

52
mdb

La réponse courte est "Vous ne le faites pas", car ouvrir un programme graphique s'exécutant sous un autre contexte utilisateur est une vulnérabilité de sécurité communément appelée Shatter Attack .

Consultez cet article MSDN: Interactive Services . Il donne quelques options pour qu'un service interagisse avec un utilisateur.

En bref, vous avez ces options:

  • Affichez une boîte de dialogue dans la session de l'utilisateur à l'aide de la fonction WTSSendMessage.

  • Créez une application graphique masquée distincte et utilisez la fonction CreateProcessAsUser pour exécuter l'application dans le contexte de l'utilisateur interactif. Concevez l'application graphique pour communiquer avec le service via une méthode de communication interprocessus (IPC), par exemple, des canaux nommés. Le service communique avec l'application graphique pour lui indiquer quand afficher l'interface graphique. L'application communique les résultats de l'interaction utilisateur au service afin que celui-ci puisse prendre les mesures appropriées. Notez que IPC peut exposer vos interfaces de service sur le réseau, sauf si vous utilisez une liste de contrôle d'accès appropriée.

    Si ce service s'exécute sur un système multi-utilisateur, ajoutez l'application à la clé suivante afin qu'elle soit exécutée dans chaque session: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run. Si l'application utilise des canaux nommés pour IPC, le serveur peut distinguer plusieurs processus utilisateur en attribuant à chaque canal un nom unique en fonction de l'ID de session.

16
mlarsen

WTSEnumerateSessions et CreateProcessAsUser.

6
Roger Lipscombe

Plusieurs personnes ont suggéré WTSEnumerateSessions et CreateProcessAsUser. Je me demande pourquoi personne n'a suggéré WTSGetActiveConsoleSessionId, puisque vous avez indiqué que vous ne souhaitez cibler qu'un seul utilisateur connecté.

Plusieurs personnes ont cependant raison de suggérer CreateProcessAsUser. Si vous appelez tout simplement l'ancien CreateProcess comme vous l'avez dit, l'interface graphique de l'application s'exécutera avec les privilèges de votre service au lieu des privilèges de l'utilisateur.

5

Les problèmes de la session 0, Services interactifs, Service Windows autorisent le service à interagir avec le bureau Sur Windows 7 ou Windows Vista

Vous pouvez lire cet article http://www.codeproject.com/KB/Vista-security/SubvertingVistaUAC.aspx

J'essaie d'expliquer ici que cela fonctionne sur Windows 7

2
mtaskopru

Sous Win2K, XP et Win2K3, l'utilisateur de la console est connecté à la session 0, à la même session que les services. Si un service est configuré comme interactif, il pourra afficher l'interface utilisateur sur le bureau de l'utilisateur.

Toutefois, sous Vista, aucun utilisateur ne peut être connecté à la session 0. Afficher l'interface utilisateur à partir d'un service est un peu plus compliqué. Vous devez énumérer les sessions actives à l'aide de WTSEnumerateSessions API, rechercher la session de console et créer le processus sous le nom de cet utilisateur. Bien entendu, vous devez également disposer d'un jeton ou des informations d'identification de l'utilisateur pour pouvoir le faire. Vous pouvez lire plus de détails sur ce processus ici .

1
Franci Penov

Important Les services ne peuvent pas interagir directement avec un utilisateur à partir de Windows Vista. Par conséquent, les techniques mentionnées dans la section intitulée Utilisation d’un service interactif ne doivent pas être utilisées dans le nouveau code.

Cela provient de: http://msdn.Microsoft.com/en-us/library/ms683502(VS.85).aspx

0
Stéphane

Je pense que tant que vous n'avez qu'un seul utilisateur connecté, il s'affichera automatiquement sur le bureau de cet utilisateur. 

Quoi qu'il en soit, soyez très prudent quand un service démarre un exe. 

Si l'accès en écriture au dossier avec l'exe n'est pas restreint, tout utilisateur peut remplacer cet exe par n'importe quel autre programme, qui sera ensuite exécuté avec les droits système. Prenons par exemple cmd.exe (disponible sur tous les systèmes Windows). La prochaine fois que le service essaiera de démarrer votre exe, vous obtiendrez une commande Shell avec les droits du système ...

0
Treb

Si vous lancez une interface graphique à partir de votre service, celle-ci apparaîtra sur le bureau actuellement actif.

Mais uniquement si vous avez ajusté les autorisations de service: Vous devez l'autoriser à interagir avec le bureau .

0
mkoeller