Creating Windows Service quite often comes as natural choice when some long-term task needs to be done or, god forbid, you need something running while there is nobody to log on. Although services are useful, there are two things that annoy me and they are just too non-obvious to do. One is debugging services and another one is installing them.
For quite a while I've been using installutil.exe in order to install services. Since I am fan of being able to put things on system without actually installing them, that meant that I went through hoops to write C# code which will find installutil.exe in all it's possible locations, under any combination of service packs and then to parse output once it gets executed.
I am not proud that it took me literally years to get idea to open installutil.exe in Reflector. And there, under whole glory, there was single function that does everything. And to make things even better parameters for this function are same as parameters for installutil.exe itself.
In order to install service, it is enough to pass name of executable (executing assembly in this example) and magic will happen:
ManagedInstallerClass.InstallHelper(new string[] { Assembly.GetExecutingAssembly().Location });
Uninstall is same story. Additional "unistall" (or "u") flag is all it takes:
ManagedInstallerClass.InstallHelper(new string[] { "/u", Assembly.GetExecutingAssembly().Location });
Design of whole thing leaves lot to be desired. It just doesn't feel like .NET - it feels like whole thing was pushed in after somebody noticed that there is no installer and there are only 2 hours before final version of .NET comes out.
One could get into refactoring whole thing out and making "proper" installer without too much effort. However, personally I will not do it. Although this function annoys me, I am also assured that Microsoft takes care of testing it and that it will work on every supported version of .NET Framework on every supported platform. Services are difficult enough without risking installation issues on some obscure combination.
Things that are not (badly) broken should not be fixed.
P.S. Not to forget, you need reference to System.Configuration.Install.dll in your program.
When I try to use Installhelper it will install but not start when I go to services -> right click – > press start. My service will work perfectly if I use InstallUtil.exe. The error I get with installhelper is that it did not start in a timely fashion. Have any idea on what I did wrong? I’m running 64 bit Windows 7
Try whether this code works for you.
That works nicely. Thanks for the tip. Question: Why can’t I just put ManagedInstallerClass.InstallHelper(new string[] { assembly.GetExecutingAssembly().Location }); instead of that big if-else block. When I just put ManagedInstallerClass.InstallHelper(new string[] { Assembly.GetExecutingAssembly().Location }); it installs fine, but I’ll still get the timely fashion error.
You can. Big “if block” is just to ensure that you get install behaviour only when you want it and not whenever application is (maybe accidentally) run.
As far as starting service goes, I found that installer class is a good place to put such code, e.g. in OnCommited event handler. You can see example of such implementation in another application of mine at BitBucket.
Oh, okay. Then how can I run the exe (as admin) so that it installs and i can run the service? Right now it installs but when i try to start it I get the Timely Fashion error again.
This Timely Fashion error is not related to install. This error is usually triggered by non-threaded (or just slow) code in your overriden ServiceBase methods.
Thank you for all your help!