计划启动 C# 应用程序无法为登录用户显示表单

Posted

技术标签:

【中文标题】计划启动 C# 应用程序无法为登录用户显示表单【英文标题】:Scheduled Startup C# Application can't show Forms for Logged-in Users 【发布时间】:2013-12-27 11:55:08 【问题描述】:

我一直在为 Windows XP 开发一个应用程序,该应用程序需要在 Windows 启动的同时以管理员级别权限启动,所以我继续使用任务计划程序将 exe 添加到“在系统启动时运行”。

在任何给定时间运行的应用程序实例都不应超过一个。理想情况下,应用程序将在 Windows 启动时启动,然后无论哪个用户登录,或者用户是否在一天中注销并登录,我的应用程序将始终在后台运行。这样,即使用户使用“快速用户切换”进行切换,我的应用程序仍将在用户之间运行。

在某种程度上,所有这些似乎都正常工作。但是,有时我的应用程序需要显示表单或以某种方式与用户交互,这就是它发生故障的地方。表格没有出现(尽管我相信它们正在运行)。如果我使用 Process 类并尝试执行程序,它们会在任务管理器中显示为正在运行,但实际上并未显示。他们在检查它们时也没有在 Process Hacker 中列出任何句柄。就像他们只是在后台默默地运行。

出于多种原因,我不能仅仅将任务更改为在用户登录时运行。一,我很确定我必须将计划任务添加到每个用户。第二,这个程序应该只有一个实例在运行,我担心如果有人使用快速用户切换,那么这个程序的两个实例会运行。即使我检测到一个实例已经在运行,它也无法解决问题,因为用户 #1 的实例 #1 无法为用户 #2 显示表单/窗口(我不认为,如果我是,请纠正我但在这一点上是错误的。)

理想情况下,我想在系统启动时让它继续运行,然后弄清楚为什么我不能显示任何窗口。

关于该程序的一些注意事项,它在第一次启动时最初不会显示任何内容。它创建一个表单

WndHidden wnd = new WndHidden()

但随后只运行Application.Run() 而不传递表单,然后等待某些系统提示何时向用户显示表单/消息。

我做错了什么?

【问题讨论】:

可能会有帮助:serverfault.com/questions/458848/… exe在哪个用户账户下运行? 它以“AdminUser”身份运行,这是计算机上唯一的管理员帐户,其他人都是受限用户。 【参考方案1】:

其实你这里的情况挺多的。你希望你的进程在启动时运行,即使没有用户登录。你希望进程在屏幕上显示一个表单。现在冲突了!表单可以显示在某些已登录用户的桌面上。没有用户 - 没有桌面 - 没有表单。

每个进程都属于某个用户。如果没有用户登录,则该进程属于 SYSTEM 。每个用户都有自己的桌面。登录用户有一个真实的桌面,SYSTEM 有一个虚拟桌面。因此,您的表单正在显示,但不是在真实桌面上,而是在虚拟桌面上。因此你看不到它。

进程不能干预其他用户的桌面。因此您的进程无法在其他用户或通过快速切换登录的用户上显示表单。

如果您忘记了快速用户切换部分并且只满足于一个用户,那么在安排它时,您可以指定该特定用户的凭据。这样你就可以得到你想要的,除了多用户场景。但请注意,如果用户更改密码,则计划任务会中断。你必须重新安排它。


您想要的是大多数防病毒软件所显示的行为。您需要 2 个可执行文件。 (它可以用一个 exe 来完成,但我们不要让事情复杂化)在任何用户登录之前让第一个进程在启动时运行。使用通常的 SYSTEM 帐户运行它。如果可能,将该进程注册为 Windows 服务,而不是计划任务。不要在进程中加入任何用户界面逻辑。

将所有 UI 逻辑放在第二个可执行文件中。注册第二个可执行文件以在每个用户启动时运行。不要事先显示任何表格。更好地制作一个托盘图标项目。在每个用户的桌面上休眠。

您的主进程是单一的并且独立于用户。每个用户的从属进程持有 UI。诀窍是将信号从主设备传递到相应的从设备。建立一种通信媒介,一种IPC(进程间通信)。当奴隶上线时,主人会收到通知。主人甚至可以选择要求哪个奴隶(用户)显示表格。即使多个用户通过远程桌面同时登录,此机制也有效。


至于 IPC,您可以从广泛的范围内进行选择。选项有:1. TCP/IP、2. 命名管道、3. WCF (tcp/named-pipe)、4. 远程处理。

如果上面的名字不熟悉,那么我建议使用普通的 TCP/IP,但尝试尽快升级到 WCF 的通信。

您要完成的工作实际上比看起来要复杂得多。在 XP 中这很容易,但这就是为什么 XP 比 Vista+ 更容易受到恶意软件和病毒的影响。欢迎再次提问。

【讨论】:

感谢好奇,只是为了澄清一下,该进程现在以管理员身份运行,因为这些是通过任务调度程序分配的凭据。如果我将程序重写为服务会怎样?这会限制它只运行一个实例并且它可以显示表单吗? 作为服务,它将作为单个实例运行,但没有表单。虽然服务可以呈现形式,但在实践中它从来没有帮助。 1-service-n-user-agents 是最长但最灵活和稳定的解决方案。

以上是关于计划启动 C# 应用程序无法为登录用户显示表单的主要内容,如果未能解决你的问题,请参考以下文章

任务计划程序在注销和登录后无法显示应用程序的 GUI(无论用户是不是登录都运行)

应用程序在第一次向用户显示表单之前无法启动

由任务计划程序启动时隐藏 C# winform 应用程序窗口

如果未使用 C# 登录 ASP.NET Web 表单,则将用户重定向到登录

如果在没有任何用户登录的情况下从任务计划程序启动应用程序是不可见的

自定义登录表单无法使用 Spring Security