从Windows服务加载GUI应用程序

时间:2009-04-30 16:01:08

标签: c# windows service launching-application

我正在编写.NET Windows服务,其作用是启动GUI应用程序(其源不可用)。 除了初始命令行参数之外,操作是火灾和遗忘,没有通信。

该服务应该作为给定的Windows帐户运行。

问题:服务启动的应用程序在桌面上显示而不是。它需要是,因为它是一个交互式应用程序。解决方案是什么?

注意:这是系统的规格和设计。在此特定情况下,服务/应用程序通信和安全性引发的典型问题不适用

编辑:当以本地系统帐户登录时,GUI元素显示正确,但是,由于GUI应用程序需要访问网络驱动器(它无法理解UNC映射),因此需要以指定用户身份运行帐户,并且没有“显示交互元素”设置。

edit2:操作系统是Windows 2003 Server,并且没有计划升级它。

5 个答案:

答案 0 :(得分:4)

遗憾的是,自Vista以来,这个问题更加严重...有关原因的详细信息发布在this blog post.

该帖子提到了一些潜在的解决方法。 Here is a thread on MSDN详细说明了整个过程,以及您可能面临的一些潜在障碍。

但是,我强烈建议您尝试查看是否可以切换为将用户模式应用程序作为启动应用程序运行(当用户登录时),并且该应用程序将处理与您的服务的任何通信。它更加可靠,尤其是在vista,终端服务和其他情况下。

答案 1 :(得分:0)

这是在黑暗中刺伤,但希望能引导你走上某种解决方案的道路。

即使安全性不是问题,也可能是问题所在。该服务使用与当前登录用户不同的凭据集启动应用程序。对于用户计算机来说它就像是远程桌面,并启动他们会看到的应用程序。

作为测试,可能会将服务的凭据更改为当前登录的用户,以查看会发生什么。

由于服务即使用户未登录也会运行,但如果启动应用程序会发生什么?您的业​​务规则或功能可能会阻止其发生,但也许Windows正在采取措施防止其无法正常工作。

答案 2 :(得分:0)

您可以使用Sysinternals / Microsoft的免费Autologon实用程序http://technet.microsoft.com/en-us/sysinternals/bb963905.aspx,并将您的应用程序放入Startup for autologon用户配置文件中。之后,您可以将屏幕服务器配置为在几分钟内启动,然后选中“在恢复时,显示登录屏幕”复选框。

答案 3 :(得分:0)

启用终端服务器角色时,您是否希望您的应用程序/服务正常工作?如果是这样,你真的需要做“轮询服务的应用程序”模型而不是“启动应用程序的服务”模型。

原因在于您可能随时有多个用户连接到计算机,并且无法知道哪个位于“控制台” - 实际上控制台上可能根本没有用户。

答案 4 :(得分:0)

这是我过去用于在任务管理服务中执行此操作的代码,有时需要在交互式会话中运行内容。用您的应用程序替换wibble.exe。它应该在Server 2003(即NT5)上正常运行。我们没有尝试在NT6上运行交互模式(太麻烦),我们让我们的应用程序在服务会话中运行,并编写了我们自己的调试实用程序,通过管道与他们交谈。

STARTUPINFO  sui ;
PROCESS_INFORMATION pi;

ZeroMemory (&sui, sizeof(STARTUPINFO));
sui.cb = sizeof (STARTUPINFO);
sui.wShowWindow = pTask->GetWinStartState();
sui.dwFlags     = STARTF_USESHOWWINDOW;
ZeroMemory (&pi,sizeof(pi));

if (InteractiveMode)
{
   HANDLE  hToken = NULL;
   DWORD dwSessionId = GetCurrentUserSession();

   if (dwSessionId != (DWORD)-1)
   {
      if (WTSQueryUserToken (dwSessionId, &hToken))
      {
         sui.lpDesktop = TEXT("winsta0\\default");
         LPVOID  pEnv = NULL;
         dwCreateFlags |= CREATE_NEW_CONSOLE;
         HMODULE hModu = LoadLibrary(TEXT("Userenv.dll"));

         if (hModu)
         {
            if (CreateEnvironmentBlock (&pEnv, hToken, FALSE))
            {
               dwCreateFlags |= CREATE_UNICODE_ENVIRONMENT;    
            }
            else
            {
               pEnv = NULL;
            }
         }

         bCreatedOk = CreateProcessAsUser (hToken,
                                           NULL,
                                           TEXT("wibble.exe"),
                                           NULL,
                                           NULL,
                                           FALSE,
                                           dwCreateFlags,
                                           pEnv,
                                           NULL,
                                           &sui,
                                           &pi);
      }
      else
      {
         // error case
      }
   }
   else
   {
      // remote session? error case.
   }
}

我想,你的“指定用户帐户”必须是控制台会话。如果您需要它在指定帐户中运行而该帐户尚未登录,那么您将处于一个全新的受伤世界,加载注册表配置单元等。