从 Windows 服务启动 GUI 应用程序 - 窗口不出现

Posted

技术标签:

【中文标题】从 Windows 服务启动 GUI 应用程序 - 窗口不出现【英文标题】:Launching GUI App from Windows Service - Window Does Not Appear 【发布时间】:2010-11-09 16:54:50 【问题描述】:

我编写了一个简单的 Windows 服务,它将启动在 onstart() 服务的方法。启动服务后,exe仅启动 出现在内存中,但在资源管理器中不显示。

我正在尝试从我的代码中启动calc.exe。它显示了内存中的 exe,但它 在资源管理器中没有出现在我的视图中(即)。

下面是我在 onStart() 方法中启动 exe 的代码

    Process pr=new Process();
    pr.StartInfo.FileName="calc.exe";
    pr.StartInfo.WindowStyle=ProcessWindowStyle.Maximized;
    pr.StartInfo.CreateNoWindow=false;
    pr.Start();
//  pr.WaitForExit();

【问题讨论】:

你期待什么?请尝试运行批处理文件。 您要启动什么类型的 exe? 请将您的问题重新表述为更有意义的内容。浏览问题列表时,它并不能说明很多... 【参考方案1】:

服务在 Vista 或更高版本的其他会话中运行,并且直接从服务启动的应用程序默认在同一会话中启动。可以在其他会话中启动应用程序 - 您必须找到用户会话的 id 并使用 CreateProcessAsUser。

如果有多个用户登录并且您需要为所有用户启动程序,您必须找到所有会话的 ID。

这里是示例代码:

int session = Win32.WTSGetActiveConsoleSessionId();
if (session == 0xFFFFFFFF)

    return false;


IntPtr userToken;
bool res = Win32.WTSQueryUserToken(session, out userToken);
if (!res)

    this.log.WriteEntry("Error WTSQueryUserToken");
    return false;


string path = GetPath();
string dir = Path.GetDirectoryName(path);
Win32.STARTUPINFO si = new Win32.STARTUPINFO();
si.lpDesktop = "winsta0\\default";
si.cb = Marshal.SizeOf(si);

Win32.PROCESS_INFORMATION pi = new Win32.PROCESS_INFORMATION();
Win32.SECURITY_ATTRIBUTES sa = new Win32.SECURITY_ATTRIBUTES();
sa.bInheritHandle = 0;
sa.nLength = Marshal.SizeOf(sa);
sa.lpSecurityDescriptor = IntPtr.Zero;

if (!Win32.CreateProcessAsUser(userToken,       // user token
                                path,           // exexutable path
                                string.Empty,   // arguments
                                ref sa,         // process security attributes ( none )
                                ref sa,         // thread  security attributes ( none )
                                false,          // inherit handles?
                                0,              // creation flags
                                IntPtr.Zero,    // environment variables
                                dir,            // current directory of the new process
                                ref si,         // startup info
                                out pi))        // receive process information in pi

    int error = Marshal.GetLastWin32Error();
    this.log.WriteEntry("Error CreateProcessAsUser:" + error);
    return false;

【讨论】:

【参考方案2】:

服务在不同的帐户权限(LocalService/NetworkService 等)下运行,因此它们无权访问您的桌面(在您的登录帐户的控制下)。

服务应该默默地完成他们的工作,这就是他们应该做的。 (除了当他们有重要的事情要说时在 Windows 事件日志中记录一些东西)

【讨论】:

此外,默认情况下,任务管理器仅显示在 您的 登录帐户下运行的进程。【参考方案3】:

如果您打开服务的属性窗口,请转到“登录”选项卡,然后选中“允许服务与桌面交互”复选框,您将获得所需的行为。此外,根据您要运行的应用程序,您可能需要更改登录帐户。

【讨论】:

【参考方案4】:

根据定义,服务不是交互式的,因此您不应期望在从服务启动应用程序时显示任何用户界面元素。

这是设计使然...

【讨论】:

【参考方案5】:

就像其他人已经提到的那样,Windows 服务“通常”在单独的帐户(“LocalSystem”或“NetworkService”)下运行。这就是您可能看不到由您的服务启动的程序的 UI 的原因。此外,服务不具有 UI,它们充当后台服务。

但还要注意,通过服务启动应用程序可能存在很高的安全风险,因为应用程序运行的权限与您的服务相同。通常这将是本地系统帐户。

我不知道你想用你的服务实现什么,但考虑使用 windows 的自动启动功能而不是服务来运行你的应用程序。

【讨论】:

以上是关于从 Windows 服务启动 GUI 应用程序 - 窗口不出现的主要内容,如果未能解决你的问题,请参考以下文章

从 Windows 服务启动 GUI 应用程序

如何在 Windows 服务中启动 GUI 程序?

错误1053:服务没有及时响应启动或控制请求

VS CodedUI无法启动经典Windows应用程序的GUI

使用网络登录从 Windows 服务创建 GUI

如何从 GUI 控制 Windows 服务的设置?