53

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

4

9 回答 9

56

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

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

但最重要的是,如果一个应用程序突然出现在用户的桌面上,这很可能发生在一个糟糕的时间(可能是因为用户根本没想到它,或者因为您试图在会话结束时启动应用程序) '尚未完全初始化,在关闭过程中,或其他)。

更传统的方法是在全球启动组中为您的服务放置一个小型客户端应用程序的快捷方式。然后,此应用程序将与每个用户会话一起启动,并可用于启动其他应用程序(如果需要),而无需处理用户凭据、会话和/或桌面。

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

于 2008-11-06T07:36:45.213 回答
19

简短的回答是“你不需要”,因为打开在另一个用户上下文下运行的 GUI 程序是一个安全漏洞,通常称为Shatter Attack

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

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

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

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

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

于 2008-11-06T08:05:25.733 回答
6

WTSEnumerateSessions 和 CreateProcessAsUser。

于 2008-11-06T07:23:40.840 回答
6

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

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

于 2008-11-06T07:51:14.717 回答
2

问题 Session 0 , Interactive Services , Windows Service Allow Service To Interact With Desktop on Windows 7 or Windows Vista

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

我尝试在这里解释它在 Windows 7 上运行

于 2010-04-07T07:44:44.433 回答
1

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

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

于 2008-11-06T07:40:29.810 回答
0

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

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

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

于 2008-11-06T07:24:00.433 回答
0

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

但前提是您调整了服务权限:您需要允许它与桌面交互

于 2008-11-06T07:31:47.267 回答
0

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

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

于 2009-02-19T20:50:04.003 回答