Install .NET Windows Service with a Different Name

Creating a Windows service in .NET could hardly be any easier. There's a template in Visual Studio which sets everything up and there's even a detailed walkthrough published on MSDN which leads you through the whole process from creating a new project to actually installing the service.

Installing multiple instances of such a service on a single computer is not that easy. You could do it by using Sc.exe instead of InstallUtil.exe, or you could modify the installer in your Windows service project to support configurable names. I prefer the latter approach, but there's not much documentation about it, which is probably the reason for many articles on the web describing over-complicated custom solutions instead of taking advantage of the APIs that are already available.

InstallUtil.exe has built-in support for passing the arguments to Windows service's Installer class. The Installer base class parses them and puts them in a handy StringDictionary, which can be accessed through InstallContext. This means, you can read these values inside your Installer and use them to change the default service name:

private void SetServiceName()
{
  if (Context.Parameters.ContainsKey("ServiceName"))
  {
    serviceInstaller1.ServiceName = Context.Parameters["ServiceName"];
  }

  if (Context.Parameters.ContainsKey("DisplayName"))
  {
    serviceInstaller1.DisplayName = Context.Parameters["DisplayName"];
  }
}

Of course, it's important, where this code is called from. If you try putting it in the class constructor, the installer will fail, because Context is not yet initialized. Fortunately the base class provides many virtual methods which you can override to get access to the Context after initialization. In our case we need to override OnBeforeInstall and OnBeforeUninstall:

protected override void OnBeforeInstall(IDictionary savedState)
{
  SetServiceName();
  base.OnBeforeInstall(savedState);
}

protected override void OnBeforeUninstall(IDictionary savedState)
{
  SetServiceName();
  base.OnBeforeUninstall(savedState);
}

The desired service name can now be passed as an argument to InstallUtil.exe:

installutil /ServiceName=A.Service /DisplayName="A Service" .\WindowsService1.exe

The same goes for uninstall:

installutil /u /ServiceName=A.Service .\WindowsService1.exe

To use the default name, the parameters can simply be omitted.

Copyright
Creative Commons License