2008-11-06 56 views
41

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

+0

你定位的是哪个版本的Windows?对于Vista和7,Windows服务不能拥有GUI组件。我的研究是从几年前,但与该服务在运行隐藏/禁用的管理员帐户(会话0)。当时我的解决方案是使用MSMQ服务和单独的GUI应用程序之间的通信。 – gooch 2010-11-17 21:09:03

回答

49

罗杰Lipscombe的答案,使用WTSEnumerateSessions找到合适的桌面,然后CreateProcessAsUser启动应用程序,桌面(你通过它的桌面的句柄作为STARTUPINFO结构的一部分)上是正确的。

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

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

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

而且,这个快捷键可以根据需要移动由管理员/禁用的,这将使您的应用程序部署要容易得多,因为它不会从其他Windows应用程序中使用的标准偏差...

+0

但它将不得不采取用户凭据,对吧? – Prakash 2012-09-29 13:52:49

6

WTSEnumerateSessions和CreateProcessAsUser。

0

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

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

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

0

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

但是,只有当您调整了服务权限时:您需要允许它为interact with the desktop

1

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

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

+0

你说的这个“这个”是什么?我在会话0是唯一的理由是,这是不使用的第一届会议时,我登录... – SamB 2010-11-28 23:18:36

5

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

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

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为每个管道指定一个唯一名称,从而区分多个用户进程。

相关问题