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

How to launch a non-background process from a Windows Service?

我有一个用 C# 编写的 Windows 服务,它使用 PuppeteerSharp 启动 Google Chrome 浏览器的一个实例。请参阅下面的启动代码:

string[] chromeArgs = { "--remote-debugging-port=9222" };
Browser browser = await Puppeteer.LaunchAsync(new LaunchOptions()
{
    ExecutablePath = "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe",
    DefaultViewport = null,
    Args = chromeArgs,
    Headless = false // <-- this is important!
});

即使我在非无头模式下启动浏览器,我也没有看到 Chrome 浏览器在我的机器上实际启动。我确认浏览器确实启动了,因为我看到它出现在任务管理器中。

我怀疑 Chrome 浏览器不可见,因为它是从作为后台进程的 Windows 服务启动的,因此 Chrome 会自动作为后台启动过程。 是否可以将 Chrome 作为非后台进程启动以便我可以看到它?如果是,怎么做?

I suspect that the Chrome browser is not visible because it is being launched from a Windows service which is a background process, so Chrome is automatically being launched as a background process. Is it possible to launch Chrome as a non-background process so I can see it? And if so, how?

Win32 services run in a separate session from user-visible applications. Among other reasons, this prevents a security vulnerability known as a shatter attack。所以它不只是在不同的桌面上;它在不同的桌面上,在不同的 Windows 站中,在不同的用户会话中。

虽然有 a hack 您可以放入允许显示来自 Win32 服务的 UI,但不应使用 的 hack。它需要降低整个系统的安全性,特别是另外降低该服务的安全性,并且可能会停止与任何未来的 Windows 更新一起工作。

The proper response to "how do I show a UI from a Win32 service" is "you don't"。有几种选择:

  1. 您真的需要 Win32 服务吗?也许它应该只是一个在登录时自动 运行 的常规应用程序?通常,使用 Win32 服务是因为它们可以 运行 无需 登录,但在那种情况下,我不得不问你会在哪里显示 UI如果没有用户登录?所以首先,考虑您的应用程序是否真的应该是 Win32 服务。
  2. 如果您确实需要 Win32 服务,您需要显示一个 UI,那么正确的架构是将现有应用拆分为 Win32 服务以及登录时 运行 的单独可执行文件。当 Win32 服务想要显示 UI 时,它使用某种形式的进程间通信来告诉 auto运行 应用程序显示实际的 UI.

请注意,对于选项 (2),您还需要决定如何处理有多个登录用户的情况(例如,远程桌面会话),并确定哪个 您要显示 UI 的会话。