Loading GUI App from Windows Service

点点圈 提交于 2019-12-01 11:31:20

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

That post has some references to a couple of potential workarounds. Here is a thread on MSDN that details the entire process, and some of the potential hiccups you may face.

However, I'd highly recommend trying to see if you can switch to having a user-mode application run as a startup app (when the user logs in), and any communication to your service be handled by that application. It's much more reliable, especially under vista, terminal services, and other situations.

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.

As a test, perhaps change the credentials of the service to the currently logged in user just to see what happens.

Since a service runs even though a user isn't logged in, what happens if it launches the app? Your business rules or functionality might keep that from happening, but perhaps windows is doing something to keep it from working.

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.

Do you expect your application/service to work when the terminal server role is enabled? If so, you really need to do the "application which polls the service" model and not the "service which launches the application" model.

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.

This is the code I have used in the past to do this in a task-management service, which sometimes needed to run stuff in an interactive session. Replace wibble.exe with your app. It should run fine on Server 2003 (i.e. NT5). We didn't bother trying to get interactive mode running on NT6 (too many hassles), we left our apps running in the service session and wrote our own debug utility to talk to them via pipes.

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.
   }
}

Your "specified user account" would have to be the console session here, I'm thinking. If you needed it to run in a specified account without that account being already logged in, you're in a whole new world of hurt, loading registry hives etc.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!