sept. 25

We have seen previously how to create and deploy a windows service (here and here using a separate installer DLL). What we have seen also is that we can control the start type of the service to specify whether it will be launched manually or automatically. This is very interesting, however this will be used internally by windows only at the next startup of the operating system.

It seems very logical that if we install a service and that we want it to start in an "automatic way", this service shall be running at the end of the installation process, and this without any manual action. We can do this in a very easy way via the installer (I will start again from the previous installer DLL we have created in this post).

Updating the installer

We will need to work at the end of the installation, ie on the "Commit" event. To do so :

  • Right-Click on the setup project and choose "View / Custom Actions"
  • Right-Click on the "Commit" event and choose "Add Custom Action"
  • Choose the "Primary Output from MyWindowsServiceInstallerActions" (from the Application Folder) and click OK

Now our installer DLL will also get called when the commit is occuring.

Starting the event

We can now update the installer class as follows :

using System.Collections;
using System.ComponentModel;
using System.Configuration.Install;
using System.IO;
using System.ServiceProcess;
 
namespace MyWindowsServiceInstallerActions
{
   [RunInstaller(true)]
   public partial class MyInstaller : Installer
   {
      //Other implementation remained unchanged, and so ommited here
 
      protected override void OnCommitted(IDictionary savedState)
      {
         base.OnCommitted(savedState);
 
         ServiceController service = new ServiceController("MyPersonalService");
         service.Start();
      }
   }
}

Some explanation about the code :

  • We could have decided to do the same treatment on the "Commit" event
  • The ServiceController class let's us manipulate a service (based on the service name, as set in the constructor of the service)
  • If for any reason, the "Start" method doesn't work (problem in the service, event log full, ...) an exception will get raised, and so the installation will fail and rollback.

A more secure implementation would be something like (you must of course include a reference to System.WindowsForms.dll if you want to use the MessageBox class) :

protected override void OnCommitted(IDictionary savedState)
{
   base.OnCommitted(savedState);
 
   ServiceController service = new ServiceController("MyPersonalService");
   string errorMessage = string.Format("Could not start the service {0}. You should launch it manually"
                                       service.DisplayName);
 
   //We'll try starting the service only if not started yet
   if ( service.Status == ServiceControllerStatus.Stopped )
   {
      try
      {
         service.Start();
         //Let's wait (for max 10 seconds) that this service is running
         service.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 10));
      }
      catch ( InvalidOperationException )
      {
         //The Start method failed
         MessageBox.Show(errorMessage);
      }
      catch ( System.ServiceProcess.TimeoutException )
      {
         //The Start method succeeded, but after 10 seconds, the service was still not running
         MessageBox.Show(errorMessage);
      }
   }
}
Note that we use the fully qualified name for the TimeOutException not to have any ambiguity with the same exception in the System namespace.

Ajouter un commentaire




biuquote
  • Commentaire
  • Aperçu immédiat
Loading