Click here to Skip to main content
11,412,516 members (72,457 online)
Click here to Skip to main content

Windows Services Can Install Themselves

, 22 Nov 2007 CPOL
Rate this:
Please Sign up or sign in to vote.
Never use the InstallUtil.exe utility that ships with the .NET SDK again.

Introduction

Using the InstallUtil.exe utility that ships with the .NET SDK can be a real pain. It's rarely in the PATH so you probably have to hunt down the utility when you are working on QA and production servers as I do. Installing a Windows Service should be easier. In this short article, I'll show you a way to make your Windows Services install themselves without needing InstallUtil.exe at all.

Assumptions

Let's assume that your service project has a service installer, a service process installer and a class derived from System.Configuration.Install.Installer already. If not, check out Mahmoud Nasr's excellent article on Windows Service development, then come back here.

Key Information

Thanks to Reflector for .NET by Lutz Roeder, it's easy to discover how the InstallUtil.exe utility does its job. After some setup, the InstallUtil.exe tool jumps to a method called InstallHelper in the ManagedInstallerClass in the System.Configuration.Install namespace. And what's really interesting is that the command line arguments passed to InstallUtil.exe as an array of strings are then passed directly to this helper method.

Well, this made me think, "If all InstallUtil.exe does is call the ManagedInstallerClass' InstallHelper method, why can't my service executable do the same thing to install itself on command?" The little class below makes it simple to do just that.

Using the Code

Create a new CS file in your service executable project containing the following code. You may also need to add a reference to the System.Configuration.Install.dll from the Global Assembly Cache if you don't already have one.

using System.Reflection;
using System.Configuration.Install;

namespace gotnet.biz.Utilities.WindowsServices
{
    public static class SelfInstaller
    {
        private static readonly string _exePath =
            Assembly.GetExecutingAssembly().Location;
        public static bool InstallMe()
        {
            try
            {
                ManagedInstallerClass.InstallHelper(
                    new string[] { _exePath } );
            }
            catch
            {
                return false;
            }
            return true;
        }

        public static bool UninstallMe()
        {
            try
            {
                ManagedInstallerClass.InstallHelper(
                    new string[] { "/u", _exePath } );
            }
            catch
            {
                return false;
            }
            return true;
        }
    }
}

Now you need to come up with some sort of convention for knowing when to invoke the installer. Below is just an example of how you might handle this in your Main() method, the entry point to your service. I like the convention of using -i or -install parameters to install the service and -u or -uninstall to uninstall it. I also like to use -c or -console to mean starting the application in a console rather than as a service. However, that's a topic for a different article.

using gotnet.biz.Utilities.WindowsServices;

namespace MyService.WinHost
{
    static class Program
    {
        public static void Main( string[] args )
        {
            if (args != null && args.Length == 1 && args[0].Length > 1
                && (args[0][0] == '-' || args[0][0] == '/'))
            {
                switch (args[0].Substring( 1 ).ToLower())
                {
                    default:
                        break;
                    case "install":
                    case "i":
                        SelfInstaller.InstallMe();
                        break;
                    case "uninstall":
                    case "u":
                        SelfInstaller.UninstallMe();
                        break;
                    case "console":
                    case "c":
                        MyConsoleHost.Launch();
                        break;
                }
            }
            else
                MyWinServiceHost.Launch();
        }
    }
}

Now, assuming my executable is named MyWinSvcHost.exe, I can invoke the installer by running:

C:\> MyWinSvcHost.exe -install

Or to uninstall my service, I would use this:

C:\> MyWinSvcHost.exe -uninstall

Other Ideas

This little bit of code called the SelfInstaller is full of possibilities. You could pass parameters to the InstallMe method to pass on to the ServiceProcessInstaller in your program, for example. Perhaps the domain name, user name and password used to start your service could be passed all the way from your Main() method to the ServiceProcessInstaller. Cool, right? I thought you would like that.

History

  • 22 Nov, 2007 - Initial publication

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

W. Kevin Hazzard
Web Developer
United States United States
After 16 years as an ardent C++ aficionado, Kevin switched to C# in 2001. Recently, Kevin's been dabbling in dynamically typed languages. Kevin is the Software Architect for Snagajob.com, the #1 source for hourly and part-time employment on the web.

Kevin loves welding, riding motorcycles and spending time with his family. Kevin has also been an adjunct professor teaching software engineering topics at a college in his hometown of Richmond, Virginia since 2000. Check out Kevin's technical blog at www.gotnet.biz for more goodies.

