【问题标题】:Are Windows-GUI calls (creating visible windows, etc.) allowed in a Windows-Service?Windows 服务中是否允许 Windows-GUI 调用(创建可见窗口等)?
【发布时间】:2013-06-26 05:46:01
【问题描述】:

首先,我知道some proper ways 可以制作真正交互式的 Windows 服务。

情况是,我确实有一个与用户交互的工具。但是,它确实会通过弹出窗口和 Windows 通知区域(又名系统托盘)显示 非阻塞通知。它还会写入它显示的通知的日志文件。

此工具通常由主用户应用程序生成,只要主应用程序是普通应用程序,这些通知就会按预期工作。

当此工具由 Windows 服务生成时,自然不会显示任何通知。 (服务的桌面会话不可见。)但这没关系,我们有日志文件,这些通知只是 - 通知,用户在任何情况下都绝对必须看到。

现在的问题变成了:进程是否在服务的上下文中运行(服务本身或它启动的任何进程)“允许”进行显示可见的 Windows API 调用图形用户界面?

  • 大多数 Windows API 调用(例如,创建和显示窗口、使用 Shell_NotifyIcon 等)在服务的不可见会话中的行为是否相同?
  • 或者我是否必须确保在整个源代码中,在服务上下文中没有调用 GUI 显示/修改内容?

是的,调用::MessageBox 是个坏主意,因为它会阻塞。但我可以处理这些电话。

是的,这可以设计得更好,但这是我目前所拥有的,如果我不必将整个工具拆开以确保服务中没有运行与 GUI 相关的代码,那就太好了。

【问题讨论】:

  • 唯一的方法似乎是使用 WTSEnumerateSessions 和 CreateProcessAsUser——见SO article
  • @EdwardClements:感谢您的链接。但是请注意,在服务上下文中运行时,我确实不需要 需要显示 GUI 元素。我只是想知道 trying 显示非阻塞 GUI 元素是否会导致服务出现问题。
  • 对不起,我的错误——我认为任何 GDI 调用都不会失败(我有一个旧服务,它在对话框窗口中显示进度消息,它仍然在 Win7/WinServer2008R2 上运行而没有错误,当然不显示任何东西)

标签: windows winapi user-interface windows-services notification-area


【解决方案1】:

来自 Windows 服务的 GUI 元素显示在会话 0 上。在 Windows XP 和 2003 上,用户可以登录会话 0 并与服务创建的窗口正常交互,但微软在isolating Session 0 在 Vista(及更高版本)中的交互式服务。

所以,回答您的具体问题:

是在服务的上下文中运行的进程(服务本身 或它启动的任何进程)“允许”进行 Windows API 调用 显示一个可见的 GUI? 大多数 Windows API 调用(例如创建和显示窗口、使用 Shell_NotifyIcon 等)在不可见会话中的行为是否相同 服务?

是的,GUI 调用是允许的,并且应该正常成功。我知道的唯一值得注意的例外是与托盘图标相关的例外,因为提供任务栏 (explorer.exe) 的进程没有在隔离的 Session 0 中运行。

或者我是否必须确保在整个源代码中,在服务上下文中没有调用 GUI 显示/修改内容?

这不是必需的,尽管您应该proceed cautiously with any GUI interaction from your service。彻底测试!

【讨论】:

  • 您应该避免在服务中呈现 UI,因为您可能会触发 UI 检测服务,这会将用户暂时切换到您的服务 UI。
  • @RaymondChen:请在另一个答案中查看我对 UI0Detect 的分析:stackoverflow.com/a/17400251/321013——我说的对吗?
【解决方案2】:

我想提供一些信息。 Raymonds Chen's comment to the other answer

您应该避免在服务中呈现 UI,因为您可能会触发 UI 检测服务,它将用户切换到您的服务 UI 暂时地。 – 雷蒙德陈

我发现了这些好文章:

在哪里可以找到关于 UI 检测服务 (UI0Detect) 是什么、做什么以及它应该如何工作的解释。

交互式服务检测(任务栏上的闪烁按钮)是 检测服务是否存在的遗留应用程序的缓解措施 试图与桌面交互。这是由 交互式服务检测 (UI0Detect) 服务。

但是,必须注意,这只有在尝试查看 GUI 的服务设置了“允许服务与桌面交互”标志时才有效,因为只有这样服务进​​程才会在WinSta0of Session0 上运行,甚至允许它显示任何内容。

Alex Ionescu mentions这个:

如果 UI0Detect.exe ... SCM 已应 Window Hook DLL 的请求启动它。这 服务将继续... 服务首先做一些 验证以确保它在正确的WinSta0\Default 上运行 windowsstation 和 desktop 然后通知 SCM 成功或 失败。

所以,回到 Raymond 的评论:据我所知,只要服务没有勾选 type= interact 选项 (see sc.exe),并且通常你不勾选这个,UI0Detect服务不做任何事情,不应该有任何触发它的“危险”。


注意:以上信息基于我仅在一台 Windows 7 PC 上进行的有限研究和测试。

【讨论】:

  • UI检测服务如何工作的细节都是实现细节,随时可能发生变化。创建 UI 并希望它不会触发 UI 检测服务不是合理的工程实践,因为您今天可能会躲避检测,但明天情况可能会发生变化。正确的解决方案是根本不显示 UI。
  • @RaymondChen - 我很感激你在这里的担忧 - 你原则上当然是对的。然而,合理的工程实践也告诉我,我不应该将时间和精力花在极不可能改变的事情上——而且考虑到服务根本不应该显示 GUI,并且整个 UI0Detect 看起来像是一个传统的离合器,如果这会改变为在今天没有的地方显示一条消息,我会感到非常惊讶。 (为了完整起见:在我的具体情况下,如果它不漂亮,它会没问题。)非常感谢您的洞察力!
猜你喜欢
  • 1970-01-01
  • 2021-02-07
  • 2020-07-28
  • 1970-01-01
  • 2010-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-11
相关资源
最近更新 更多