【问题标题】:How can a Windows service execute a GUI application?Windows 服务如何执行 GUI 应用程序?
【发布时间】:2023-03-15 10:39:01
【问题描述】:

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

【问题讨论】:

  • 您的目标是什么版本的 Windows?使用 Vista 和 7 windows 服务不能有 GUI 组件。我的研究是从几年前开始的,但它与运行服务的隐藏/禁用管理员帐户(会话 0)有关。我当时的解决方案是使用 MSMQ 在服务和单独的 GUI 应用程序之间进行通信。

标签: c++ winapi windows-services


【解决方案1】:

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

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

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

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

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

【讨论】:

    【解决方案2】:

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

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

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

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

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

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

    【讨论】:

      【解决方案3】:

      WTSEnumerateSessions 和 CreateProcessAsUser。

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          【解决方案5】:

          那个问题 Session 0 , Interactive Services , Windows 服务允许服务与桌面交互 在 Windows 7 或 Windows Vista 上

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

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

          【讨论】:

            【解决方案6】:

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

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

            【讨论】:

            • 你说的这个“the”是什么?我在会话 0 中的唯一原因是它是我登录时第一个未使用的会话...
            • 在 Win2K、XP 和 Win2K3 上,只有一个控制台会话,并且始终处于 Session 0 中。其他所有会话均由 TS 用户使用。
            【解决方案7】:

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

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

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

            【讨论】:

              【解决方案8】:

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

              但前提是你调整了服务权限:你需要允许interact with the desktop

              【讨论】:

                【解决方案9】:

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

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

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2010-09-08
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-06-12
                  相关资源
                  最近更新 更多