【问题标题】:Loading GUI App from Windows Service从 Windows 服务加载 GUI 应用程序
【发布时间】:2009-04-30 16:01:07
【问题描述】:

我正在编写一个 .NET Windows 服务,其作用是启动一个 GUI 应用程序(其源代码不可用)。 该操作是一劳永逸,除了初始命令行参数外没有任何通信。

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

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

注意:这是系统的规格和设计。与服务/应用程序通信和安全相关的典型问题不适用于这种特定情况。

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

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

【问题讨论】:

    标签: c# windows service launching-application


    【解决方案1】:

    不幸的是,自 Vista 以来,问题更加严重......关于原因的一些详细信息发布在 this blog post.

    那篇文章提到了一些潜在的解决方法。 Here is a thread on MSDN 详细介绍了整个过程,以及您可能面临的一些潜在问题。

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

    【讨论】:

    • 服务器是 Win2K3,它可以保持这种状态。指定的目标是首选方法是让应用作为服务运行。
    【解决方案2】:

    这是在黑暗中的尝试,但希望能引导您找到解决方案。

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

    作为测试,也许将服务的凭据更改为当前登录的用户只是为了看看会发生什么。

    由于即使用户未登录服务也会运行,如果它启动应用程序会发生什么?您的业​​务规则或功能可能会阻止这种情况发生,但也许 Windows 正在做一些事情来阻止它工作。

    【讨论】:

    • 为清晰起见进行了编辑。安全绝对是这里的“问题”。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

      这样做的原因是,您可能随时有多个用户连接到计算机,并且无法知道“控制台”上的用户是谁 - 实际上控制台上可能根本没有人。

      【讨论】:

        【解决方案5】:

        这是我过去在任务管理服务中使用的代码,有时需要在交互式会话中运行一些东西。将 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.
           }
        }
        

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-09-06
          • 1970-01-01
          • 1970-01-01
          • 2023-03-15
          • 2010-11-09
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多