Configuring Client Computers and Servers to Use a Windows Service

Until now, you have been using the built-in Windows tools to view and manage Windows services. The .NET Framework also provides a set of classes that enable you to work with Windows services directly from your Visual Basic .NET application code. This can be very useful if you have created a Windows service that monitors and logs some system performance data, but you want it to run only while your application is running. You can start the service when your application starts up and stop it when your application closes. You can even add custom commands to your service and call them from application code.

In this section, you are going to learn how to use the ServiceController class. This is a .NET Framework class that has methods to programmatically control a Windows Service. You will create a Windows Forms application that can start and stop services. A sample application called ServiceControllerProject is included on the book’s CD and incorporates all the features covered in this section (see Figure 1.3). You might want to load the application code so that you can review it while you are reading this section.

Exercise 1.4 at the end of the chapter is designed to take you step-by-step through the features of the ServiceControllerProject demo application. Exercise 1.5 provides some examples that modify the CustomLogService that you created earlier in the chapter to support custom commands and for building a service controller application of your own to test them.

click to expand
Figure 1.3: The ServiceControllerProject demo

Instantiating the ServiceController Object

When you instantiate a ServiceController object, you must supply two important pieces of information:

  • The service name that you want to control

  • The machine name that the service is running on

If you do not specify a machine name, the default is to look for the service on the local machine. Your project must include a reference to System.ServiceProcess.dll, and you should add an Imports statement for System.ServiceProcess as well. The ServiceController object can be instantiated as follows:

Dim servController = New _     ServiceController("CustomLogService")

In the preceding example, the service name is passed to the overloaded constructor method as a single string parameter. The ServiceName property can also be set independently, as shown here:

Dim servController as New ServiceController() ServController.ServiceName = "CustomLogService" 

Properties and Methods of the ServiceController Class

There are several important properties of the service that you might be interested in testing. Table 1.3 shows some of the properties of the ServiceController class. The listed properties map to the properties of the ServiceBase class discussed in the first part of this chapter.

Table 1.3: Properties of the ServiceController Class

Property Name

Description

CanPauseAndContinue

True if the service can be paused and continued. (Read-only)

CanShutdown

True if the service should be notified when the system is shutting down. (Read-only.)

CanStop

True if the service can be stopped after it has started. (Read-only.)

DependentServices

Gets the set of services that depends on the service associated with this ServiceController instance.

DisplayName

A friendly name for the service.

MachineName

The name of the computer on which the service is running.

ServiceName

Identifies the service that this instance of the ServiceController references.

ServicesDependedOn

The set of services that this service depends on.

ServiceType

One of the following: Win32OwnProcess, Win32ShareProcess (these are the types that can be created in Visual Studio .NET). Other system services might show a service type of Adapter, FileSystemDriver, InteractiveProcess, KernelDriver, or RecognizerDriver.

Status

One of the following: StartPending, Running, StopPending, Stopped, PausePending, Paused, ContinuePending.

Remember, you use the properties of the ServiceBase class when you are creating a Windows service. The CanStop, CanPauseAndContinue, and CanShutdown properties of the ServiceBase class enable you to set the behavior for your service. In the ServiceController class, these properties are read-only. The ServiceController instance can only test the property to see what was set when the service was created.

When you are working programmatically with a service, it is good practice to always test the service’s state before you try an operation. For example, before you try to issue a Pause command to a service, test the CanPauseAndContinue property to see whether Pause is a valid action for that particular service:

If servController.CanPauseAndContinue = True Then    servController.Pause() End If

You also might want to test the current value of the Status property before issuing a command to change the status:

If servController.Status = _      ServiceControllerStatus.Paused Then         servController.Continue() End If

The only valid settings for the Status property are defined by the ServiceControllerStatus enumeration, as Intellisense in Visual Studio .NET will show you (see Figure 1.4).

click to expand
Figure 1.4: The ServiceControllerStatus enumeration

Table 1.4 lists the methods of the ServiceController class. These methods enable you to write code in a Visual Basic .NET application that can cause a Windows service application to start, stop, pause, or continue. Your code can also call custom commands and get other information about the service.

Table 1.4: Methods of the ServiceController Class

Method Name

Description

Close

Disconnects the ServiceController object from the service and releases any resources that were in use

Continue

Resumes a service after a paused command

ExecuteCommand

Executes a custom command on the service

GetDevices

Gets a list of device driver services on a computer

GetServices

Gets a list of services on a computer

Pause

Pauses the service

Refresh

Gets current property values

Start

Starts the service

Stop

Stops this service and any services that are dependent on this service

WaitForStatus

Waits for the service to reach the specified status or for the request to time out

