Search code examples
windows-servicesbackground-process

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


I have a Windows Service written in C# that launches an instance of the Google Chrome browser using PuppeteerSharp. See the launching code below:

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!
});

Even though I am launching the browser in non-headless mode, I don't see the Chrome browser actually being launched on my machine. I have confirmation that the browser does actually get launched because I see it show up in Task Manager.

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?


Solution

  • 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. So it's not just on a different desktop; it's in a different desktop, which is in a different Windows station, which is in a different user session.

    While there is a hack you can put in that allows displaying a UI from a Win32 service, that hack should not be used. It requires lowering the security of the entire system, additionally lowering the security of that service in particular, and may stop working with any future Windows Update.

    The proper response to "how do I show a UI from a Win32 service" is "you don't". There are a couple of alternatives:

    1. Do you really need a Win32 service? Perhaps it should just be a regular app that is auto-run on login? Usually, Win32 services are used because they can run without a login, but in that case, I'd have to ask where exactly would you show the UI if there's no user logged in? So first, consider whether your application should really be a Win32 service or not.
    2. If you do really need a Win32 service, and you need to show a UI, then the proper architecture is to split the existing app into a Win32 service and a separate executable that runs on login. When the Win32 service wants to display a UI, it uses some form of inter-process communication to tell the autorun application to display the actual UI.

    Note that with option (2), you'd also need to decide how to handle the situation where there are multiple logged-in users (e.g., Remote Desktop sessions), and determine which session you want to display the UI on.