Installing multiple instances of the same windows service on a server
Solution 1
Have you tried the sc / service controller util? Type
sc create
at a command line, and it will give you the help entry. I think I've done this in the past for Subversion and used this article as a reference:
http://svn.apache.org/repos/asf/subversion/trunk/notes/windows-service.txt
Solution 2
sc create [servicename] binpath= [path to your exe]
This solution worked for me.
Solution 3
You can run multiple versions of the same service by doing the following:
1) Copy the Service executable and config to its own folder.
2) Copy Install.Exe to the service executable folder (from .net framework folder)
3) Create a config file called Install.exe.config in the service executable folder with the following contents (unique service names):
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="ServiceName" value="The Service Name"/>
<add key="DisplayName" value="The Service Display Name"/>
</appSettings>
</configuration>
4) Create a batch file to install the service with the following contents:
REM Install
InstallUtil.exe YourService.exe
pause
5) While your there, create an uninstall batch file
REM Uninstall
InstallUtil.exe -u YourService.exe
pause
EDIT:
Note sure if I missed something, here is the ServiceInstaller Class (adjust as required):
using System.Configuration;
namespace Made4Print
{
partial class ServiceInstaller
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
private System.ServiceProcess.ServiceInstaller FileProcessingServiceInstaller;
private System.ServiceProcess.ServiceProcessInstaller FileProcessingServiceProcessInstaller;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.FileProcessingServiceInstaller = new System.ServiceProcess.ServiceInstaller();
this.FileProcessingServiceProcessInstaller = new System.ServiceProcess.ServiceProcessInstaller();
//
// FileProcessingServiceInstaller
//
this.FileProcessingServiceInstaller.ServiceName = ServiceName;
this.FileProcessingServiceInstaller.DisplayName = DisplayName;
//
// FileProcessingServiceProcessInstaller
//
this.FileProcessingServiceProcessInstaller.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
this.FileProcessingServiceProcessInstaller.Password = null;
this.FileProcessingServiceProcessInstaller.Username = null;
//
// ServiceInstaller
//
this.Installers.AddRange(new System.Configuration.Install.Installer[] { this.FileProcessingServiceInstaller, this.FileProcessingServiceProcessInstaller });
}
#endregion
private string ServiceName
{
get
{
return (ConfigurationManager.AppSettings["ServiceName"] == null ? "Made4PrintFileProcessingService" : ConfigurationManager.AppSettings["ServiceName"].ToString());
}
}
private string DisplayName
{
get
{
return (ConfigurationManager.AppSettings["DisplayName"] == null ? "Made4Print File Processing Service" : ConfigurationManager.AppSettings["DisplayName"].ToString());
}
}
}
}
Solution 4
Another quick way to specify a custom value for ServiceName
and DisplayName
is using installutil
command line parameters.
In your
ProjectInstaller
class override virtual methodsInstall(IDictionary stateSaver)
andUninstall(IDictionary savedState)
public override void Install(System.Collections.IDictionary stateSaver) { GetCustomServiceName(); base.Install(stateSaver); } public override void Uninstall(System.Collections.IDictionary savedState) { GetCustomServiceName(); base.Uninstall(savedState); } //Retrieve custom service name from installutil command line parameters private void GetCustomServiceName() { string customServiceName = Context.Parameters["servicename"]; if (!string.IsNullOrEmpty(customServiceName)) { serviceInstaller1.ServiceName = customServiceName; serviceInstaller1.DisplayName = customServiceName; } }
- Build your project
Install the service with
installutil
adding your custom name using/servicename
parameter:installutil.exe /servicename="CustomServiceName" "c:\pathToService\SrvcExecutable.exe"
Please note that if you do not specify /servicename
in the command line the service will be installed with ServiceName and DisplayName values specified in ProjectInstaller properties/config
Solution 5
Old question, I know, but I've had luck using the /servicename option on InstallUtil.exe. I don't see it listed in the built-in help though.
InstallUtil.exe /servicename="My Service" MyService.exe
I'm not entirely sure where I first read about this but I haven't seen it since. YMMV.
Related videos on Youtube
Switters
Updated on June 30, 2020Comments
-
Switters almost 4 years
So we've produced a windows service to feed data to our client application and everything is going great. The client has come up with a fun configuration request that requires two instances of this service running on the same server and configured to point at separate databases.
So far I haven't been able to get this to happen and was hoping my fellow stackoverflow members might be able to give some hints as to why.
Current setup:
I've set up the project that contains the windows service, we'll call it AppService from now on, and the ProjectInstaller.cs file that handles custom installation steps to set the service name based on a key in the App.config like so:
this.serviceInstaller1.ServiceName = Util.ServiceName; this.serviceInstaller1.DisplayName = Util.ServiceName; this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
In this case Util is just a static class tha tloads the service name from the config file.
From here forward I have tried two different ways to get both services installed and both have failed in an identical way.
The first way was to simply install the first copy of the service, copy the installed directory and renamed it, and then ran the following command after modifying the app config to change the desired service name:
InstallUtil.exe /i AppService.exe
When that didn't work I tried to create a second installer project, edited the config file and built the second installer. When I ran the installer it worked fine but the service did not show up in services.msc so I ran the previous command against the second installed code base.
Both times i received the following output from InstallUtil (relevant parts only):
Running a transacted installation.
Beginning the Install phase of the installation.
Installing service App Service Two... Service App Service Two has been successfully installed. Creating EventLog source App Service Two in log Application...
An exception occurred during the Install phase. System.NullReferenceException: Object reference not set to an instance of an object.
The Rollback phase of the installation is beginning.
Restoring event log to previous state for source App Service Two. Service App Service Two is being removed from the system... Service App Service Two was successfully removed from the system.
The Rollback phase completed successfully.
The transacted install has completed. The installation failed, and the rollback has been performed.
Sorry for the long winded post, wanted to make sure there is enough relevant information. The piece that so far has me stumped is that it states that the installation of the service completes successfully and its only after it goes to create the EventLog source that the NullReferenceException seems to get thrown. So if anyone knows what I'm doing wrong or has a better approach it would be much appreciated.
-
Switters almost 15 yearsI think what you are describing is more or less what I've done by allowing the ServiceName and DisplayName to be set from my services app.config I did attempt what you describe but unfortunately it resulted in the same issue listed in my question.
-
Mark Redman almost 15 yearsI kind of have a template I use, which I have used for ages, so maybe I missed something, what does your ServiceInstaller Class look like, will post a working copy of one I use, let me know i fthis helps?
-
Switters almost 15 yearsOur service installers are actually nearly identical. I use a static class to load the service and display names from the config file but other than that they are very similar. My guess as to why it isn't working for me is that there may be something a bit peculiar about our service code. A lot of hands have been on it unfortunately. From what I understand though, your answer should work in a majority of cases thanks for the help.
-
Vivian River over 14 yearsI found this page to be useful:
http://journalofasoftwaredev.wordpress.com/2008/07/16/multiple-instances-of-same-windows-service/
. You can insert code into the installer to get the service name that you want when you run installutil. -
NullReference over 11 yearsHuge help thanks. I think the install config file needs to be named InstallUtil.exe.confg not Install.exe.config for the InstallUtil.exe
-
STLDev about 10 yearsLink to wordpress blog has been changed to: journalofasoftwaredev.wordpress.com/2008/07
-
timmi4sa about 10 yearsA nice approach that totally works. That is if you know which InstallUtil.exe to copy to your installation folder (I personally have tons of framework versions installed which is exacerbated by the 64-bit copies). This would make it pretty difficult to explain to Helpdesk team if they do the installations. But for a developer-lead installation it is very elegant.
-
NovaJoe over 9 yearsHi Chris House! Stumbled across your answer because I'm building a self-hosted OWIN-based Web API around Quartz.NET scheduler and sticking it in a Windows Service. Pretty slick! Hoping you're well!
-
NovaJoe over 9 yearsHi Chris House! Stumbled across your answer because I'm building a self-hosted OWIN-based Web API around Quartz.NET scheduler and sticking it in a Windows Service. Pretty slick! Hoping you're well!
-
fizch almost 9 yearsI had to add this code to the project installer class, but it worked without issue.
-
mkb over 8 yearsReturns this error:
An exception occurred during the Install phase. System.ComponentModel.Win32Exception: The specified service already exists
-
mkb over 8 yearsjust to point out;
[path to your exe]
has to be full path and don't forget the space afterbinpath=
-
Jonathon Watney over 8 years@mkb Do you have a another service called "My Service"?
-
mkb over 8 yearsYes, as in the question I have one service, same executable, but I want to install two instances of it, each with different config. I copy-paste the service exe but this one didn't work.
-
Teoman shipahi about 8 yearsConfigurationManager.AppSettings["ServiceName"] always returns null for me even if I set them under app.config. Any idea why? If I debug project it reads it but if I run from serviceutil it always sets service name as default value. (hardcoded one)
-
Noel Widmer almost 8 yearsThis does indeed allow a service to be installed multiple times. However, all the information provided by the service installer. F.e. description, logon type etc. is ignored
-
granadaCoder over 7 years/servicename="My Service InstanceOne" and /servicename="My Service InstanceTwo" The names have to be unique.
-
Iofacture over 5 yearsBrilliant!! Thank you - this was exactly what was needed and to the point.
-
Balagurunathan Marimuthu over 5 years@MarkRedman Uninstalling and reinstalling windows service causes an error as "Error:1001 The specified service already exists." How to resolve this?
-
Mark Redman over 5 years@BalagurunathanMarimuthu You will need to uninstall the service first, before re-installing it again.
-
Mark Redman over 5 yearsAre you sure it's removed from the Services console? you can also try: sc delete <Service_Name> and see if that works?
-
Balagurunathan Marimuthu over 5 years@MarkRedman Yes, I have checked in Service console, sc delete, regedit, installation path, etc., but, it not working...
-
Mark Redman over 5 years@BalagurunathanMarimuthu: Not being funny, but have you tried rebooting? sometimes services can get disabled until reboot? Might help?
-
Balagurunathan Marimuthu over 5 years@MarkRedman It works after sometimes without made any changes in the system. Thanks for your solution.
-
Balagurunathan Marimuthu over 5 years@MarkRedman Is it possible to install windows service as multiple instance of same window service through installer package? Here, I need to create two different desktop shortcut with two different name.. and, above approach doesn't make any entry in "programs & Features". Hence, my windows service also has windows application which needs to be a copy for each instance of service installed.
-
Mark Redman over 5 years@BalagurunathanMarimuthu Yes you can install the same service multiple times, you will need to change the service name and description.. ideally you would have these in different folders depending on your configuration, check that there is no conflict in what your service is doing.
-
progLearner over 4 yearsThat is great, but that is just for the installer. Once you have a new instance name, how will the Windows service know about this new name? Do you have to pass it on at construction of the Windows service?
-
tristankoffee over 4 yearsThanks! The installer will set the name on the Windows Service while it's installing it using the values set in the SetNames() method above.
-
progLearner over 4 yearsSure, but how can you set this name from the outside world?
-
tristankoffee over 4 yearsIn my answer is the command used on the command line to install (and uninstall) the service in the outside world. The value you pass into
/ServiceSuffix="UAT"
is used by the installer to set the suffix on the service. In my example, the value passed in isUAT
. In my scenario I just wanted to add a suffix onto the existing name of the service, but there's no reason you couldn't adapt this to replace the name entirely with the value that's passed in. -
progLearner over 4 yearsThanks, but that is a command line input (= manual input), not code. As per original question: Once you have a new instance name, how will the Windows service know about this new name? Do you have to pass it on at construction of the Windows service?
-
tristankoffee over 4 yearsI'm not sure I understand what problem it is you're trying to solve. The original question was about how to install the same windows service twice on the same machine - the OP was having a problem when installing the same service from the command line from two different locations - this was failing because both services would have the same name which Windows didn't like. My answer demonstrates how to fix that by passing in a parameter into the installer from the command line to set different names. It sounds like you're trying to do something else and I'm not clear what - could you explain?
-
progLearner over 4 yearsThanks @tristankoffee. It is just that you answer is incomplete in the sense that passing a name to the installer does not make the service work with that instance name by magic :-) I had to pass that instance name to my Windows service constructor (withing the installer) so that the system actually knows about and is able to refer/use that specific service instance. Otherwise, it won't work. Unless you have another idea on how to do it, which is what I asked for since I was not sure it was the best way to do it :-)
-
tristankoffee over 4 years@progLearner - unfortunately I wrote this answer almost 4 years ago and don't have access to the original code and can't remember how you would go about hooking up the service name with the installer, so I'm sorry I can't help you with that. Likely, as the OP referenced the installer code already, I removed the superfluous code for brevity. Good luck with your project.
-
progLearner over 4 yearsI understand and appreciate you tried, thank you anyway :-) +1 on you original answer
-
Hermetism about 2 yearsThis is the actual answer to the question.