The Start, Stop, Pause, and Continue methods are easy to understand. They work the same way in code that they work when you are issuing these commands through the Service Control Manager interface.

The Refresh method gets the current settings for the properties of the service that you are monitoring, without affecting the state of the service.

The GetServices and GetDevices methods populate an array of ServiceController objects, which in turn can access information about all the services installed on a computer (as shown in Listing 1.3). The GetDevices method gets those services that are of type KernelDriver or FileSystemDriver.

Listing 1.3 shows the procedure from the ServiceControllerProject demo that loads a ListBox control with the names of all services on the computer.

Listing 1.3: A Procedure to List All Services Running on the Local Computer

start example
Private Sub btnGetServices_Click(ByVal sender _      As_System.Object, ByVal e As System.EventArgs) _      Handles btnGetServices.Click         Dim servArray() As ServiceController         Dim i As Integer         servArray = ServiceController.GetServices()         lstDisplay.Items.Clear()         For i = 0 To servArray.Length - 1            lstDisplay.Items.Add(servArray(i).ServiceName)         Next         servArray = Nothing     End Sub
end example

The WaitForStatus method takes into consideration that sometimes a particular service might take a long time to start or not start at all. Also, StartPending, StopPending, PausePending, and ContinuePending will appear as the service’s status briefly, before they have completely reached a final state. You can test this with the ServiceControllerProject demo. After a service is stopped, click the Start button.

The display in the list box will show the status as StartPending. If you click the Get Properties button again a moment later, the display updates to show that the service now has a status of Running. If you select the check box labeled Wait Until Running, the code in the ServiceControllerProject demo will call the ServiceController object’s WaitForStatus method and the code will block until the target service achieves the specified status. The display does not update until the service’s status is Running. This is shown in the following code snippet:

If chkWait.Checked Then    servController.WaitForStatus( _       ServiceControllerStatus.Running) End If

You can also call the WaitForStatus method by specifying two parameters: the status to wait for and a TimeSpan value, which indicates how long your code should wait before it times out and reports an error condition.

Executing Custom Commands for a Service

The ServiceController class offers a method that enables you to define truly customized functionality for your Windows service application. You have seen how to add code to standard methods that will fire in the normal cycle of events, as a Windows service application is started and stopped. The ServiceController class provides a means to call custom methods that you have designed for your Windows service application.

Let’s return to the source code for your Windows service application named CustomLogService. You will add another event procedure to the service and then recompile and reinstall it.

When you create custom functionality for a Windows service, calls to any of your procedures are handled inside the single Windows service event procedure named OnCustomCommand. Inside this procedure, you can use a conditional test or Case statement to break out one or more groups of code that will be executed as part of a given command. The OnCustomCommand method accepts an integer parameter that indicates which section of code should be executed for any specific call to the method. The integer parameter must be within the range of 128 and 256. Values below 128 are reserved for system commands. If the AutoLog property of the service is True, calls to OnCustomCommand will be noted in the Windows Application event log.

The procedure inside your Windows Service application will look like Listing 1.4.

Listing 1.4: The OnCustomCommand Procedure

start example
Protected Overrides Sub OnCustomCommand( _   ByVal command As Integer)     Select Case command       Case 130         CustomEventLog.WriteEntry( _           "Command 130 successfully completed.")       Case 140         CustomEventLog.WriteEntry( _           "Command 140 successfully completed.")       Case 150         CustomEventLog.WriteEntry( _           "Command 150 successfully completed.")       Case Else         CustomEventLog.WriteEntry( _           "ERROR: Unrecognized command parameter!")     End Select End Sub
end example

For simplicity, your custom command does nothing more than write a log entry to verify that the command successfully completed. But that’s enough to test your code in the ServiceControllerProject demo.

After you have the code in the Windows service application, you can write a method in your ServiceController application that calls the ServiceController.ExecuteCommand method. The ServiceControllerProject demo has a simple user interface that calls the method and passes a user-selected integer parameter (see Figure 1.5). As you can see from Listing 1.4, the OnCustomCommand method will recognize three valid parameter values: 130, 140, and 150. If any other value is passed, an error message will be written to the custom event log.


Figure 1.5: Executing a custom command from the ServiceControllerProject demo

Listing 1.5 shows the code from the ServiceControllerProject demo that calls the Execute command method:

Listing 1.5: Executing a Custom Command

start example
Private Sub btnCommand_Click(ByVal sender As _    System.Object, ByVal e As System.EventArgs) _    Handles btnCommand.Click         Dim commandNumber As Integer         servController = New _            ServiceController("CustomLogService")         Try            commandNumber = CType(txtCommand.Text, Integer)             servController.ExecuteCommand(commandNumber)             MessageBox.Show("Command completed. " & _                "Check the Custom event log.")         Catch ex As Exception             MessageBox.Show("Invalid command number.")         End Try     End Sub
end example

