22

I've created a Windows service in C#, installed it on a server and it is running fine.

Now I want to install the same service again, but running from a different working directory, having a different config file etc. Thus, I would like to have two (or more) instances of the same service running simultaneously. Initially, this isn't possible since the installer will complain that there's already a service with the given name installed.

I can overcome this by changing my code, setting the ServiceBase.ServiceName property to a new value, then recompiling and running InstallUtil.exe again. However, I would much prefer if I could set the service name at install-time, i.e. ideally I would do something like

InstallUtil.exe /i /servicename="MyService Instance 2" MyService.exe

If this isn't achievable (I very much doubt it), I would like to be able to inject the service name when I build the service. I thought it might be possible to use some sort of build event, use a clever msbuild or nant trick or something along those lines, but I haven't got a clue.

Any suggestions would be greatly appreciated.

Thank you for your time.

Rune
  • 8,340
  • 3
  • 34
  • 47
  • 1
    Is there a reason you haven't given your service the abbility to execute the business logic in n-threads for n-config files? Thus saving the multiple instances issue from the start? – Nate May 07 '09 at 15:50
  • Hmmm, that might be a good point. But the service was created a year ago, way before I realized that I would like to be able to run multiple instances, so the application isn't really architected appropriately. However, I've found a solution and will post it in a sec. – Rune May 07 '09 at 19:49

3 Answers3

29

I tried accessing a configuration using

ConfigurationManager.OpenExeConfiguration(string exePath)

in the installer, but couldn't get it to work.

Instead I decided to use System.Environment.GetCommandLineArgs() in the installer like this:

string[] commandlineArgs = Environment.GetCommandLineArgs();

string servicename;
string servicedisplayname;
ParseServiceNameSwitches(
    commandlineArgs, 
    out servicename, 
    out servicedisplayname);

serviceInstaller.ServiceName = servicename;
serviceInstaller.DisplayName = servicedisplayname;

Now I can install my services using

InstallUtil.exe /i InstallableService.dll /servicename="myserviceinstance_2" /servicedisplayname="My Service Instance 2"

I wrote up a more elaborate explanation here.

Rune
  • 8,340
  • 3
  • 34
  • 47
  • Look at question and answer to get perfect solution for this: http://stackoverflow.com/questions/8516701/how-to-get-windows-service-name-from-app-config – techExplorer Feb 17 '16 at 13:06
  • Please could you post your "more elaborate explanation" somewhere? Your link doesn't work and I'd like to read it – cja Sep 19 '19 at 17:44
4

You can't pass this in as a command line arg, since InstallUtil doesn't provide the right hooks for that.

However, you can make your service installer read the ServiceName from a config file. If you look at some code for a typical ServiceInstaller, you'll see it's just a matter of having the appropriate DisplayName and ServiceName properties setup at runtime. These could easily be read from a configuration file instead of being hard-coded.

Markus Jarderot
  • 86,735
  • 21
  • 136
  • 138
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • Really? I've tried reading these values from the ServiceExeName.config file during installation of the windows service and it didn't work :( – Darragh Feb 07 '11 at 10:06
2

Instead of using Environment.GetCommandLineArgs(); the class Installer has a property called Context from which you can access command line arguments passed to InstallUtil structured in a nice StringDictionary.

Arthur Rizzo
  • 333
  • 1
  • 7