Create and manipulate a Windows service: Write code that is executed when a Windows service is started or stopped .
In this section, you'll use the ServiceBase class to create a Windows service application. You'll learn
About the ServiceBase class and its functionality
How the SCM interacts with a Windows service derived from the ServiceBase class
How to create a Windows service by deriving a class from the ServiceBase class
Programmatically, a Windows service is a class that derives its basic functionality from the ServiceBase class of the System.ServiceProcess namespace. The ServiceBase class provides its derived classes with some well-known methods and properties. The SCM knows these methods and properties and uses them to communicate with the Windows services. Table 6.1 lists the important members of the ServiceBase class.
Member Name | Type | Description |
---|---|---|
AutoLog | Property | When set to true, automatically logs the call to OnStart() , OnStop() , OnPause() , and OnContinue() methods in the Application event log. |
CanPauseAndContinue | Property | When set to true, indicates that the service can be paused and resumed. |
CanShutdown | Property | When set to true, indicates that the service should be notified when the system is shutting down. |
CanStop | Property | When set to true, indicates that the service can be stopped once it has started. |
EventLog | Property | Specifies an event log that can be used to write customized messages to the Application event log on method calls such as OnStart() and OnStop() . |
OnContinue() | Method | Specifies the actions to take when a service resumes normal functioning after being paused. This method is executed when the SCM sends a continue command to the Windows service. |
OnPause() | Method | Specifies the actions to take when a service pauses. This method is executed when the SCM sends a pause command to the Windows service. |
OnStart() | Method | Specifies the actions to take when a service starts running. This method is executed when the SCM sends a start command to the Windows service. |
OnStop() | Method | Specifies the actions to take when a service stops running. This method is executed when the SCM sends a stop command to the Windows service. |
Run() | Method | Provides the main entry point for a service executable. |
ServiceName | Property | Specifies a name that identifies the service. |
EXAM TIP
Writing to a Custom Event Log With the help of the AutoLog and the EventLog properties of the ServiceBase class, you can write messages only to the Application event log. If you want to write entries to a different event log, you should create a new EventLog component and the OnStart() , OnStop() , and so on methods to explicitly post entries to that log.
A Windows service application defines one or more classeseach defining a Windows service. Only one of these classes can define a Main() method, which is the main entry point for the application. The Main() method specifies which Windows services should run by passing the instances of the Windows service to the static Run() method of the ServiceBase class.
The Run() method does not actually start the Windows service; instead, the Run() method just passes the reference of the Windows service objects to the SCM. The SCM uses these objects to send messages to the Windows service.
Figure 6.2 illustrates how the SCM interacts with a Windows service derived from the ServiceBase class.
When the SCM sends a start message to the Windows service, the following things happen:
The SCM finds the path of the Windows service application's executable file from the Windows service database.
SCM creates a Windows service process by executing the Main() method defined in the Windows service executable.
The Main() method of the Windows service executable creates one or more instances of the Windows service class and passes their references to the SCM through the static Run() method of the ServiceBase class. The SCM uses these references to send messages to the Windows service.
The handler associated with the start messagethe OnStart() methodis executed. The OnStart() method executes the code required for a Windows service to carry out its tasks , such as listening to a port for incoming requests , logging events to the event log, spooling print jobs, and so on.
After the Windows service is started, SCM can use its reference to send various messagessuch as pause, continue, and stopto the Windows service. These messages invoke the OnPause() , OnContinue() , and OnStop() methods of the Windows service, respectively.
Not all services implement the OnPause() , OnContinue() , and OnStop() methods. Whether a service needs to implement these methods depends on the CanPauseAndContinue and CanStop properties of a Windows service. If these properties are true, the SCM can invoke the OnPause() , OnContinue() , and OnStop() methods. But not every service implements this functionality. Some common examples of services that do not enable pausing or stopping include the Event Log, the Plug and Play, and the Security Accounts Manager services, which can neither be paused nor stopped, as well as the Print Spooler and the System Event Notification services, which can be stopped but not paused.
NOTE
Controlling a Windows Service If you set any of the CanStop , CanShutdown , or CanPauseAndContinue properties for a Windows service to true, you also must implement a corresponding handler method (such as OnStop() , OnPause() , OnContinue() , and so on). Otherwise , when SCM sends any of these messages, the Windows service will throw an exception and ignore the command.
There is no CanStart property in the ServiceBase class. This means that not starting is not an option for a Windows service. A Windows service class must provide an OnStart() method; otherwise, the base class version of the method is called.
When SCM sends a stop message to the Windows service, the associated handler OnStop() method is executed. After this, the Windows service process is unloaded from the memory.
To demonstrate how the Windows services are created, I'll create an OrderService that listens for XML files containing order information in a particular disk directory ( c:\orders ). As soon as an XML file is created in the directory, the service reads the files and, based on its data, creates a new record in the Orders table of the Northwind database. This type of application is typically used for updating orders received from the Internet, business partners , and from legacy applications.
Step By Step 6.1 shows how to create the OrderService application.
STEP BY STEP6.1 Creating a Windows Service Application
|
When you create a new project based on the Windows Service template, Visual Studio .Net automatically inserts a class that derives from the System.ServiceProcess.ServiceBase class in the project. In order to respond to various events raised by the SCM messages, I have overridden the base class version of the OnStart() , OnStop() , OnPause() , and OnContinue() methods.
In Step By Step 6.1, I'm using the FileSystemWatcher component. This component watches for any changes in the file system and raises events when a file or directory changes. In this example, I have initialized the FileSystemWatcher component in such a way that it just watches for the creation of XML files in a directory named c:\orders . I have also instructed the FileSystemWatcher component to exclude any subdirectories of c:\orders to narrow down the scope of notifications.
When an XML file is created in the c:\orders directory, the FileSystemWatcher component raises the Created event. I am using the fswOrders_Created() event handler to retrieve the order information from the newly created XML file and insert this information as a new order to the Order table of the Northwind database.
Table 6.2 lists some important members of the FileSystemWatcher component.
Member | Type | Description |
---|---|---|
Changed | Event | When a file or directory in the specified Path is changed this occurs. |
Created | Event | When a file or directory in the specified Path is created this occurs. |
Deleted | Event | When a file or directory in the specified Path is deleted this occurs. |
EnableRaisingEvents | Property | Specifies whether the component is enabled. If its value is false, the component does not receive any events. |
Error | Event | Occurs when the internal buffer of the component overflows. |
Filter | Property | Specifies which files are monitored in a directory. Its default value is *.* , which monitors for all types of files. |
IncludeSubdirectories | Property | Specifies whether the subdirectories within the specified path should be monitored. |
InternalBufferSize | Property | Specifies the size of the internal buffer. |
NotifyFilter | Property | Specifies the type of file system changes to monitor. Its value is a combination of values (each separated by a comma) from the NotifyFilters enumeration. Its default value is FileName, DirectoryName, LastWrite , which means that the component monitors for any changes in the filename, directory name, and the date and time of the last write operation on the files or directory. |
Path | Property | Specifies the path of the directory to watch. When a file or directory in the specified Path is renamed this occurs. |
SynchronizingObject | Property | Specifies the object that is used to marshal the event handler calls. |
WaitForChanged() | Method | This method is a synchronous method that returns a structure that contains specific information on the file system change. |
WARNING
The FileSystemWatcher Component Might Lose Track of Changes The FileSystemWatcher component stores the file system changes in an internal buffer whose size is set by a property named InternalBufferSize before it acts on those changes. If there are too many changes in a short time, this buffer can overflow and cause the FileSystemWatcher component to lose track of the file system changes. The default size of this buffer is 8192 bytes. You should not arbitrarily increase the size of this buffer because this buffer is maintained in non-paged memory and increasing its size would directly impact the performance of other applications. Instead, you should use the Path , NotifyFilter , and IncludeSubdirectories properties to narrow down the scope of notifications that the FileSystemWatcher component receives.
Compilation of the StepByStep6_1 project creates an executable file just like other Windows applications. However, you cannot directly run this executable. If you try doing so, you'll get a Windows service start failure error with the following message:
Cannot start service from the command line or a debugger. A Windows Service must first be installed (using installutil.exe) and then started with the Server Explorer, Windows Services Administrative tool or the NET START command
Apparently, you need to install a Windows service application before you can start it. You'll learn how to do that in the following section.
Top |