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

时间:2008-11-06 07:15:39

标签: c++ winapi windows-services

我编写了一个Windows服务,允许我远程运行和停止应用程序。这些应用程序使用CreateProcess运行,这对我有用,因为它们中的大多数只执行后端处理。最近,我需要运行将GUI呈现给当前登录用户的应用程序。如何在C ++中编码以允许我的服务找到当前活动的桌面并在其上运行GUI?

9 个答案:

答案 0 :(得分:52)

Roger Lipscombe的回答是,使用WTSEnumerateSessions找到合适的桌面,然后CreateProcessAsUser启动该桌面上的应用程序(将{{3}的一部分传递给桌面的句柄) }结构)是正确的。

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

但最重要的是,如果某个应用程序突然出现在用户的桌面上,这可能会在一个糟糕的时间发生(或者是因为用户根本没想到它,或者是因为您尝试启动应用程序时在关闭或其他任何事情的过程中,会话还没有完全初始化。

更传统的方法是在全局启动组中为您的服务添加一个小客户端应用程序的快捷方式。然后,此应用程序将与每个用户会话一起启动,并且可以在不使用任何用户凭据,会话和/或桌面的情况下启动其他应用程序(如果需要)。

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

答案 1 :(得分:16)

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

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

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

  • 使用WTSSendMessage函数在用户会话中显示一个对话框。

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

    如果此服务在多用户系统上运行,请将应用程序添加到以下密钥,以便在每个会话中运行:HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Run。如果应用程序使用IPC的命名管道,则服务器可以通过根据会话ID为每个管道提供唯一名称来区分多个用户进程。

答案 2 :(得分:6)

WTSEnumerateSessions和CreateProcessAsUser。

答案 3 :(得分:5)

有人建议使用WTSEnumerateSessions和CreateProcessAsUser。我想知道为什么没有人建议WTSGetActiveConsoleSessionId,因为你说你只想定位一个登录用户。

有些人确实建议使用CreateProcessAsUser。如果按照你所说的方式调用普通的旧CreateProcess,则应用程序的GUI将使用您的服务权限而不是用户的权限运行。

答案 4 :(得分:2)

问题第0节,互动服务, Windows服务允许服务与桌面交互 在Windows 7或Windows Vista上

您可以阅读这篇文章 http://www.codeproject.com/KB/vista-security/SubvertingVistaUAC.aspx

我尝试在这里解释它正在使用Windows 7

答案 5 :(得分:1)

在Win2K,XP和Win2K3上,控制台用户在会话0中登录,这是服务所在的同一会话。如果服务配置为交互式,则它将能够在用户桌面上显示UI。 / p>

然而,在Vista上,没有用户可以在会话0中登录。从服务显示UI有点棘手。您需要使用WTSEnumerateSessions API枚举活动会话,找到控制台会话并以该用户身份创建流程。当然,您还需要令牌或用户凭据才能执行此操作。您可以阅读有关此流程的更多详细信息here

答案 6 :(得分:0)

我认为只要您只有一个用户登录,它就会自动显示在该用户的桌面上。

无论如何,在服务启动exe时要非常小心。

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

答案 7 :(得分:0)

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

但是,只有在您调整了服务权限时:您需要将其设为interact with the desktop

答案 8 :(得分:0)

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

取自:http://msdn.microsoft.com/en-us/library/ms683502(VS.85).aspx