Installing a Windows Service



Installing a Windows Service

The .NET Framework enables you to create custom installer components. The custom installer components are the classes that an installation tool, such as installutil.exe, can use to properly install an application.

The following three installation components are used when creating an installer for the Windows service applications:

  • The System.ServiceProcess.ServiceProcessInstaller Class— This class creates the records for all the Windows services contained with the application in the Windows service database. You need to have just one instance of the ServiceProcessInstaller class in a Windows service application.

  • The System.ServiceProcess.ServiceInstaller Class— This class writes specific information about a Windows service to the Windows service database. You'll have as many instances of the ServiceInstaller class as the number of services in a Windows service application.

  • The System.Configuration.Install.Installer Class— This class works as the entry point for the installation process. The Installer class maintains a collection of custom installer objects, which can be accessed through the Installers property. You should add the instance of the ServiceProcessInstaller class and instances of the ServiceInstaller class of the Windows service application to this collection. You should also apply the RunInstaller attribute to this class and set its value to true.

When you use an installation tool such as installutil.exe to install a Windows service application, the installation tool takes the following steps:

  1. It looks for an installer class in the Windows service application that has its RunInstaller attribute set to true and creates an instance of this class.

  2. It gets a collection of custom installer objects from the Installers property and invokes the Install() method on each of these objects to perform the custom installation.

  3. It rolls back the installation of all custom installers if any one of them failed.

The ServiceProcessInstaller and the ServiceInstaller Classes

I'll talk more about the installation process and the Installer class later in Chapter 10. This section focuses on some important properties of the ServiceProcessInstaller class and the ServiceInstaller class because these properties specify the values that are written to the Windows service database.

The ServiceProcessInstaller class specifies the security settings for the Windows services in the Windows service application. Figure lists some important properties of the ServiceProcessInstaller class.

Figure Important Properties of the ServiceProcessInstaller Class

Property

Description

Account

Specifies the type of account under which the services run. This property takes one of the values from the ServiceAccount enumeration. These values are LocalService, LocalSystem, NetworkService, and User. If you set the Account property to User and do not specify a value for either the Username or Password property, then you are prompted to enter both username and password at the time of installation.

Password

This property is useful only when the Account property is set to User. In that case, this property specifies the password of the account under which the service application runs.

Username

This property is useful only when the Account property is set to User. In that case, this property specifies the username of the account under which the service application runs.

EXAM TIP

Some Accounts Are XP-only The LocalService and NetworkService accounts are only available on Windows XP and Windows Server 2003. These accounts do not exist on Windows 2000 or older operating systems.


The ServiceInstaller specifies the individual settings for each service in the Windows service database. Figure lists some important properties of the ServiceInstaller class.

Figure Important Members of the ServiceInstaller Class

Property

Description

DisplayName

Specifies a descriptive friendly name that identifies the service to the user. This name is often used by interactive tools to display the service to the user.

ServiceName

Specifies a unique name by which the system identifies this service. The ServiceName must be between 1 to 256 characters. And it cannot contain '/', '\', or any character from the ASCII character set with a value less than decimal value 32.

ServicesDependedOn

Specifies an array of strings that represents the services that must be running for this service to run. If any service in the array is not running, the SCM tries to start that service before starting this service.

StartType

Indicates how and when this service is started. The value of this property is one of the ServiceStartMode enumeration value—Automatic, Disabled or Manual. The value Automatic specifies that the service is started automatically when Windows starts. The default value of this property is Manual, which means that the service will not start automatically with Windows.

EXAM TIP

The ServiceName Property The ServiceName property of a ServiceInstaller object must exactly match the ServiceName property of the corresponding Windows service class.


NOTE

Windows Service Description Unfortunately, the Installer class does not have a property to set the description for a Windows Service. If you need to set a description for a service, you have two choices: Either use the Service Control utility (sc.exe) or modify the Registry key corresponding to the Windows service, add a string value named Description, and set the data for this value with the description text.


Adding Installer Classes to a Windows Service Project

When you use Visual Studio .NET to create a Windows service application, it is easy to create the required installer classes. The Properties window of the Windows service, as shown earlier in Figure, displays a link called Add Installer. When you click on that link, Visual Studio .NET automatically adds a class named ProjectInstaller in your project. This class derives from the Installer class and contains an instance of the ServiceProcessInstaller class and one or more instances of the ProcessInstaller class (depending on the number of Windows services you have in the application).

Step-by-Step 6.2 demonstrates how to add installer classes to a Windows service project.

STEP BY STEP

