During the years as a developer, I have been working a lot in the field of Windows Services in .NET both implementing them as well as monitoring or controlling them.

This has lead to an implementation of a so called ServiceWatcher, basically a class that in a defined interval updates a ServiceController and then checks the status. If changes in a monitored services status are discovered, the ServiceWatcher will raise an event containing the new status of the service.

A Simple Implementation

The very first implementation was very simple, it contained 3 elements in basic that was used to obtain the needed functionality.

  • A Timer to update at a frequency
  • A ServiceControllerStatus holding the status of the service on the last check.
  • A ServiceController for getting the status of a service.

While the interface allowed one to listen to an event that would occur on changes, set the service name and update interval, and explicitly perform an update.

Here is the code.

   1:  public class ServiceWatcher
   2:  {
   3:      public event EventHandler<ServiceChangedEventArgs> ServiceChangedEvent;
   4:   
   5:      private Timer timer;
   6:      private ServiceControllerStatus lastStatus;
   7:      private ServiceController service;
   8:   
   9:      public int UpdateInterval { get; set; }
  10:      public string ServiceName { get; set; }
  11:   
  12:      public void Start()
  13:      {
  14:          service = new ServiceController( ServiceName );
  15:          timer = new Timer( o => Update(), null, 0, UpdateInterval );
  16:      }
  17:   
  18:      public void Update()
  19:      {
  20:          service.Refresh();
  21:          ServiceControllerStatus newStatus = service.Status;
  22:          if ( newStatus != lastStatus )
  23:          {
  24:              OnServiceChangedEvent( new ServiceChangedEventArgs( newStatus ) );
  25:              lastStatus = newStatus;
  26:          }
  27:      }
  28:   
  29:      private void OnServiceChangedEvent( ServiceChangedEventArgs args )
  30:      {
  31:          if ( ServiceChangedEvent != null )
  32:          {
  33:              ServiceChangedEvent( this, args );
  34:          }
  35:      }
  36:  }
  37:   
  38:  public class ServiceChangedEventArgs : EventArgs
  39:  {
  40:      public ServiceControllerStatus Status { get; private set; }
  41:      public ServiceChangedEventArgs( ServiceControllerStatus status )
  42:      {
  43:          Status = status;
  44:      }
  45:  }

Obviously there is a few problems with the above. First of all subscribing to a service that did not exist would cause an exception within the timer thread. But for me a more important thing was that it did not meet my requirements for testing.

I'm not necessarily the person who just love testing, but I do like at least some, and referring a ServiceController directly made it difficult to perform other than integration tests, and after all I'm not that interested in ending up having a set of tests that as a major part tests the ServiceController in the .NET framework implicitly.

But even more concerning, the test would depend on services on the computer, and that did not feel right.

Wrapping the ServiceController

First of I needed to wrap the .NET ServiceController so that the ServiceWatcher did not rely on that, but instead relied on an interface which I could mock out.

This is pritty straight forward since we just map all the methods and properties from the service controller, I chose to leave out elements that was not directly defined on the ServiceController class, e.g. all the inherited methods from Control.

   1:  public interface IServiceControllerWrapper : IDisposable
   2:  {
   3:      bool CanPauseAndContinue { get; }
   4:      bool CanShutdown { get; }
   5:      bool CanStop { get; }
   6:   
   7:      string DisplayName { get; set; }
   8:      string MachineName { get; set; }
   9:      string ServiceName { get; set; }
  10:   
  11:      SafeHandle ServiceHandle { get; }
  12:      ServiceType ServiceType { get; }
  13:   
  14:      IServiceControllerWrapper[] ServicesDependedOn { get; }
  15:      IServiceControllerWrapper[] DependentServices { get; }
  16:      ServiceControllerStatus Status { get; }
  17:   
  18:      void Close();
  19:      void Continue();
  20:      void ExecuteCommand( int command );
  21:      void Pause();
  22:      void Refresh();
  23:      void Start();
  24:      void Start( string[] args );
  25:      void Stop();
  26:      void WaitForStatus( ServiceControllerStatus desiredStatus );
  27:      void WaitForStatus( ServiceControllerStatus desiredStatus, TimeSpan timeout );
  28:  }
 

So that's the interface. You may note that for the ServiceDependedOn property as well as the DependentServices property the mapping to the ServiceController is not direct, instead all returned ServiceControllers should be returned as our wrapper.

Now we need an actual implementation, this is also rather easy, basically we implement the interface, and for all methods redirect the call to a ServiceController except the two properties we defined differently on the interface.

Here is a sample of the implementation, I have excluded all properties and methods that are just redirects and instead just focused on the constructors as well as the two properties I mentioned before.

   1:  public class ServiceControllerWrapper : IServiceControllerWrapper
   2:  {
   3:      private readonly ServiceController innerController;
   4:   
   5:      public IServiceControllerWrapper[] ServicesDependedOn
   6:      {
   7:          get
   8:          {
   9:              return Array.ConvertAll( innerController.ServicesDependedOn, sc => ( new ServiceControllerWrapper( sc ) ) );
  10:          }
  11:      }
  12:   
  13:      public IServiceControllerWrapper[] DependentServices
  14:      {
  15:          get
  16:          {
  17:              return Array.ConvertAll( innerController.DependentServices, sc => ( new ServiceControllerWrapper( sc ) ) );
  18:          }
  19:      }
  20:   
  21:      public ServiceControllerWrapper()
  22:      {
  23:          innerController = new ServiceController();
  24:      }
  25:   
  26:      public ServiceControllerWrapper( string name )
  27:      {
  28:          innerController = new ServiceController( name );
  29:      }
  30:   
  31:      public ServiceControllerWrapper( string name, string machineName )
  32:      {
  33:          innerController = new ServiceController( name, machineName );
  34:      }
  35:   
  36:      public ServiceControllerWrapper( ServiceController innerController )
  37:      {
  38:          this.innerController = innerController;
  39:      }
  40:  }
 

