Installing a Windows service

Sunday, August 1, 2010

#.NET #C# #Windows Service

To install a service you need to use the ServiceProcessInstaller and the ServiceInstaller classes. These handle the installation of the Windows service as a process with the provided information. The Account-property on the ServiceProcessInstaller is used to tell what security context the service should run under when installed. I use LocalSystem here because I need my service to have access to my file system, but here you have to choose what best fits your situation of course. The username and password properties are used to tell what user the service should run as. Next for the properties of the ServiceInstaller you can specify how and when your service is started with the StartType-property and you can set the service name, display name, a description and then you need to assign the ServiceProcessInstaller instance as parent to the ServiceInstaller instance. Then you need to specify the context in which the service should be installed: the full path to the executable that holds the service as a commandline and a path to a log file if needed. Then you install it by calling the Install-method on the ServiceInstaller instance. Then, because we need to start up the service, we takes control of the installed service with the ServiceController-class and call the Start-method. That’s it! Your service is installed :)

ServiceProcessInstaller processInstaller =
    new ServiceProcessInstaller();
processInstaller.Account = ServiceAccount.LocalSystem;
processInstaller.Username = null;
processInstaller.Password = null;

ServiceInstaller serviceInstaller =
    new ServiceInstaller();
serviceInstaller.StartType = ServiceStartMode.Automatic;
serviceInstaller.ServiceName = ServiceName;
serviceInstaller.DisplayName = ServiceDisplayName;
serviceInstaller.Description = ServiceDescription;
serviceInstaller.Parent = processInstaller; 

string path = string.Format("/assemblypath={0}", ServiceExecutablePath);
string[] cmdline = { path };
string logFilePath = “C:\path\to\your\logfile.txt”;
serviceInstaller.Context = new System.Configuration.Install.InstallContext(logFilePath, cmdline);

System.Collections.Specialized.ListDictionary state =
    new System.Collections.Specialized.ListDictionary();
serviceInstaller.Install(state);

ServiceController serviceController =
    new ServiceController(serviceInstaller.ServiceName);

serviceController.Start();

If you need to uninstall your service to update it for instance (that’s right, the service executable cannot be altered as long as the service is installed), you can use the below code to do just that. It should be quite straight forward. You just take control of the service as in the code above, figure out if the service is running, if it’s running then it has to be stopped before we can uninstall it, wait for it to stop and then gives the need context-information and then we uninstall by calling Uninstall on our ServiceInstaller object.

ServiceInstaller serviceInstaller =
    new ServiceInstaller();
serviceInstaller.ServiceName = ServiceName;

ServiceController serviceController =
    new ServiceController(serviceInstaller.ServiceName);

if ((serviceController.Status == ServiceControllerStatus.Running)
    || (serviceController.Status == ServiceControllerStatus.Paused))
{
    serviceController.Stop();

    serviceController.WaitForStatus(ServiceControllerStatus.Stopped, new TimeSpan(0, 0, 0, 15));

    serviceController.Close();
}

string path = String.Format("/assemblypath={0}", ServiceExecutablePath);
string[] cmdline = { path };
string logFilePath = “C:\path\to\your\logfile.txt”;
serviceInstaller.Context = new System.Configuration.Install.InstallContext(logFilePath, cmdline);

serviceInstaller.Uninstall(null);