¿Cómo puede un servicio de Windows ejecutar una aplicación GUI?

He escrito un servicio de Windows que me permite ejecutar y detener aplicaciones de forma remota. Estas aplicaciones se ejecutan usando CreateProcess, y esto funciona para mí porque la mayoría de ellas solo realiza el procesamiento de back-end. Recientemente, necesito ejecutar aplicaciones que presenten GUI al usuario de inicio de sesión actual. ¿Cómo codigo en C ++ para permitir que mi servicio ubique el escritorio actualmente activo y ejecute la GUI en él?

La respuesta de Roger Lipscombe, para usar WTSEnumerateSessions para encontrar el escritorio correcto, luego CreateProcessAsUser para iniciar la aplicación en ese escritorio (le pasa el control del escritorio como parte de la estructura STARTUPINFO ) es correcta.

Sin embargo, recomendaría encarecidamente no hacer esto. En algunos entornos, como los servidores de Terminal Server con muchos usuarios activos, determinar qué escritorio es el “activo” no es fácil, y puede que ni siquiera sea posible.

Pero lo más importante es que si una aplicación aparece repentinamente en el escritorio de un usuario, es posible que esto ocurra en un mal momento (ya sea porque el usuario simplemente no lo espera o porque está intentando iniciar la aplicación cuando la sesión no está disponible). todavía bastante inicializado, en proceso de cierre, o lo que sea).

Un enfoque más convencional sería poner un acceso directo a una pequeña aplicación cliente para su servicio en el grupo de arranque global. Esta aplicación se lanzará junto con cada sesión de usuario, y se puede utilizar para iniciar otras aplicaciones (si así lo desea) sin ningún tipo de malabares de credenciales de usuario, sesiones y / o escritorios.

Además, los administradores pueden mover / deshabilitar este atajo si lo desean, lo que facilitará la implementación de su aplicación, ya que no se desvía de los estándares utilizados por otras aplicaciones de Windows …

La respuesta breve es “No”, ya que la apertura de un progtwig de GUI que se ejecuta en otro contexto de usuario es una vulnerabilidad de seguridad comúnmente conocida como Ataque Shatter .

Eche un vistazo a este artículo de MSDN: Servicios interactivos . Ofrece algunas opciones para que un servicio interactúe con un usuario.

En resumen, tienes estas opciones:

  • Muestre un cuadro de diálogo en la sesión del usuario utilizando la función WTSSendMessage.

  • Cree una aplicación GUI oculta por separado y use la función CreateProcessAsUser para ejecutar la aplicación dentro del contexto del usuario interactivo. Diseñe la aplicación GUI para comunicarse con el servicio a través de algún método de comunicación entre procesos (IPC), por ejemplo, conductos con nombre. El servicio se comunica con la aplicación GUI para indicarle cuándo mostrar la GUI. La aplicación comunica los resultados de la interacción del usuario de vuelta al servicio para que el servicio pueda tomar la acción adecuada. Tenga en cuenta que IPC puede exponer sus interfaces de servicio a través de la red a menos que use una lista de control de acceso (ACL) apropiada.

    Si este servicio se ejecuta en un sistema multiusuario, agregue la aplicación a la siguiente clave para que se ejecute en cada sesión: HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Run. Si la aplicación utiliza canalizaciones con nombre para IPC, el servidor puede distinguir entre múltiples procesos de usuario al dar a cada canal un nombre único basado en la ID de la sesión.

WTSEnumerateSessions y CreateProcessAsUser.

Varias personas sugirieron WTSEnumerateSessions y CreateProcessAsUser. Me pregunto por qué nadie sugirió WTSGetActiveConsoleSessionId, ya que dijo que solo desea apuntar a un usuario que ha iniciado sesión.

Sin embargo, varias personas tienen razón al sugerir CreateProcessAsUser. Si llama al viejo y simple CreateProcess de la manera que dijo, entonces la GUI de la aplicación se ejecutará con los privilegios de su servicio en lugar de los privilegios del usuario.

Que los problemas de la sesión 0, los servicios interactivos, el servicio de Windows permiten que el servicio interactúe con el escritorio en Windows 7 o Windows Vista

Puedes leer este artículo http://www.codeproject.com/KB/vista-security/SubvertingVistaUAC.aspx

Intento explicar aquí está trabajando en Windows 7

En Win2K, XP y Win2K3, el usuario de la consola ha iniciado sesión en la Sesión 0, la misma sesión en la que viven los servicios. Si un servicio se configura como interactivo, podrá mostrar la interfaz de usuario en el escritorio del usuario.

Sin embargo, en Vista, ningún usuario puede iniciar sesión en la Sesión 0. Mostrar la IU de un servicio es un poco más complicado. Debe enumerar las sesiones activas mediante la API WTSEnumerateSessions , buscar la sesión de la consola y crear el proceso como ese usuario. Por supuesto, también necesita un token o credenciales de usuario para poder hacer eso. Puede leer más detalles sobre este proceso aquí .

Creo que siempre que solo haya un usuario conectado, se mostrará automáticamente en el escritorio de ese usuario.

De todos modos, tenga mucho cuidado cuando tenga un servicio para comenzar un exe.

Si el acceso de escritura a la carpeta con el exe no está restringido, cualquier usuario puede reemplazar ese exe con cualquier otro progtwig, que luego se ejecutará con derechos de sistema. Tomemos como ejemplo cmd.exe (disponible en todos los sistemas de Windows). La próxima vez que el servicio intente iniciar su exe, obtendrá un shell de comandos con derechos de sistema …

Si inicia una GUI desde su servicio, aparecerá en el escritorio actualmente activo.

Pero solo si ajustó los permisos de servicio: debe permitir que interactúe con el escritorio .

Los servicios importantes no pueden interactuar directamente con un usuario a partir de Windows Vista. Por lo tanto, las técnicas mencionadas en la sección titulada Uso de un servicio interactivo no se deben utilizar en el nuevo código.

Esto se toma de: http://msdn.microsoft.com/en-us/library/ms683502(VS.85).aspx