Installing multiple instances of the same windows service on a server

106,450

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.

  1. In your ProjectInstaller class override virtual methods Install(IDictionary stateSaver) and Uninstall(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;
        }
    }
    
  2. Build your project
  3. 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.

Share:
106,450

Related videos on Youtube

Switters
Author by

Switters

Updated on June 30, 2020

Comments

  • Switters
    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
    Switters almost 15 years
    I 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
    Mark Redman almost 15 years
    I 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
    Switters almost 15 years
    Our 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
    Vivian River over 14 years
    I found this page to be useful: http://journalofasoftwaredev.wordpress.com/2008/07/16/multip‌​le-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
    NullReference over 11 years
    Huge help thanks. I think the install config file needs to be named InstallUtil.exe.confg not Install.exe.config for the InstallUtil.exe
  • STLDev
    STLDev about 10 years
    Link to wordpress blog has been changed to: journalofasoftwaredev.wordpress.com/2008/07
  • timmi4sa
    timmi4sa about 10 years
    A 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
    NovaJoe over 9 years
    Hi 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
    NovaJoe over 9 years
    Hi 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
    fizch almost 9 years
    I had to add this code to the project installer class, but it worked without issue.
  • mkb
    mkb over 8 years
    Returns this error: An exception occurred during the Install phase. System.ComponentModel.Win32Exception: The specified service already exists
  • mkb
    mkb over 8 years
    just to point out; [path to your exe] has to be full path and don't forget the space after binpath=
  • Jonathon Watney
    Jonathon Watney over 8 years
    @mkb Do you have a another service called "My Service"?
  • mkb
    mkb over 8 years
    Yes, 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
    Teoman shipahi about 8 years
    ConfigurationManager.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
    Noel Widmer almost 8 years
    This 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
    granadaCoder over 7 years
    /servicename="My Service InstanceOne" and /servicename="My Service InstanceTwo" The names have to be unique.
  • Iofacture
    Iofacture over 5 years
    Brilliant!! Thank you - this was exactly what was needed and to the point.
  • Balagurunathan Marimuthu
    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
    Mark Redman over 5 years
    @BalagurunathanMarimuthu You will need to uninstall the service first, before re-installing it again.
  • Mark Redman
    Mark Redman over 5 years
    Are you sure it's removed from the Services console? you can also try: sc delete <Service_Name> and see if that works?
  • Balagurunathan Marimuthu
    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
    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
    Balagurunathan Marimuthu over 5 years
    @MarkRedman It works after sometimes without made any changes in the system. Thanks for your solution.
  • Balagurunathan Marimuthu
    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
    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
    progLearner over 4 years
    That 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
    tristankoffee over 4 years
    Thanks! 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
    progLearner over 4 years
    Sure, but how can you set this name from the outside world?
  • tristankoffee
    tristankoffee over 4 years
    In 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 is UAT. 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
    progLearner over 4 years
    Thanks, 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
    tristankoffee over 4 years
    I'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
    progLearner over 4 years
    Thanks @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
    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
    progLearner over 4 years
    I understand and appreciate you tried, thank you anyway :-) +1 on you original answer
  • Hermetism
    Hermetism about 2 years
    This is the actual answer to the question.