Tải bản đầy đủ - 0 (trang)
14-6. Create a Windows Service

14-6. Create a Windows Service

Tải bản đầy đủ - 0trang

CHAPTER 14 ■ WINDOWS INTEGRATION



(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.



■ Tip If you are using Microsoft Visual Studio, 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 control your service, the SCM uses the eight protected methods inherited from the ServiceBase

class described in Table 14-5. You should override these virtual methods to implement the functionality

and behavior required by your service. Not all services must support all control messages. The CanXXX

properties inherited from the ServiceBase class declare to the SCM which control messages your service

supports; Table 14-5 specifies the property that controls each operation.

Table 14-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. These arguments can be specified when the ServiceController.Start

method is called, and are usually configured in the service’s property window in the

Windows Control Panel. However, they are rarely used, because it is better for the

service to retrieve its configuration information directly from the Windows registry.

The OnStart method must normally return within 30 seconds, or else the SCM will

abort the service. Your service must call the RequestAdditionalTime method of the

ServiceBase class if it requires more time; specify the additional milliseconds

required as an int.



OnStop



Called by the SCM to stop a service—the SCM will call OnStop only if the CanStop

property is set to true.



OnPause



Called by the SCM to pause a service—the SCM will call OnPause only if the

CanPauseAndContinue property is set to true.



OnContinue



Called by the SCM to continue a paused service—the SCM will call OnContinue only if

the CanPauseAndContinue property is set to true.



OnShutdown



Called by the SCM when the system is shutting down—the SCM will call OnShutdown

only if the CanShutdown property is set to 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 set to true.



700



www.it-ebooks.info



CHAPTER 14 ■ WINDOWS INTEGRATION



Method



Description



OnCustomCommand



Allows you to extend the service control mechanism with custom control messages;

see the .NET Framework SDK documentation for more details.



OnSessionChange



Called by the SCM when a change event is received from the Terminal Services

session or when users log on and off on the local machine. A

System.ServiceProcess.SessionChangeDescription object passed as an argument by

the SCM contains details of what type of session change occurred. The SCM will call

OnSessionChange only if the CanHandleSessionChangeEvent property is set to true. This

method is new in the .NET Framework 2.0.



As mentioned in Table 14-5, the OnStart method is expected to return within 30 seconds, so you

should not use OnStart to perform lengthy initialization tasks if possible. 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, or OnContinue control

messages from Table 14-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 14-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.



The Code

The following Windows service example uses a configurable System.Timers.Timer to write an entry to

the Windows event log periodically. You can start, pause, and stop the service using the Services

application in the Control Panel.

using System;

using System.Timers;

using System.ServiceProcess;

namespace Apress.VisualCSharpRecipes.Chapter14

{

class Recipe14_06 : ServiceBase

{

// A Timer that controls how frequently the example writes to the

// event log.

private System.Timers.Timer timer;



701



www.it-ebooks.info



CHAPTER 14 ■ WINDOWS INTEGRATION



public Recipe14_06()

{

// Set the ServiceBase.ServiceName property.

ServiceName = "Recipe 14_06 Service";

// Configure the level of control available on the service.

CanStop = true;

CanPauseAndContinue = true;

CanHandleSessionChangeEvent = true;

// Configure the service to log important events to the

// Application event log automatically.

AutoLog = true;

}

// The method executed when the timer expires and 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("Recipe14_06 Service 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 = Double.Parse(args[0]);

interval = Math.Max(1000, interval);

}

catch

{

interval = 5000;

}

EventLog.WriteEntry(String.Format("Recipe14_06 Service 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;



702



www.it-ebooks.info



CHAPTER 14 ■ WINDOWS INTEGRATION



timer.AutoReset = true;

timer.Elapsed += new ElapsedEventHandler(WriteLogEntry);

timer.Start();

}

protected override void OnStop()

{

EventLog.WriteEntry("Recipe14_06 Service stopping...");

timer.Stop();

// Free system resources used by the Timer object.

timer.Dispose();

timer = null;

}

protected override void OnPause()

{

if (timer != null)

{

EventLog.WriteEntry("Recipe14_06 Service pausing...");

timer.Stop();

}

}

protected override void OnContinue()

{

if (timer != null)

{

EventLog.WriteEntry("Recipe14_06 Service resuming...");

timer.Start();

}

}

protected override void OnSessionChange(SessionChangeDescription change)

{

EventLog.WriteEntry("Recipe14_06 Session change..." +

change.Reason);

}

public static void Main()

{

// Create an instance of the Recipe14_06 class that will write

// an entry to the Application event log. Pass the object to the

// static ServiceBase.Run method.

ServiceBase.Run(new Recipe14_06());

}

}

}



703



www.it-ebooks.info



CHAPTER 14 ■ WINDOWS INTEGRATION



Usage

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 or run a service class directly. Recipe 14-7 describes what you must do to

install your service before it will execute.



14-7. Create a Windows Service Installer

Problem

You have created a Windows service application and need to install it.



Solution

Add a new class to your Windows service project that extends the System.Configuration.Install.

Installer class to create an installer class containing the information necessary to install and configure

your service class. Use the Installer tool (Installutil.exe) to perform the installation, which is installed

as part of the .NET Framework.



■ Note You must create the installer class in the same assembly as the service class for the service to install and

function correctly.



How It Works

As recipe 14-6 points out, you cannot run service classes directly. The high level of integration with the

Windows operating system and the information stored about the service in the Windows registry means

services require explicit installation.

If you have Microsoft Visual Studio .NET, you can create an installation component for your service

automatically by right-clicking in the design view of your service class and selecting Add Installer from

the context menu. You can call this installation component by using deployment projects or by using the

Installer tool to install your service. You can also create installer components for Windows services

manually by following these steps:

1.



In your project, create a class derived from the Installer class.



2.



Apply the attribute System.ComponentModel.RunInstallerAttribute(true) to

the installer class.



3.



In the constructor of the installer class, create a single instance of the

System.ServiceProcess.ServiceProcessInstaller class. Set the Account, User,

and Password properties of ServiceProcessInstaller to configure the account

under which your service will run. This account must already exist.



704



www.it-ebooks.info



CHAPTER 14 ■ WINDOWS INTEGRATION



4.



5.



In the constructor of the installer class, create one instance of the

System.ServiceProcess.ServiceInstaller class for each individual service you

want to install. Use the properties of the ServiceInstaller objects to configure

information about each service, including the following:





ServiceName, which specifies the name Windows uses internally to identify

the service. This must be the same as the value assigned to the

ServiceBase.ServiceName property.







DisplayName, which provides a user-friendly name for the service.







StartType, which uses values of the

System.ServiceProcess.ServiceStartMode enumeration to control whether

the service is started automatically or manually, or is disabled.







ServiceDependsUpon, which allows you to provide a string array containing a

set of service names that must be started before this service can start.



Add the ServiceProcessInstaller object and all ServiceInstaller objects to

the System.Configuration.Install.InstallerCollection object accessed

through the Installers property, which is inherited by your installer class

from the Installer base class.



The Code

The following example is an installer for the Recipe14_06 Windows service created in recipe 14-6. The

sample project contains the code from recipe 14-6 and for the installer class. This is necessary for the

service installation to function correctly. To compile the example, you must reference two additional

assemblies: System.Configuration.Install.dll and System.ServiceProcess.dll.

using System.Configuration.Install;

using System.ServiceProcess;

using System.ComponentModel;

namespace Apress.VisualCSharpRecipes.Chapter14

{

[RunInstaller(true)]

public class Recipe14_07 : Installer

{

public Recipe14_07()

{

// Instantiate and configure a ServiceProcessInstaller.

ServiceProcessInstaller ServiceExampleProcess =

new ServiceProcessInstaller();

ServiceExampleProcess.Account = ServiceAccount.LocalSystem;

// Instantiate and configure a ServiceInstaller.

ServiceInstaller ServiceExampleInstaller =

new ServiceInstaller();

ServiceExampleInstaller.DisplayName =

"Visual C# Recipes Service Example";



705



www.it-ebooks.info



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

14-6. Create a Windows Service

Tải bản đầy đủ ngay(0 tr)

×