English 中文(简体)
从Windows服务加载GUI应用程序
原标题:
  • 时间:2009-04-30 16:01:07
  •  标签:

I am writing a .NET Windows service whose role is to launch a GUI application(whose source is unavailable). The operation is a fire and forget, no communication besides initial command-line parameters.

The service ought to run as a given Windows account.

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

Note: this is the specification and the design of the system. The typical concerns raised with service/app communication and security do not apply in this specific case.

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

edit2: The OS is Windows 2003 Server, and there are no plans to upgrade it.

问题回答

This is, unfortunately, more problematic since Vista... Some details as to why are posted on this blog post.

这篇帖子提到了几种可能的解决方法。 这是 MSDN 上的一个帖子 ,详细介绍了整个过程,以及您可能会遇到的一些潜在问题。

然而,我强烈建议尝试看看是否可以将用户模式应用程序切换为启动应用程序(当用户登录时),并且任何与您的服务的通信都由该应用程序处理。这更加可靠,特别是在Vista,终端服务和其他情况下。

This is a stab in the dark but hopefully will lead you down some sort of path to the solution.

Even though security isn t a concern, it may be the problem. The service is launching the app under a different set of credentials than the currently logged in user. It d be like Remote Desktop to a users machine and launch an app that they would see.

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

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

You can use free Autologon utility http://technet.microsoft.com/en-us/sysinternals/bb963905.aspx from Sysinternals/Microsoft and put you application into Startup for autologon user profile. After that you can configure screen sever to start in several minutes and check "On resume, display logon screen" checkbox.

你希望在终端服务器角色启用时,你的应用程序/服务能够正常工作吗?如果是,那么你真的需要采用“轮询服务的应用程序”模型而不是“启动应用程序的服务”模型。

The reason for this is that you may have multiple users connected to the machine at any time and there s no way of knowing which is at the "console" - in fact there might be nobody at the console at all.

这是我过去在任务管理服务中用于执行交互式会话的代码。将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.
   }
}

你的“指定用户帐户”必须在这里成为控制台会话,我在考虑。如果您需要在指定帐户中运行而不需要该帐户已登录,则需要加载注册表文件,这是一个全新的麻烦世界。





相关问题
热门标签