The standard way of installing Windows services using the Visual Studio Windows Service project and the InstallUtil.exe tool does not allow the user to specify the service name after the project has been compiled. This is problematic if you want to install two or more instances of a Windows service on the same computer. So in this post I propose a way to achieve this without much effort.
The procedure consists of the steps described below. I’ll assume that you already have a Visual Studio project and you want to extend it with the multiple instance support:
1. Add a new XML file named App.InstallConfig.xml to your project. It should contain the following XML code:
<installconfig>
<servicename>My Service Name</servicename>
</installconfig>
2. Add a post-build step to the project:
copy $(ProjectDir)App.InstallConfig.xml $(TargetPath).InstallConfig.xml
This will copy the installation configuration file from the project directory to the target and will replace the ‘App’ name with the name of your project’s assembly.
3. Add a new private method to the main (project) installer class:
private void ConfigureInstaller
()
{
// find the install configuration file
string assemblyLocation = Assembly.
GetExecutingAssembly ().
Location;
string installConfigFile = assemblyLocation +
".InstallConfig.xml";
// now load the file and parse it
XmlDocument xmlDoc = new XmlDocument ();
xmlDoc.Load (installConfigFile);
XmlNode serviceNameNode = xmlDoc.SelectSingleNode ("InstallConfig/ServiceName");
if (serviceNameNode != null)
{
string serviceName = serviceNameNode.InnerText.Trim ();
this.ListenerServiceInstaller.ServiceName = serviceName;
}
}
This method opens the mentioned configuration file and reads the InstallConfig/ServiceName setting which should contain the actual name of the Windows service instance. It uses this name to set the ServiceInstaller.ServiceName before the installation is initiated.
4. And finally, add the call of the ConfigureInstaller() method to the project installer constructor, like this:
public ProjectInstaller()
{
// This call is required by the Designer.
InitializeComponent();
ConfigureInstaller ();
}
NOTE: replace the name of the ProjectInstaller constructor with your own class name.
This should be it. To install the service under the desired name, you just edit the .InstallConfig.xml file before calling the InstallUtil tool.
Extending this further
You can use the same system to include some other Windows service parameters (like the user account under which it will run, for example). The installer class provided by the .NET Framework does not allow setting the Windows service’s description, but there is a way to do this (see the “Adding a description to a .NET Windows Service” article on CodeProject). Then you can add the description tag in the .InstallConfig.xml file and have a different description for each of the service instances.
Also check out the “Windows Services Can Install Themselves” article on how to create self-installing Windows services (be sure to read the article’s comments, they contain some additional tips).