C++ Windows服务如何执行GUI应用程序?

C++ Windows服务如何执行GUI应用程序?,c++,winapi,windows-services,C++,Winapi,Windows Services,我编写了一个Windows服务,允许我远程运行和停止应用程序。这些应用程序是使用CreateProcess运行的,这对我来说很有用,因为它们大多数只执行后端处理。最近,我需要运行向当前登录用户提供GUI的应用程序。如何在C++中允许我的服务定位当前活动桌面并运行它上的GUI? < p> WTSENUMARATESESARDEST和CreateProcessAsUser。 < P>我认为只要你只有一个用户登录,它将自动显示在该用户的桌面上。p> 无论如何,让服务启动exe时要非常小心 如果使用ex

我编写了一个Windows服务,允许我远程运行和停止应用程序。这些应用程序是使用CreateProcess运行的,这对我来说很有用,因为它们大多数只执行后端处理。最近,我需要运行向当前登录用户提供GUI的应用程序。如何在C++中允许我的服务定位当前活动桌面并运行它上的GUI?

< p> WTSENUMARATESESARDEST和CreateProcessAsUser。

< P>我认为只要你只有一个用户登录,它将自动显示在该用户的桌面上。p> 无论如何,让服务启动exe时要非常小心


如果使用exe对文件夹的写入权限不受限制,则任何用户都可以使用任何其他程序替换该exe,然后该程序将以系统权限运行。以cmd.exe(可在所有windows系统上使用)为例。下次服务尝试启动exe时,您将获得一个具有系统权限的命令shell…

如果您从服务启动GUI,它将显示在当前活动桌面上


但只有在您调整了服务权限的情况下:您需要允许它。

Roger Lipscombe的回答是,使用找到正确的桌面,然后在该桌面上启动应用程序(您将桌面句柄作为结构的一部分传递给它)是正确的

然而,我强烈建议不要这样做。在某些环境中,例如具有许多活动用户的终端服务器主机,确定哪个桌面是“活动”桌面并不容易,甚至可能不可能

但最重要的是,如果一个应用程序突然出现在用户的桌面上,这很可能发生在一个不好的时间(要么是因为用户根本没有预料到它,要么是因为你试图在会话尚未完全初始化时启动应用程序,或者是在关闭过程中启动应用程序,等等)

一种更为传统的方法是在全球创业团队中为您的服务设置一个小型客户端应用程序的快捷方式。然后,该应用程序将随每个用户会话一起启动,并可用于启动其他应用程序(如果需要),而无需对用户凭据、会话和/或桌面进行任何改动


此外,管理员可以根据需要移动/禁用此快捷方式,这将使应用程序的部署更加容易,因为它不会偏离其他Windows应用程序使用的标准…

在Win2K、XP和Win2K3上,控制台用户登录到会话0,即服务所在的会话。如果服务配置为交互式,它将能够在用户桌面上显示UI


但是,在Vista上,任何用户都无法登录会话0。从服务中显示UI有点棘手。您需要使用API枚举活动会话,找到控制台会话并作为该用户创建进程。当然,您还需要一个令牌或用户凭据才能做到这一点。您可以阅读有关此过程的更多详细信息。

一些人建议使用WTSEnumerateSessions和CreateProcessAsUser。我想知道为什么没有人建议使用WTSGetActiveConsoleSessionId,因为您说过您只希望针对一个登录用户

不过,有几个人建议CreateProcessAsUser是正确的。如果您按照您所说的方式调用普通的旧CreateProcess,那么应用程序的GUI将以您的服务权限而不是用户权限运行。

简短的回答是“您没有”,因为打开在另一个用户上下文下运行的GUI程序是一个安全漏洞,通常称为安全漏洞

请看这篇MSDN文章:。它为服务提供了一些与用户交互的选项

简而言之,您有以下选项:

  • 使用WTSSendMessage功能在用户会话中显示对话框

  • 创建一个单独的隐藏GUI应用程序,并使用CreateProcessAsUser函数在交互用户的上下文中运行该应用程序。设计GUI应用程序以通过进程间通信(IPC)的某种方法(例如命名管道)与服务通信。该服务与GUI应用程序通信,告诉它何时显示GUI。应用程序将用户交互的结果传回服务,以便服务可以采取适当的操作。请注意,IPC可以通过网络公开您的服务接口,除非您使用适当的访问控制列表(ACL)

    如果此服务在多用户系统上运行,请将应用程序添加到以下密钥,以便在每个会话中运行:HKEY\U LOCAL\U MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\run。如果应用程序为IPC使用命名管道,服务器可以根据会话ID为每个管道指定唯一名称,从而区分多个用户进程


从Windows Vista开始,重要服务无法直接与用户交互。因此,标题为“使用交互式服务”的部分中提到的技术不应在新代码中使用


这取自:

问题会话0,交互式服务, Windows服务允许服务与桌面交互 在Windows 7或Windows Vista上

你可以读这篇文章


我试着在这里解释它在Windows 7上工作

您的目标是什么版本的Windows?使用Vista和7 windows服务时,无法使用GUI组件。我的研究是几年前的,但它与运行服务的隐藏/禁用管理员帐户(会话0)有关。我当时的解决方案是使用MSMQ在服务和一个单独的GUI应用程序之间进行通信?我在会话0中的唯一原因是,这是我登录时第一个未使用的会话…在Win2K、XP和Win2K3上,只有一个控制台会话,并且始终在会话0中。TS用户使用所有其他会话。