How to monitor Windows Service for background process crash?

Issue #155 new
Former user created an issue

When you package as a Windows Service, you implement the OnStart() and OnStop() functions in your primary script. Per the PoshTools documentation, it is not permitted to block/loop endlessly in the OnStart() function, so it seems that the OnStart() function must initiate a background job via Start-Job or a runspace. But if the background job/runspace crashes, the parent script (running as the service EXE) does not also crash. Instead, the parent script is still running, listening for a call to OnStop() from the OS service manager.

A windows service can be configured to automatically restart if it crashes. But in this case, the service EXE doesn't crash if a background job/runspace crashes. So the service effectively goes offline, even though it appears as Running to the OS. How can the parent script (EXE) monitor the background job and take action to re-launch it when necessary? Seems like I need some kind of scheduled endpoint functionality in the parent script itself to periodically run a scriptblock that could check the health of background processes.

Am I missing something?

Comments (3)

  1. Justin Holloman

    I figured out how to implement this. In short, I implemented a .NET Timer and registered an event handler inside the OnStart() function. Then I defined a scriptblock to evaluate the health of my running jobs which is triggered on every ‘tick’ of the timer.

  2. Adam Driscoll

    Nice. That’s a good solution. I guess it would be a good feature to have this built into the packaged service.

  3. Andrew Stanton

    Just be aware that Timers can also die off without notice or the ability to recover in a windows service. Ive seen it happen in the non Windows.Forms timers also. I use a non-background thread (if a foreground thread dies the program should stop) that does something like this…

    private bool _isRunning; // set to true in OnStart() before starting this thread
                             // set to false at the beginning of OnStop()
    
    void CheckingLoop()
    {
      var nextCheckTime = GetNow().AddSeconds(10);
      while (_isRunning)  
      {
        if (GetNow() >= nextCheckTime)
        {
          //do yer checking
          nextCheckTime = GetNow().AddSeconds(10);
        }
        Thread.Sleep(100);  // dont sleep for the full interval between checks
                            // doing so will cause problems with stopping the service
                            // if the interval is too long.
      }
    }
    
    protected virtual DateTime GetNow()
    {
      return DateTime.Now; //this is for unit test mocking
    }
    

  4. Log in to comment