如何从 Windows 服务启动具有 UI 的进程?

Posted

技术标签:

【中文标题】如何从 Windows 服务启动具有 UI 的进程?【英文标题】:How can i lauch a process which has a UI from Windows service? 【发布时间】:2009-10-21 19:17:37 【问题描述】:

我已经创建了一个服务应用程序和一个 Windows 窗体应用程序,现在我想从服务中启动 Windows 应用程序。我知道在win7中因为服务隔离 您不能直接执行此操作,因此我使用了“advapi32.dll”方法的“CreateProcessAsUser”,但它能够创建也出现在“任务管理器”中的进程,但不会向用户显示 UI。是什么原因 ?有人可以帮我解决这个问题吗?

好的,让我给出我写的代码

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Ansi, EntryPoint = "CreateProcessAsUser")] 

public static extern bool CreateProcessAsUser(IntPtr hToken,string lpApplicationName,string lpCommandLine,ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes,bool bInheritHandles,int dwCreationFlags,string lpEnvironment,string lpCurrentDirectory,ref STARTUPINFO lpStartupInfo,ref PROCESS_INFORMATION lpProcessInformation);


void LounchNewApplication() 




 try

   

      string strAppName = @"D:\Working\UAC Demo\Tester\bin\Debug\Tester.exe"; 

      string strAppPath = @"D:\Working\UAC Demo\Tester\bin\Debug\";

      PROCESS_INFORMATION lpProcessInformation = new PROCESS_INFORMATION(); 

      SECURITY_ATTRIBUTES lpProcessAttributes = new SECURITY_ATTRIBUTES(); 

      lpProcessAttributes.nLength = (uint)Marshal.SizeOf(lpProcessAttributes); 

      STARTUPINFO lpStartupInfo = new STARTUPINFO(); 

      lpStartupInfo.cb = Marshal.SizeOf(lpStartupInfo); 

      lpStartupInfo.lpDesktop = "WinSta0\\Default"; 
      IntPtr htoken = IntPtr.Zero; 

      LogonUser("myName", "DomineName", "password", 2, 0, out htoken); 


      if (!CreateProcessAsUser(htoken, strAppName, null, ref lpProcessAttributes,
         ref lpProcessAttributes, true, 0, null, strAppPath, ref lpStartupInfo,
         ref lpProcessInformation)) 

        

          eventLogger.WriteEntry("Error in starting application", EventLogEntryType.Error); 

        
     else
         eventLogger.WriteEntry("Application launched successfulll" EventLogEntryType.Information); 




      //CloseHandle(lpProcessInformation.hThread);



      //CloseHandle(lpProcessInformation.hProcess);

  



  catch (Exception ex) 

  

    eventLogger.WriteEntry(ex.Message,


     EventLogEntryType.Error); 

  


我正在调用服务的 LounchNewApplication() 方法 OnStart。

【问题讨论】:

【参考方案1】:

您以用户身份启动进程,但在会话 0 中,这是非交互式的。不要使用 LogonUser 创建用户令牌。使用WTSQueryUserToken,传入您要在其中创建进程的会话。此令牌具有正确的会话ID。您可以使用WTSEnumerateSessions 列出机器上的所有会话,或在服务处理程序中处理会话更改通知。

【讨论】:

亲爱的迈克尔,感谢您的回答。现在我可以从 win 服务启动应用程序,并且我可以在用户会话中看到 UI 非常感谢... @Arjuna,如果这有帮助,那么您应该接受这个答案,以便迈克尔获得适当的信任。【参考方案2】:

从技术上讲,服务必须标记为交互式,例如。 sc config <servicename> type= interact

服务不应该与控制台交互,并且绝对不能在服务启动中。幸运的是,这在 Windows 2003 之后得到了修复,在 Vista、Windows 2008 和 Windows 7 中,这种不当行为变得越来越难。

正确的方法是将您的应用程序分成服务和监控应用程序。监视器作为用户会话上的普通应用程序运行,并通过 IPC 与服务通信。

【讨论】:

以上是关于如何从 Windows 服务启动具有 UI 的进程?的主要内容,如果未能解决你的问题,请参考以下文章

如何从Windows服务启动进程到当前登录的用户会话

如何从Windows服务启动非后台进程?

CreateProcessAsUser,C#写的windows服务弹框提示消息或者启动复杂的UI界面的子进程

如何启动一个进程以从 Windows 服务运行 bat 文件

以 Windows 登录用户身份从服务启动进程

如何从C#启动/停止Windows服务