Logo: C# Computing
Web CsharpComputing.com

C# Tutorial Lesson 22: Writing and Installing a Windows service

Start by creating new Windows Service Project:

A windows service cannot be run directly but needs an installer. To add the installer to the project, right click on Service1.cs Design pane and choose Add Installer. You will see  two object added to your Windows Service project: serviceInstaller1 and serviceProcessInstaller1:

Service Installer has some important properties like: Display Name, Service Name and Start Type (Manual, Automatic, Disabled). Display Name is unfortunately not used by the installer, and there is no way with .NET 1.0 or 1.1 to set a display name without using unmanaged code. Service Name is the  "official" service name that appears in the Service Control Manager (SCM) and is also stored in the registry. Because of this, Service Name cannot contain spaces, dashes or underscores. Start Type specifies the services' behavior after reboot: auto-start for automatic, manual for could be started, and disabled for deactivated.

Service Process Installer specifies whether to install the service under User, Local System, Network Service or Local Service account. User is the default account setting and it allows the service to impersonate a specific user whether or not that user is logged in. Local System is a system account with high privileges similar to the Administrator account. However, Local System account doesn't have necessary access to UI elements. So, if you pop up a dialog as Local System, it will show on a system desktop! The key Service code is inside On Start and On Stop event handlers. These event handlers are called when a service is about to be started or stopped. On Start and On Stop work differently with or without impersonation. When a service runs as a user, you can call your code synchronously from On Start method. When a service runs as Local System, it is started only after On Start method returns. If synchronous code is put inside On Start method, the method will never return and the service will never start.

Running service as user provides excellent impersonation benefits, especially if the service access any user specific settings like printer, registry, isolated storage or browser settings. Remember that only members of Administrators group have access to SCM and only these users can start and stop services. Therefore a user X, who is not an administrator, will not be able to start or stop any service, including a service running as X.

Once a service is written, it is installed with gacutil /u myservice.exe command. Gacutil is part of .NET redistributable and it is available on every computer that has .NET installed.

Comments by Dawn:

After adding the installer to the project, enter the name you want to appear in the Service Control Manager in the DisplayName field. Tip: to keep names consistent, I enter the same name in the
ServiceName field and the DisplayName field. This will ensure the name that gets
displayed in the SCM is the same name as your service name. The SCM displays what's entered in the DisplayName field so it may as well be the name of the service.
If the DisplayName field is empty, the SCM displays the value in the ServiceName field.

I used installutil to install the service on the target machine. To install the Windows Service on a machine with the .NET SDK, open a .NET command prompt, and enter installutil /i
fullfilepathtoservice.exe. The service can be removed from the machine with the command installutil /u fullfilepathtoservice.exe.

If the target machine has the .NET Framework installed but not the .NET SDK, open a
regular command prompt and type C:\WINNT\Microsoft.NET\Framework\v1.1.4322 installutil /i fullfilepathtoservice.exe.

To debug the service, add this line of C# code -
to the OnStart() method, build the solution, and install the service.
If the StartType is manual, open the SCM and start the service. The service must be installed
and running to be able to step into it. This may seem obvious but it isn't if it's the first service you've ever written. When the
debugger line of code is reached, the program will launch a tool that asks you to select the debugger
(I usually choose the current instance of VS.NET) and choose the
program type to debug. The default selections are CLR and Native; I usually uncheck Native.