从Windows服务启动GUI应用程序 - 窗口未显示

8
我已经编写了一个简单的Windows服务,该服务将在onstart()方法中启动指定的exe。启动服务后,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();

你期望什么?试着运行一个批处理文件。 - Adrian Godong
你试图启动哪种类型的exe文件? - abhilash
请将您的问题重新表述为更有意义的内容。当浏览问题列表时,这样做可以提供更多信息... - Hemant
5个回答

11

在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;
}

4

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

服务的作用是默默地完成工作,这正是它们应该做的。但当它们有重要事情要说时,在 Windows 事件日志中记录一些内容是例外。


此外,默认情况下,任务管理器仅显示在您的登录帐户下运行的进程。 - MSalters

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

1

按照定义,服务本质上不是交互式的,因此当您从服务启动应用程序时,不应该期望显示任何用户界面元素。

这是设计上的考虑...


1

正如其他人所提到的,Windows服务通常在单独的帐户(“LocalSystem”或“NetworkService”)下运行。这就是为什么您可能看不到由服务启动的程序的用户界面的原因。此外,服务不打算具有UI,它们作为后台服务。

但请注意,通过服务启动应用程序可能会带来高安全风险,因为该应用程序与您的服务具有相同的特权。通常,这将是本地系统帐户。

我不知道您的服务尝试实现什么目标,但请考虑使用Windows的自动启动功能而不是服务来运行您的应用程序。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接