从Windows服务启动winform应用程序

时间:2010-08-26 14:39:31

标签: windows vb.net winforms windows-services

请告诉我如何在服务的当前登录用户下运行应用程序。

为了给你背景,我有一个VB.NET Windows服务,其唯一的功能是在指定的时间运行Winform App。除此之外,它还设置了系统唤醒计时器,以便系统可以在指定的时间唤醒,如果它进入待机/睡眠状态,则运行应用程序。此服务必须满足我们网络上的XP / Vista / Win7桌面。此服务不会在服务器和笔记本电脑上运行。

Winform应用程序显示用户提供一些输入的UI。如果用户未在15分钟内提供输入,则默认值,然后进入系统托盘图标。用户可以单击图标并稍后更改值(在指定的时间范围内,也只是两次)。

除了启动应用程序的服务之外,服务和winform应用程序之间绝对没有交互。它还监视应用程序是否已被用户杀死/崩溃。如果它已被杀死/崩溃,则在上一次运行30分钟后运行一个新实例。

如果没有用户登录,那么我也希望应用程序在指定的时间运行。正如我之前所说,该应用程序有一个默认计时器。因此,如果某个用户刚刚从系统注销,则默认值将由winform应用程序设置。

现在为什么我会遇到这种设计 - 我无法使用TaskScheduler,因为它已在所有机器上禁用,安全团队不愿意更改它。 TaskScheduler可以选择将机器从睡眠和其他东西中唤醒。所以基本上我最终创建了一个像任务调度程序一样的服务。

目前,当我通过服务中的process.start()运行app.exe时,它在SYSTEM帐户下运行,因为该服务也在LOCAL SYSTEM下运行。所以基本上我没有得到任何UI。无论如何在当前登录用户下运行它?我不担心多个用户登录,因为我们不会在服务器上运行它,并且我们的桌面上没有启用交换机用户。即使有人通过mstsc进行了远程登录,我也需要运行应用程序并向用户显示UI。

请告诉我如何在服务的当前登录用户下运行应用程序。

由于 askids

1 个答案:

答案 0 :(得分:1)

我发布了一些其他评论。但我不知道怎么看不到它:(

回到最初的问题。经过几次试验和错误,我能够弄明白。我会详细说明。

使用Vista及更高版本,服务与其他用户会话隔离开来。它们在会话0中运行。用户会话在1及更高版本中运行。所以基本上你需要模拟当前登录用户的过程。

  1. 使用 WTSEnumerateSessions 和 获得会议。检查是否有sesion 国家是活跃的。这将会 当前登录的用户会话。如果 它没有活跃的会话 表示没有登录用户。在 我的情况下,只会记录1个 在用户上。所以我不需要弄清楚 活跃的会议(像其他人一样) 需要这样做。
  2. 使用 WTSQueryUserToken 在活动会话中获取用户令牌。 使用 DuplicateTokenEx
  3. 创建主要用户令牌
  4. 使用 CreateEnvironmentBlock
  5. 创建环境
  6. 使用 CreateProcessAsUser
  7. 中的上述信息

    之所以在XP中而不是在Vista中工作,是因为它看起来像启动默认信息不同。在我设置了startupinfo结构的wShowWindow标志后,GUI将开始出现。

    Dim StartupInfo As New STARTUPINFO()
    StartupInfo.cb = Marshal.SizeOf(StartupInfo)
    StartupInfo.dwFlags = STARTF_USESHOWWINDOW 
    StartupInfo.wShowWindow = WINDOW_STATUS.SW_SHOWNORMAL
    

    还有一个额外信息。我试图使用
    设置默认桌面 StartupInfo.lpDesktop = "WinSta0\\Default"
    因为应用程序在启动时会崩溃。所以我评论了它。

    我还有一个最后的问题。推出的应用程序不是焦点。 GUI出现,但在后台。但我在想,它将再次与上面的一些参数有关。一旦我搞清楚,我将添加细节。