17.5 Create a Windows Service


Problem

You need to create an application that will run as a Windows service.

Solution

Create a class that extends System.ServiceProcess.ServiceBase . Use the inherited properties to control the behavior of your service, and override inherited methods to implement the functionality required. Implement a Main method that creates an instance of your service class and passes it to the static ServiceBase.Run method.

Discussion

If you are using Microsoft Visual C# .NET (other than the standard edition), you can use the Windows Service project template to create a Windows service. The template provides the basic code infrastructure required by a Windows service class, which you can extend with your custom functionality. To create a Windows service manually, you must implement a class derived from the ServiceBase class. The ServiceBase class provides the base functionality that allows the Windows Service Control Manager (SCM) to configure the service, operate the service as a background task, and control the life cycle of the service. The SCM also controls how other applications can control the service programmatically.

Important  

The ServiceBase class is defined in the System.Serviceprocess assembly, so you must include a reference to this assembly when you build your service class.

To control your service, the SCM uses the seven protected methods inherited from ServiceBase class described in Table 17.5. You should override these inherited methods to implement the functionality and behavior required by your service. Not all services must support all control messages. The properties inherited from the ServiceBase class declare to the SCM which control messages your service supports; the property that controls each message type is specified in Table 17.5.

Table 17.5: Methods That Control the Operation of a Service

Method

Description

OnStart

All services must support the OnStart method, which the SCM calls to start the service. The SCM passes a string array containing arguments specified for the service. The OnStart method must return within 30 seconds or the SCM will abort the service.

OnStop

Called by the SCM to stop a service ”the SCM will call OnStop only if the CanStop property is true .

OnPause

Called by the SCM to pause a service ”the SCM will call OnPause only if the CanPauseAndContinue property is true .

OnContinue

Called by the SCM to continue a paused service ”the SCM will call OnContinue only if the CanPauseAndContinue property is true .

OnShutdown

Called by the SCM when the system is shutting down ”the SCM will call OnShutdown only if the CanShutdown property is true .

OnPowerEvent

Called by the SCM when a system-level power status change occurs, such as a laptop going into suspend mode. The SCM will call OnPowerEvent only if the CanHandlePowerEvent property is true .

OnCustomCommand

Allows you to extend the service control mechanism with custom control messages; see the .NET Framework SDK documentation for more details.

As mentioned in Table 17.5, the OnStart method must return within 30 seconds, so you shouldn't use OnStart to perform lengthy initialization tasks . A service class should implement a constructor that performs initialization, including configuring the inherited properties of the ServiceBase class. In addition to the properties that declare the control messages supported by a service, the ServiceBase class implements three other important properties.

  • ServiceName is the name used internally by the SCM to identify the service and must be set before the service is run.

  • AutoLog controls whether the service automatically writes entries to the event log when it receives any of the OnStart , OnStop , OnPause , and OnContinue control messages from Table 17.5.

  • EventLog provides access to an EventLog object that's preconfigured with an event source name that's the same as the ServiceName property registered against the Application log. (See recipe 17.3 for more information about the EventLog class.)

The final step in creating a service is to implement a static Main method. The Main method must create an instance of your service class and pass it as an argument to the static method ServiceBase.Run . If you want to run multiple services in a single process, you must create an array of ServiceBase objects and pass it to the ServiceBase.Run method. Although service classes have a Main method, you can't execute service code directly; attempting to run a service class directly results in Windows displaying the Windows Service Start Failure message box shown in Figure 17.1. Recipe 17.6 describes what you must do to install your service before it will execute.

click to expand
Figure 17.1: The Windows Service Start Failure message box.

The ServiceExample class shown here uses a configurable System.Timers.Timer to write an entry to the Windows event log periodically.

 using System; using System.Timers; using System.ServiceProcess; public class ServiceExample : ServiceBase {     // A Timer that controls when ServiceExample writes to the     // event log.     private System.Timers.Timer timer;     public ServiceExample() {         // Set the ServiceBase.ServiceName property.         ServiceName = "ServiceExample";         // Configure the level of control available on the service.         CanStop = true;         CanPauseAndContinue = true;         // Configure the service to log important events to the          // Application event log.         AutoLog = true;     }     // The method executed when the timer expires - writes an     // entry to the Application event log.     private void WriteLogEntry(object sender, ElapsedEventArgs e) {         // Use the EventLog object automatically configured by the          // ServiceBase class to write to the event log.          EventLog.WriteEntry("ServiceExample active : " + e.SignalTime);     }     protected override void OnStart(string[] args) {         // Obtain the interval between log entry writes from the first         // argument. Use 5000 milliseconds by default and enforce a 1000         // millisecond minimum.         double interval;         try {             interval = System.Double.Parse(args[0]);             interval = Math.Max(1000, interval);         } catch {             interval = 5000;         }         EventLog.WriteEntry(String.Format("ServiceExample starting. " +             "Writing log entries every {0} milliseconds...", interval));         // Create, configure, and start a System.Timers.Timer to          // periodically call the WriteLogEntry method. The Start         // and Stop methods of the System.Timers.Timer class         // make starting, pausing, resuming, and stopping the          // service straightforward.         timer = new Timer();         timer.Interval = interval;         timer.AutoReset = true;         timer.Elapsed += new ElapsedEventHandler(WriteLogEntry);         timer.Start();     }     protected override void OnStop() {         EventLog.WriteEntry("ServiceExample stopping...");         timer.Stop();         // Free system resources used by the Timer object.         timer.Dispose();         timer = null;     }     protected override void OnPause() {         if (timer != null) {             EventLog.WriteEntry("ServiceExample pausing...");             timer.Stop();         }     }     protected override void OnContinue() {         if (timer != null) {             EventLog.WriteEntry("ServiceExample resuming...");             timer.Start();         }     }     public static void Main() {         // Create an instance of the ServiceExample class that will write          // an entry to the Application event log. Pass the object to the         // static ServiceBase.Run method.         ServiceBase.Run(new ServiceExample());     } } 



C# Programmer[ap]s Cookbook
C# Programmer[ap]s Cookbook
ISBN: 735619301
EAN: N/A
Year: 2006
Pages: 266

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net