6.2 Creating an Installer for the Windows Service

  1. Open the project StepByStep6_1. Access the design view for the OrderService component. Click anywhere on the background of the designer to select the service itself, rather than any of its components. Access the Properties window for the service. In the gray area below the list of properties, you see a hyperlink named Add Installer (refer to Figure). Click on the hyperlink.

  2. The preceding step adds a component named ProjectInstaller.cs to the StepByStep6_1 project. Access the design view for ProjectInstaller.cs to see that it has two components: serviceProcessInstaller1 and serviceInstaller1.

  3. Access the properties for the serviceProcessInstaller1 component. You'll note that this component is an instance of the ServiceProcessInstaller class. Change its Account property from User to LocalSystem.

  4. Access the properties for the serviceInstaller1 component. You'll note that this component is an instance of the ServiceInstaller class. Change its DisplayName and ServiceName properties to OrderService and the StartType property to Automatic.

  5. Build the project StepByStep6_1. The Windows service is now ready to be installed.

At this stage, the OrderService application has both a Windows service and an installer.

Using Installer tool (installutil.exe) to Install a Windows Service Application

You can easily install an executable file that has the code for the installer class by using the command line Installer tool (installutil.exe) that comes as a part of the .NET Framework SDK.

Step-by-Step 6.3 demonstrates how to use installutil.exe to install a Windows service application in the Windows service database.

STEP BY STEP

6.3 Using installutil.exe to Install a Windows Service Application

  1. Open the Visual Studio .NET command prompt by selecting Start, Programs, Microsoft Visual Studio .NET, Visual Studio .NET Tools, Visual Studio .NET Command Prompt. This opens a command window with necessary environment variables set to run the .NET Framework SDK tools. Change the directory to the bin\debug directory of the StepByStep6_1 project where the .exe file for the Windows service application is stored.

  2. Issue the following command; you see the results as shown in Figure:

    
    installutil StepByStep6_1.exe
    
    
    Figure. You can use installutil.exe to install a Windows service application.

    graphics/06fig06.jpg

The Windows service application is now stored in the Windows service database. Not only this, but based on the information in the executable file, installutil.exe has also installed an event source named OrderService for writing to the Application event log.

Because the StartType of the OrderService Windows service is set as Automatic, it will start automatically when Windows starts next time.

Starting and Testing a Windows Service

To see the OrderService Windows service in action, you need to first create the directory c:\orders because OrderService depends on it. In most cases, it is helpful to create any such required files or directories at the time of installation itself. However, for that you have to install the Windows service using a setup package based on the Windows Installer. You'll learn how to do that later in Chapter 10.

Step-by-Step 6.4 shows how to use the OrderService service to automatically add new records in the Orders table of the Northwind database, whenever an XML file is created in the c:\orders directory.

STEP BY STEP

6.4 Starting a Windows Service

  1. Create a directory c:\orders. This is the directory where the incoming orders will be created as an XML file.

  2. Restart the computer; the OrderService is started automatically when Windows is started.

  3. Right-click on the My Computer icon and select Manage from its shortcut menu. In the Computer Management window, navigate to System Tools, Event Viewer, Application. You'll see that OrderService has written an informational message to the Application event log. Double-click to open the message; you'll see that the message is about the successful start of OrderService, as shown in Figure.

    Figure. When the StartType for a Windows service is set to Automatic, the service is started automatically when Windows is started.

    graphics/06fig07.jpg

  4. Create an XML file named Orders.xml and store the following information in this file:

    
    <?xml version="1.0" standalone="yes"?>
    
    <dsOrders xmlns="http://www.tempuri.org/dsOrders.xsd">
    
      <Orders>
    
        <CustomerID>VINET</CustomerID>
    
        <EmployeeID>5</EmployeeID>
    
        <OrderDate>2002-10-11</OrderDate>
    
        <RequiredDate>2002-10-21</RequiredDate>
    
        <ShippedDate>2002-10-18</ShippedDate>
    
        <ShipVia>3</ShipVia>
    
        <Freight>22.38</Freight>
    
        <ShipName>Vins et alcools Chevalier</ShipName>
    
        <ShipAddress>59 rue de l'Abbaye</ShipAddress>
    
        <ShipCity>Reims</ShipCity>
    
        <ShipRegion>MI</ShipRegion>
    
        <ShipPostalCode>51100</ShipPostalCode>
    
        <ShipCountry>France</ShipCountry>
    
      </Orders>
    
    </dsOrders>
    
    
  5. Copy this file to the c:\orders directory. You'll note that in a few moments the Orders.xml file is moved from c:\orders to a new subdirectory, c:\orders\updated.

  6. Query the Orders table in the Northwind database. You'll find that a record has been added to the Orders table with the information in the Orders.xml file.

  7. Create another orders file in the c:\orders directory. You'll note that the file is moved again to the updated subdirectory and the Orders table is updated with the information in the XML file.

In Step-by-Step 6.4, you saw that as the new XML files are created, they are inserted into the Northwind database's Orders table. After the order record is inserted, the program also moves the XML file to the c:\orders\updated subdirectory. The FileSystemWatcher is configured not to listen to any of the subdirectories inside c:\orders; therefore XML files created in c:\orders\updated do not raise any events of interest to the FileSystemWatcher component.