One important thing to remember about calling a custom command on a Windows service is that all error handling must be done within the Windows service application itself. In this simple example, our “error handling” consisted of writing an error message to the event log. In a real-world application, you will need to consider your error handling carefully. The error handling implemented in the ServiceController client application guards only against sending a nonnumeric value as a parameter to the call to ExecuteCommand.

In Exercise 1.4, you will load the ServiceControllerProject demo and try some of its features that were discussed in this section.

Exercise 1.4: Trying the ServiceController Demo Project

start example

On the CD included with this book, you will find a Visual Basic .NET project titled ServiceControllerProject. Open this project in Visual Studio .NET.

  1. If you have already created the CustomLogService (see Exercise 1.2), the ServiceControllerProject will immediately display information about the service when you first run it. If you do not have a service named CustomLogService installed, you will get an error message. If you get this message, type in the name of a valid service, such as ClipBook. Then click the Get Properties button.

  2. Experiment with the Stop and Start buttons. You might also want to open the Service Control Manager and watch the service status changing there as well. You will need to refresh the display in the Service Control Manager each time you change the status by using the Visual Basic .NET application.

    Note 

    Because the CanPauseAndContinue property of CustomLogService is set to False, the Pause and Continue buttons are disabled.

  3. Notice that when you stop and then start the CustomLogService, the status that is displayed is StartPending. If you click the Get Properties button again a few seconds later, you will see the status is now Running.

  4. Select the Wait Until Running check box; then stop and start the service again. This time the ListBox display will not be updated until the service has been fully started and the status has reached Running.

  5. Type in the name of a different service, such as EventLog, and view its properties. Remember, do not stop the system services or services you didn’t create (especially if you’re not sure what the service does); doing so can cause problems with your computer.

  6. The Service Lists menu displays another form, where you can see a list of all the services installed on your computer. The GetDevices method shows all installed services that are device drivers.

  7. Finally, the Execute Commands menu displays one more form. This form contains code to execute custom commands against CustomLogService. You can’t test this feature yet. In the next exercise, Exercise 1.5, you will modify CustomLogService to accept custom commands.

end example

In Exercise 1.5, you will uninstall and modify the CustomLogService you created in Exercise 1.2. To uninstall the CustomLogService, you will be using the Windows Control Panel application Add/Remove Programs. While looking at the list of installed applications on your computer, you will see only the entry for the setup program that installs the service. You will not see an entry for the service itself.

Exercise 1.5: Uninstalling and Modifying CustomLogService

start example
  1. Start the Windows Control Panel application Add/Remove programs. Remove CustomLogSetup.

  2. Verify that CustomLogService is no longer installed by checking the Service Control Manager. Right-click on Services (local) and choose Refresh.

  3. Open the CustomLogService solution in Visual Studio .NET (it should contain both the service and setup projects).

  4. Add the following method to CustomLogService.vb. Add this code directly after the OnStart and OnStop methods (refer to the following screen capture):

    click to expand

    Protected Overrides Sub OnCustomCommand(ByVal command As Integer)    Select Case command      Case 130        CustomEventLog.WriteEntry( _           "Command 130 successfully completed.")      Case 140        CustomEventLog.WriteEntry( _           "Command 140 successfully completed.")      Case 150        CustomEventLog.WriteEntry( _           "Command 150 successfully completed.")      Case Else        CustomEventLog.WriteEntry( _           "ERROR: Unrecognized command parameter!")    End Select End Sub 

  5. Save the solution. Right-click the CustomLogService project in the Solution Explorer and chose Build. Then right-click the CustomLogSetup project and choose Build.

  6. Go to the Debug subdirectory under the CustomLogSetup project directory. Double-click the CustomLogSetup.msi file to install the revised version of the service.

  7. Use the ServiceControllerProject demo that you used in Exercise 1.4 to verify that the CustomLogService is once again installed on your computer.

  8. Start the CustomLogService.

  9. Go to the Execute Commands form in the ServiceControllerProject demo and test execution of the custom commands. Try the valid parameter numbers 130, 140, and 150 and then try an invalid number, such as 155.

  10. Open the Windows Event Viewer and look at the entries. Double-click an entry to display the Properties dialog box and view the message.

end example



MCAD/MCSD(c) Visual Basic. NET XML Web Services and Server Components Study Guide
MCAD/MCSD: Visual Basic .NET XML Web Services and Server Components Study Guide
ISBN: 0782141935
EAN: 2147483647
Year: 2005
Pages: 153

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