Dynamic Windows Service – Dynamic Name, Dynamic Configuration
If customers knew all technology, there would have been no innovation. Since customers don’t know technology, they keep asking for things which we generally think not possible, but once they ask we get in the research and proof-of-concepts and finally find that yes it is Possible!!
Dynamic Windows Service was one such area for me. ONE single EXE and Multiple Installations and all with Different Names and Configuration. Yes possible!!
The problem:
I had to give one single EXE to my clients and another installer EXE which could multiple install the same EXE all with different names and configurations.
This was easy but the real problem was Service Installer was able to install my windows service with different names, but when I use to start my service, (from with in service EXE) it had no clues which instance was started and thus ran with its default name. Now if it ran with the default name, I cannot read different configurations, since I don’t know which instance is running.
The Solutions:
Solution Number 1:
My Service EXE name is: oneservice.exe
I use installutil.exe to install it. I got to .NET Command prompt and type:
installutil oneservice.exe
This would always take ONE name, the default one and thus will do ONE EXE ONE SERVICE installation.
Result: Not dynamic at all.
Solution Number 2:
Modify your Project Installer Class in order to add a parameter during installation which would take the service name and install the service with this name.
How? Here it is:
In your ProjectInstaller_OnBeforeInstall
and
ProjectInstaller_OnBeforeUnInstall
use
this.Context.Parameters["SName"]
to read the command line parameters of installutil
and accordingly assign it to ServiceName.
Write this one line in your service OnStart Method
System.Diagnostics.EventLog.WriteEntry("Hi from Service: "+ this.ServiceName, this.ServiceName);
Again use installutil.exe and supply values to the parameter:
installutil /SName=FirstService oneservice.exe
installutil /SName=SecondService oneservice.exe
Now, once the service is started, goto the Services console (services.msc) and start both the services.
Now go to Event Viewer to check the Event Entry and you will find that both the entries say “Hi from Service: Service1″.
Oops! I named them as FirstService and SecondService respectively but here it is not reflected. What happened?
Understand this, ProjectInstaller class just assigns a “install time” name to the service and not the “run-time” name. So even if to people it looks two different services, to it self its the two services with the same name. If you do not plan to use different configurations and just want two different instance to run simultaneously, this should be your solution. For others, please read on.
Result: Dynamic to some extent, but not fully.
Solution Number 3:
Modify the Project Installer class to read the ServiceName from a configuration file.
Modify the Service to read the ServiceName from the same configuration file.
use installutil again
installutil oneservice.exe
[Internally it will read ServiceName from Configuration file and install a different named service]
The problem with this one is: since you have ServiceName in configuration file, you have keep as many copies of EXEs in multiple folders as many services you want because once the service reads one file it acquires a name and if it reads another it converts to another.
Result: Pretty Dynamic but not what we want, as we want to keep a single EXE only.
Solution Number 4:
Now if you want a Solution Number 3 with Single EXE what you should. You should make your service some how read the name of the instance. How? Can we pass on a parameter to our Main Method and that parameter would be the ServiceName. Yes, this looks like the solution.
So when you start your service, you supply the parameter
oneservice.exe FirstService
Read this args[0] and assign it to the ServiceName. Yes this is the solution, but wait, how will you achieve this with installutil. Remember this is the one we always use for installing services. Probing installutil with the following command
installutil /SName=FisrtService oneservice.exe FirstService
or
installutil /SName=FirstService "oneservice.exe FirstService"
returned me errors saying that it was not able to find FirstService file in the current directory.
Now, I thought that my Solution Number 1, 2 and 3 didn’t worked and what they have in common is installutil, so I finally figured out that its the installutil which is stopping me from becoming dynamic and not my own service.
So I finally settled down to use sc.exe [Service Controller]
Its pretty simple and straight forward and not need to even modify the ProjectInstaller code.
Just use the following command
sc create FirstService binPath= "c:\OneService.exe FirstService"
and see your services console. The name of the service reads FirstService
Start your service and see your Event Viewer it reads “Hi from Service: First Service”
To remove use:
sc delete FirstService
Ah! Finally we have found the solution.
Result: Totally Dynamic!!
So until some one suggests me a better method, I will be using Solution number 4 for writing fully dynamic services.
Dynamic Configuration:
You can have one configuration per instance of the service with the name of the service itself. So your config file names would be FirstService.xml.
In your service OnStart method
read the configuration file as
string configFile = this.ServiceName + ".xml";
and then read the further values as you would read any XML file and start your service to work accordingly.
Cheers!!