REVIEW BREAK

  • You can easily create Windows services by using the functionality provided by the System.ServiceProcess.ServiceBase class.

  • The System.ServiceProcess.ServiceProcessInstaller and the System.ServiceProcess.ServiceInstaller classes provide the functionality for custom installation of Windows service applications.

  • For installation tools such as installutil.exe to install an assembly, the 4assembly must have a class derived from System.Configuration.Install.Installer. If any custom installers (such as Windows service installers) need to be installed, they are added to the Installers collection of the Installer class.

  • When the SCM sends a start message to a Windows service, first the Main() method of the Windows service application is executed. This method creates one or more instances of the Windows services and passes them to the Run() method of the ServiceBase class. This method provides the references of Windows service objects to the SCM. SCM uses these references to communicate with the Windows service.

GUIDED PRACTICE EXERCISE 6.1

Recall from Chapter 3, ".NET Remoting," that when you want to remote an object by some method other than using IIS, you have to create a remoting server and manually start the service whenever the computer is restarted. When you implement a remoting server as a Windows service, it is easy to ensure that the remoting server is automatically started with Windows.

The objective of this exercise is to create a Windows service that exposes the DbConnect class of the StepByStep3_10 project as a Singleton server-activated object. You'll use a client program such as the one created in StepByStep3_12 project to connect to this service.

The server and client should communicate via the TCP channels and the binary formatter. The service should start automatically when Windows is started. The service should allow itself to be stopped but should not support pause and continue operations.

How would you create such a Windows service?

You should try working through this problem on your own first. If you get stuck, or if you'd like to see one possible solution, follow these steps:

  1. Add a new Visual C# .NET Windows Service application named GuidedPracticeExercise3_1 to the solution.

  2. Add references to the .NET assembly System.Runtime.Remoting, and to the project StepByStep3_9 and StepByStep3_10 that you created in Chapter 3 (the interface to the remotable class and the remotable class itself).

  3. In the Solution Explorer, rename the default Service1.cs to DbConnectSingletonServer.cs. Click on the designer surface, and then in the Properties window. Set the Name and ServiceName properties to DbConnectSingletonServer. Note the CanPauseAndContinue property is already set to false.

  4. Switch to the code view and change all occurrences of Service1 to DbConnectSingletonServer. Add the following using directives to the code:

    
    using StepByStep3_9;
    
    using StepByStep3_10;
    
    using System.Runtime.Remoting;
    
    using System.Runtime.Remoting.Channels;
    
    using System.Runtime.Remoting.Channels.Http;
    
    
  5. In the code, search for the skeleton of the OnStart() method and modify it as follows:

    
    protected override void OnStart(string[] args)
    
    {
    
        // Register a TCP server channel that
    
        // listens on port 1234
    
        TcpServerChannel channel =
    
            new TcpServerChannel(1234);
    
        ChannelServices.RegisterChannel(channel);
    
    
    
        // Resgister the service that publishes
    
        // DbConnect for remote access in Singleton mode
    
        RemotingConfiguration.RegisterWellKnownServiceType
    
           (typeof(StepByStep3_10.DbConnect), "DbConnect",
    
           WellKnownObjectMode.Singleton);
    
    }
    
    
  6. Access the Properties window for the DbConnectSingletonServer component. Click on the Add Installer hyperlink. This adds a component named ProjectInstaller.cs to the project. Access the design view for ProjectInstaller.cs to see that it has two components: serviceProcessInstaller1 and serviceInstaller1.

  7. Access the properties for the serviceProcessInstaller1 component. You'll note that this component is an instance of the ServiceProcessInstaller class. Change its Account property from User to LocalSystem.

  8. Access the properties for the serviceInstaller1 component. You'll note that this component is an instance of the ServiceInstaller class. Change its ServiceName and DisplayName properties to DbConnectSingletonServer and the StartType property to Automatic.

  9. Set DbConnectSingletonServer.cs as the startup object for the project.

  10. Build the project. This step creates a remoting server that is capable of using the Singleton activation mode via the TCP channel to register the StepByStep3_10.DbConnect class for remote invocation.

  11. To install the Windows service, open the Visual Studio .NET command prompt and change the directory to the bin\debug directory in the project folder. Execute the following command:

    
    installutil GuidedPracticeExercise6_1.exe
    
    
  12. Use the command prompt to execute the following command to start the Windows service:

    
    NET START DbConnectSingletonServer
    
    
  13. Run the executable file StepByStep3_12.exe for the project created in Step-by-Step 3.12 in Chapter 3. In the window that appears type queries for retrieving data from the Northwind database.

If you have difficulty following this exercise, review the sections "Creating a Windows Service Application" and "Installing a Windows Service" earlier in this chapter. Also review the sections, "Creating a Remotable Class" and "Creating a Server-Activated Object" in Chapter 3. Make sure that you also perform Step-by-Step 6.1 through Step-by-Step 6.3 and Step-by-Step 3.9 to Step-by-Step 3.12. After doing that review, try this exercise again.