3

I have a windows service that polls a database and will do things depending on the records it finds.

I want to set up Azure Devops to automatically deploy an upgrade to this service.

In order to deploy the upgrade I need to stop the service.

Is there a way that I can tell whether this would interrupt it processing?

In my release pipeline, with a command task, I use

sc stop MyService

[Update]

Here is my simplified code

static class Program
{
    static void Main()
    {
        ServiceBase.Run(new ServiceBase[] { new Hoster() });
    }
}

  public sealed class Hoster : ServiceBase
{
    private IMyEngine _engine;
    private readonly EventHandler<EngineProgressEventArgs> _progressHandler;
    public Hoster()
    {
            _progressHandler = TrapEngineProgress;
    }

    protected override void OnStart(string[] args)
    {
        try
        {
            _engine = MyFactory.Create();
            _engine.Progress += _progressHandler;
            _engine.StartupEngine();
        }
        catch (Exception ex)
        {
            _logger.Error("OnStart failed", ex);
        }
    }

    protected override void OnStop()
    {
        if (_engine == null) return;
        _engine.Dispose();
        _engine.Progress -= _progressHandler;
        _engine = null;
    }


    private void TrapEngineProgress(object sender, EngineProgressEventArgs e)
    {
        switch (e.Type)
        {
            case ProgressType.Changed:
                Trace("Changed: " + e.Filename);
                break;
            case ProgressType.Created:
                Trace("Created: " + e.Filename);
                break;
            case ProgressType.Trace:
                Trace(e.Message);
                break;
            case ProgressType.Error:
                Error(e.Error, e.Message);
                break;
        }
    }
}
Julian
  • 33,915
  • 22
  • 119
  • 174
Kirsten
  • 15,730
  • 41
  • 179
  • 318
  • https://ss64.com/nt/sc.html – Kirsten Jun 07 '19 at 03:40
  • 1
    depends on your service-implementation. your service could write an empty ".isworking" file to indicate that it is working. you could then check if that file exists before stopping the service or waiting in a loop for the file to dissapear and then stop the service. – D.J. Jun 07 '19 at 06:46
  • I guess I could also do this with an environment variable. I was wondering if there was any "right way" maybe some property inside the service. – Kirsten Jun 08 '19 at 08:16
  • https://stackoverflow.com/questions/39097719/tcp-ip-listener-in-windows-service – Kirsten Jun 16 '19 at 06:07

1 Answers1

3

When you issue the SC STOP command, you are merely making a request for the service to stop itself. When the service receives the request, it can stop immediately or wait until it has finished important tasks — whatever it wants to do. Your service is in control.

To avoid inappropriate interruption, your service's "stop workflow" should look like this:

  1. A request is made to stop the service (via SC STOP, NET STOP, etc.)
  2. The service's "listener thread" receives the request to stop
  3. The thread sets a flag that a stop has been requested and sets the service's state to SERVICE_STOP_PENDING
  4. The "processing thread" periodically checks the flag (at convenient times — likely between jobs)
  5. If the flag is set, the processing loop exits when convenient
  6. And since all processing is done, the service status is set to SERVICE_STOPPED and the entire service exits.

With that approach, your service will never be interrupted in a "bad" place.

CoreTech
  • 2,345
  • 2
  • 17
  • 24