Comments and Discussions

 
Questionwill it install without using newer version of installutil .exe incase our windows service is built in newer version only if latest client profile and runtime is intalled. Pin
ShabanaParveen at 4-Dec-12 22:42
memberShabanaParveen4-Dec-12 22:42 
QuestionInstall two services from the same assembly Pin
P. de Jong at 30-Aug-11 5:23
memberP. de Jong30-Aug-11 5:23 
GeneralService Template Pin
Steve Foster (Havok Multimedia) at 26-Sep-10 12:09
memberSteve Foster (Havok Multimedia)26-Sep-10 12:09 
GeneralRe: Service Template Pin
ComplexityChaos at 14-Oct-10 7:26
memberComplexityChaos14-Oct-10 7:26 
GeneralRe: Service Template Pin
Steven D. Foster at 15-Oct-10 6:05
memberSteven D. Foster15-Oct-10 6:05 
GeneralNice but Pin
Giorgi Dalakishvili at 6-Mar-10 11:18
mentorGiorgi Dalakishvili6-Mar-10 11:18 
Questionhow do i get the service name from another exe Pin
jbencic at 19-Dec-09 16:56
memberjbencic19-Dec-09 16:56 
QuestionError 1053: The service did not respond to the start or control request in a timely fashion. Pin
khayyam22 at 1-Sep-09 21:15
memberkhayyam221-Sep-09 21:15 
GeneralTwo lines are confusing me please help Pin
khayyam22 at 1-Sep-09 21:11
memberkhayyam221-Sep-09 21:11 
GeneralConfused Steps Pin
khayyam22 at 1-Sep-09 8:50
memberkhayyam221-Sep-09 8:50 
GeneralDifferent Solution Pin
David Hoyt at 13-Aug-09 7:56
memberDavid Hoyt13-Aug-09 7:56 
Generalno console output Pin
rapid2k2 at 11-Aug-09 16:52
memberrapid2k211-Aug-09 16:52 
GeneralRe: no console output Pin
Erik Burger at 29-Jul-10 2:50
memberErik Burger29-Jul-10 2:50 
GeneralAwesome! GUI and CLI! Pin
Bit-Smacker at 3-Aug-09 10:39
memberBit-Smacker3-Aug-09 10:39 
GeneralManagedInstallerClass doesn't work to me Pin
Bizancio Spirit at 9-Jun-09 5:10
memberBizancio Spirit9-Jun-09 5:10 
I have a problem Frown | :( I can install a Windows service by InstallUtil but I can't do it when I try to do it with ManagerInstallerClass. It's strange, I reflected the Code (is the same that InstallUtil) and it doesn't work. Context data? This is My Code:

static void Main(string[] args)
{
string path = @"";

MainK(new string[] { path });
}

public static int MainK(string[] args)
{
Thread.CurrentThread.CurrentUICulture = CultureInfo.CurrentUICulture.GetConsoleFallbackUICulture();
if (((Console.OutputEncoding.CodePage != 0xfde9) && (Console.OutputEncoding.CodePage != Thread.CurrentThread.CurrentUICulture.TextInfo.OEMCodePage)) && (Console.OutputEncoding.CodePage != Thread.CurrentThread.CurrentUICulture.TextInfo.ANSICodePage))
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
}
Assembly.GetEntryAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), true);
try
{
ManagedInstallerClass.InstallHelper(args);
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
return -1;
}
return 0;
}
GeneralAwesome post, thanks. Always wanted to know how that was done. Pin
Buddy Stein at 1-Apr-09 8:11
memberBuddy Stein1-Apr-09 8:11 
GeneralInstallHelper Doesn't release Service1.exe file after uninstall Pin
surf uk at 22-Jan-09 3:55
membersurf uk22-Jan-09 3:55 
GeneralRe: InstallHelper Doesn't release Service1.exe file after uninstall Pin
HJG007 at 6-Feb-09 2:27
memberHJG0076-Feb-09 2:27 
GeneralRe: InstallHelper Doesn't release Service1.exe file after uninstall Pin
Veener at 29-Apr-09 14:56
memberVeener29-Apr-09 14:56 
General[Message Removed] Pin
Katekortez at 25-Oct-08 10:30
memberKatekortez25-Oct-08 10:30 
QuestionSetting ServiceProcessInstaller attributes Pin
Chris Newton at 28-May-08 3:45
memberChris Newton28-May-08 3:45 
GeneralFor the console lovers ;-) Pin
Aleksei Nickolayev at 3-Mar-08 5:06
memberAleksei Nickolayev3-Mar-08 5:06 
GeneralRe: For the console lovers ;-) Pin
W. Kevin Hazzard at 6-Mar-08 7:51
memberW. Kevin Hazzard6-Mar-08 7:51 
GeneralGreat article Pin
srinath g nath at 30-Dec-07 19:09
membersrinath g nath30-Dec-07 19:09 
GeneralInstall on first run [modified] Pin
Ashley van Gerven at 21-Dec-07 18:55
memberAshley van Gerven21-Dec-07 18:55 
GeneralRe: Install on first run Pin
W. Kevin Hazzard at 26-Dec-07 4:54
memberW. Kevin Hazzard26-Dec-07 4:54 
GeneralRe: Install on first run Pin
Ashley van Gerven at 26-Dec-07 5:13
memberAshley van Gerven26-Dec-07 5:13 
GeneralCan't start service. Pin
Ricky at 27-Nov-07 15:09
memberRicky27-Nov-07 15:09 
GeneralRe: Can't start service. Pin
W. Kevin Hazzard at 29-Nov-07 11:00
memberW. Kevin Hazzard29-Nov-07 11:00 
GeneralRe: Can't start service. Pin
Ricky at 30-Nov-07 13:44
memberRicky30-Nov-07 13:44 
GeneralRe: Can't start service. Pin
Ricky at 30-Nov-07 13:54
memberRicky30-Nov-07 13:54 
GeneralI took a different tack [modified] Pin
PIEBALDconsult at 26-Nov-07 17:12
memberPIEBALDconsult26-Nov-07 17:12 
GeneralRe: I took a different tack Pin
cplas at 14-Jan-09 15:04
membercplas14-Jan-09 15:04 
GeneralYou can go further (an alternative approach) Pin
Oleg Shilo at 26-Nov-07 16:18
memberOleg Shilo26-Nov-07 16:18 
GeneralRe: You can go further (an alternative approach) Pin
tag2001 at 26-Nov-07 19:24
membertag200126-Nov-07 19:24 
GeneralRe: You can go further (an alternative approach) Pin
Oleg Shilo at 26-Nov-07 19:41
memberOleg Shilo26-Nov-07 19:41 
GeneralRe: You can go further (an alternative approach) Pin
One Smart Motor Scooter at 27-Nov-07 7:46
memberOne Smart Motor Scooter27-Nov-07 7:46 
GeneralRe: You can go further (an alternative approach) Pin
W. Kevin Hazzard at 29-Nov-07 10:55
memberW. Kevin Hazzard29-Nov-07 10:55 
GeneralDoesn't seem to work for me Pin
smesser at 23-Nov-07 21:49
membersmesser23-Nov-07 21:49 
GeneralRe: Doesn't seem to work for me Pin
W. Kevin Hazzard at 24-Nov-07 5:21
memberW. Kevin Hazzard24-Nov-07 5:21 
GeneralRe: Doesn't seem to work for me [modified] Pin
smesser at 24-Nov-07 5:36
membersmesser24-Nov-07 5:36 
GeneralRe: Doesn't seem to work for me Pin
W. Kevin Hazzard at 24-Nov-07 6:24
memberW. Kevin Hazzard24-Nov-07 6:24 
GeneralRe: Doesn't seem to work for me Pin
smesser at 24-Nov-07 7:08
membersmesser24-Nov-07 7:08 
GeneralIndispensable Pin
munenedumunenedu at 23-Nov-07 6:17
membermunenedumunenedu23-Nov-07 6:17 
GeneralExcellent! Pin
T1TAN at 23-Nov-07 1:23
memberT1TAN23-Nov-07 1:23 
GeneralJust like Delphi does it. Pin
stensones at 23-Nov-07 0:33
memberstensones23-Nov-07 0:33 
GeneralExcellent article!!! Pin
ndinges at 22-Nov-07 23:52
memberndinges22-Nov-07 23:52 
GeneralGreat Article Pin
Cool Dirty Boy at 22-Nov-07 22:48
memberCool Dirty Boy22-Nov-07 22:48 
GeneralGreat article Pin
NikoTanghe at 22-Nov-07 22:43
memberNikoTanghe22-Nov-07 22:43 
GeneralExcellent! [modified] Pin
TheCardinal at 22-Nov-07 22:34
memberTheCardinal22-Nov-07 22:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150427.1 | Last Updated 22 Nov 2007
Article Copyright 2007 by W. Kevin Hazzard
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid