2

I am trying to build a windows service that automates the running of an 3rd party application, let's call it BlackBox.exe. BlackBox.exe runs fine when run from the current user's session but fails when executed from the service. BlackBox.exe has a UI but it can be automated by passing it command line parameters. In the automated mode it shows some UI, reads input files, writes output files and then exits without any user interaction. We only have binaries for BlackBox.exe.

The service is configured to use the same user as BlackBox.exe was installed and registered under.

I've run a comparison of a the events captured by Process Monitor interactive session vs service session. There's no registry or file operations that are failing for the service session and succeeding for the service session. Notably, the registry keys for the license activation are read successfully in both cases.

When run from the service BlackBox.exe is visible in the Task Manager with 0% cpu and will remain there until killed.

I guess the lack of access to the desktop is causing BlackBox.exe to fail - maybe there's a way to fool BlackBox.exe to think it has access to the desktop without having a user logged in?

How can I run BlackBox.exe from a service?

UPDATE: If I:

  • start the "Interactive Services Detection" service,
  • click "View Message" from the Interactive Services Detection dialog,
  • watch BlackBox.exe gui do its processing until I see the Interactive Serivces Detection message "the application is no longer requesting your attention"
  • click "Return Now"

...it works fine. So it might be related to Session 0 isolation

Sam Sippe
  • 3,160
  • 3
  • 27
  • 40
  • 1
    Why a service, and not a scheduled task (see [Task Scheduler](https://msdn.microsoft.com/en-us/library/windows/desktop/aa383614.aspx))? – IInspectable Jan 25 '16 at 02:17
  • @IInspectable It could be a scheduled task. However, I've tested scheduled tasks but it doesn't work when you select the "Run whether user is logged on or not" option is selected, which is what I need. I assume the failure is for the same reason as the service. – Sam Sippe Jan 25 '16 at 02:26
  • 1
    What version of Windows are you using? – CoreTech Jan 25 '16 at 06:51
  • @CoreTech Windows 7 Professional – Sam Sippe Jan 27 '16 at 01:11
  • 1
    So just to be clear -- it doesn't work if the Interactive Services Detection service is stopped? What about if the ISD service is running but you don't click "View Message"? – CoreTech Jan 27 '16 at 20:43
  • @CoreTech A1 - correct. A2 - Doesn't work. – Sam Sippe Jan 27 '16 at 22:44
  • 1
    Did you check "Allow service interact with desktop" in service properties? – jlvaquero Feb 01 '16 at 11:07
  • @jlvaquero Yes tried both with and without this set. That allows the Blackbox.exe to run if the user clicks View Message and switches to the Session 0 desktop. However, the goal is to have the Blackbox.exe run without user intervention. – Sam Sippe Feb 01 '16 at 23:50
  • 1
    Maybe this could be useful ( http://stackoverflow.com/questions/3128017/possible-to-launch-a-process-in-a-users-session-from-a-service ) Also this (http://blogs.msdn.com/b/winsdk/archive/2009/07/14/launching-an-interactive-process-from-windows-service-in-windows-vista-and-later.aspx) can help. – jlvaquero Feb 02 '16 at 08:32
  • @jlvaquero Thanks for that. It seems as though the service can CreateProcessAsUser provided there is an existing interactive user session that the service can make use of. Do you know if the service can create an interactive user session to use? – Sam Sippe Feb 02 '16 at 23:26

1 Answers1

1

Can you essentially run a popup blocker against this? The assumptions here are that that CloseMainWindow() will have the same effect as "View Message", and that you allow the service to interact with the desktop. Sample code below; adapt to your particular scenario and run as a separate thread from your service.

public class Program
{
    public static void Main(string[] args)
    {
        while (true)
        {
            DestroyAllBobs();
            Thread.Sleep(100);
        }
    }

    private static void DestroyAllBobs()
    {
        Process[] bobs = Process.GetProcessesByName("robert");
        foreach (Process bob in bobs)
        {
            if ("Microsoft Visual C++ Runtime Library".Equals(bob.MainWindowTitle))
            {
                bob.WaitForInputIdle();
                if ("Microsoft Visual C++ Runtime Library".Equals(bob.MainWindowTitle)
                    && "robert".Equals(bob.ProcessName))
                {
                    try
                    {
                        bob.CloseMainWindow();
                    }
                    catch (Exception)
                    {
                    }
                }
            }
        }
    }
}
Eric Hirst
  • 1,111
  • 15
  • 31
  • Worth a try. What are you basing your assumption on? – Sam Sippe Feb 03 '16 at 03:00
  • This is a technique I used in the past with a 3rd party COM-automated exe that was violating its "no popup windows when in windowless mode" contract. We ran code like this (in a more tightly scoped manner) from inside a desktop app, not a service. I'd been assuming that you have something similar here, and that it's not as simple as just using .NET's ProcessStartInfo.CreateNoWindow flag. However, as I re-read your question, I wonder if the CreateNoWindow is actually all that's missing? – Eric Hirst Feb 03 '16 at 17:58
  • Tried with ProcessStartInfo.CreateNoWindow=true and no change. – Sam Sippe Feb 04 '16 at 02:22
  • Tried CloseMainWindow after waiting 30s and has no impact. The MainWindowTitle=="" which is the case "If the associated process does not have a main window" – Sam Sippe Feb 04 '16 at 02:25
  • Hmm. There might be something in the Process's Component.Events enumeration that you could hook into, but I'm just guessing at this point. Integrating with 3rd party binaries like this can be a bit of an art, unfortunately. – Eric Hirst Feb 04 '16 at 19:18