So now we are done with the wrapper.

A Better Implementation

Since the service watcher does not bind to a service before the Start method is called, we cannot just inject our wrapper. Instead we must add something that enables us to create our wrapper at demand. So I have created a ServiceControllerWrapperFactory and of course an interface for it as well.

   1:  public interface IServiceControllerWrapperFactory
   2:  {
   3:      IServiceControllerWrapper Create( string name );
   4:  }
   5:   
   6:  public class ServiceControllerWrapperFactory : IServiceControllerWrapperFactory
   7:  {
   8:      public IServiceControllerWrapper Create( string name )
   9:      {
  10:          return new ServiceControllerWrapper( name );
  11:      }
  12:  }
 

Nothing special there, just a very simple factory, again I have left out parts of the interface as well as the implementation and only focused on the important parts, to give a brief note on what I have left out, it is create methods matching the constructors I defined on the wrapper implementation.

And now we are able to implement the ServiceWatcher using injection.

   1:  public class ServiceWatcher : IServiceWatcher
   2:  {
   3:      public event EventHandler<ServiceChangedEventArgs> ServiceChangedEvent;
   4:   
   5:      private Timer timer;
   6:      private ServiceControllerStatus lastStatus;
   7:      private IServiceControllerWrapper service;
   8:      private IServiceControllerWrapperFactory factory;
   9:   
  10:      public int UpdateInterval { get; set; }
  11:      public string ServiceName { get; set; }
  12:   
  13:      public ServiceWatcher( IServiceControllerWrapperFactory factory )
  14:      {
  15:          this.factory = factory;
  16:          UpdateInterval = 3000;
  17:      }
  18:   
  19:      public void Start()
  20:      {
  21:          service = factory.Create( ServiceName );
  22:          timer = new Timer( o => Update(), null, 0, UpdateInterval );
  23:      }
  24:   
  25:      public void Update()
  26:      {
  27:          service.Refresh();
  28:          ServiceControllerStatus newStatus = service.Status;
  29:          if ( newStatus != lastStatus )
  30:          {
  31:              OnServiceChangedEvent( new ServiceChangedEventArgs( newStatus ) );
  32:              lastStatus = newStatus;
  33:          }
  34:      }
  35:   
  36:      public void Dispose()
  37:      {
  38:          ...
  39:      }
  40:   
  41:      private void OnServiceChangedEvent( ServiceChangedEventArgs args )
  42:      {
  43:          if ( ServiceChangedEvent != null )
  44:          {
  45:              ServiceChangedEvent( this, args );
  46:          }
  47:      }
  48:  }

Testing our ServiceWatcher

So now we are able to actually unit test our ServiceWatcher using RhinoMocks and NUnit. (other mock frameworks and test frameworks can be used as well)

Here is an example of a test with a single test method.

   1:  [TestFixture]
   2:  public class ServiceWatcherTest
   3:  {
   4:      private MockRepository mocks;
   5:      private ServiceWatcher underTest;
   6:      private IServiceControllerWrapperFactory factoryMock;
   7:      private IServiceControllerWrapper serviceMock;
   8:   
   9:      [SetUp]
  10:      public void SetUp()
  11:      {
  12:          mocks = new MockRepository();
  13:          factoryMock = mocks.StrictMock<IServiceControllerWrapperFactory>();
  14:          serviceMock = mocks.StrictMock<IServiceControllerWrapper>();
  15:   
  16:          underTest = new ServiceWatcher( factoryMock );
  17:      }
  18:   
  19:      [TearDown]
  20:      public void TearDown()
  21:      {
  22:          mocks.BackToRecordAll();
  23:          underTest.Dispose();
  24:      }
  25:   
  26:      [Test]
  27:      public void TestStart()
  28:      {
  29:          mocks.Record();
  30:   
  31:          Expect.Call( factoryMock.Create( Arg<string>.Is.Equal( "ServiceName" ) ) ).Return( serviceMock );
  32:   
  33:          Expect.Call( serviceMock.Refresh );
  34:          Expect.Call( serviceMock.Status ).Return( ServiceControllerStatus.Running );
  35:   
  36:          mocks.ReplayAll();
  37:   
  38:          underTest.ServiceName = "ServiceName";
  39:          underTest.Start();
  40:   
  41:          mocks.VerifyAll();
  42:      }
  43:  }

As you see I chose to mock out both the factory and the wrapper, this is because these are not under test but the factory also needs to be mocked because our simple example of a factory would prevent us from mocking the wrapper.

Conclusion

And that's basically it, we now have a testable service watcher.
(Note that this is not my final implementation or my entire implementation, so there might miss some things)

This all may seem like it generates a huge overhead in both complexity and development, but after all we can now ensure some kind of quality in our ServiceWatcher.

In a hobby project this might be less relevant, especially for a person like me who doesn't generally test my hobby projects all that much. But if for nothing else. Then just for the fun of it.

Final Note: I Do apologize for any spelling errors or alike, first of English aren't my first language, secondly I'm currently very tired after a hard couple of (release) weeks at work

References:

ayende.com/projects/rhino-mocks.aspx
www.nunit.org/index.php