I l @ ve RuBoard |
Services are often configured to start automatically with the operating system, although an administrator can start and stop a service using the Services console in Control Panel. (In Control Panel, click Performance and Maintenance, click Administrative Tools, and then double-click Services.) You can also control services programmatically if you have the appropriate access rights ”the assembly must be granted System.ServiceProcess.ServiceControllerPermission , which by default is denied to all assemblies other than those loaded from the local computer. Displaying Service InformationThe key to manipulating services with the Microsoft .NET Framework is to use the System.ServiceProcess.ServiceController class. A ServiceController object caches information about a particular service and makes this information available through a series of properties, which we'll examine in this section. The ServiceController class also provides methods that you can use to change the state of a service (start it, stop it, pause it, and so on). Note You must add a reference to the System.ServiceProcess.dll assembly in order to use the ServiceController class. The ServiceForm Windows Form (which is available in ControllerForm.jsl in the ServiceForm project) shows the ServiceController class in action. Its function mimics the Services console in Control Panel in that it lists all the services running on the local computer and allows you to start and stop services. (The data is displayed in a raw format, and you cannot change the properties of a service, unlike with the Services console). Figure 15-1 shows the application running. Figure 15-1. The ServiceForm application, showing the services executing on the local machine
The form comprises a DataGrid control called serviceGrid for displaying the services, two buttons for starting and stopping a selected service, and a status bar for reporting any errors as services are started and stopped . If you examine the code in the ControllerForm class (this is the main form of the application), you'll see that we've declared an array of ServiceController objects: importSystem.ServiceProcess.*; publicclassControllerFormextendsSystem.Windows.Forms.Form { privateServiceController[]services; The ControllerForm constructor populates the services array by calling the static GetServices method of the ServiceController class. GetServices is overloaded; the version used here retrieves the services installed on the local computer, but you can also supply the name of a machine as a String , and GetServices will return the services installed on that computer instead ( assuming you have the appropriate access rights). The service information is displayed in the data grid using the SetDataBinding method, as shown below. This is a convenient way of binding the data in any data source to a data grid, and will render each item in the array or collection as rows in the grid. Each row will comprise one or more columns, derived from the fields of the data source. The data in the individual columns of the data grid is generated by executing the ToString method over each field in the data source. publicControllerForm() { services=ServiceController.GetServices(); serviceGrid.SetDataBinding(services,null); } Note A data source can comprise several data members . The second parameter of SetDataBinding indicates which specific data member should be used. In the case of a simple collection or array, you can specify a null value for this parameter. If you want more information about the DataGrid control, look up the System.Windows.Forms.DataGrid class in the Visual Studio .NET documentation. There are actually two classes of service available under Windows ”those that implement device drivers (modems, CD-ROM, hard disks, network cards, and so on) and those that don't. The GetServices method returns a list of non “device driver services. If you want to retrieve a list of device driver services, execute the GetDevices method instead. The properties of the ServiceController class displayed in the data grid are (in order of importance):
Although it is not displayed in the data grid, the ServiceController class also has a MachineName property. This is a String that specifies the machine the service is running on. Starting and Stopping a ServiceThe Start and Stop buttons start and stop a selected service; the user selects a service in the data grid and then clicks the appropriate button. The Click event handlers behind each button contain the necessary code. The startButton_Click method determines which service the user selected by retrieving the value of the CurrentRowIndex property of the data grid. (The data grid is zero-based ”the first row in the grid being row 0.) The program then obtains the current state of the service by querying the Status property of the ServiceController object at the identified offset in the services array: privatevoidstartButton_Click(System.Objectsender,System.EventArgse) { intserviceNum=serviceGrid.get_CurrentRowIndex(); ServiceControllerStatusstatus=services[serviceNum].get_Status(); The value returned will be a member of the System.ServiceProcess.ServiceControllerStatus enumeration. Table 15-1 describes the values in this enumeration. Note that a service can accept requests for work only when it is in the Running state. Table 15-1. ServiceControllerStatus Values
A service can be asked to start running only if it is in the Stopped state. The startButton_Click method therefore checks that this is the case before attempting to start the service; if the service is not in the Stopped state, this method will report a warning in the status bar at the bottom of the form: if(status==ServiceControllerStatus.Stopped) { //Starttheservice } else { statusBar.set_Text("Serviceisalreadyrunning"); } Starting a service can take a little time (up to 30 seconds), so the startButton_Click method changes the cursor to an hourglass and then sends a Start request to the service using the Start method of the ServiceController : Cursorcurs=Cursor.get_Current(); Cursor.set_Current(Cursors.get_WaitCursor()); services[serviceNum].Start(); The Start method completes when the signal has been passed to the service, but it does not wait until the service has started. You can suspend execution while a service starts using the WaitForStatus method. (You can optionally specify a TimeSpan timeout value.) The startButton_Click method waits for the service to reach the Running state before continuing: services[serviceNum].WaitForStatus(ServiceControllerStatus.Running); When the startButton_Click method resumes, it updates the status bar, refreshes the data grid, and restores the cursor: statusBar.set_Text("Servicestartedsuccessfully"); services=ServiceController.GetServices(); serviceGrid.SetDataBinding(services,null); serviceGrid.set_CurrentRowIndex(serviceNum); Cursor.set_Current(curs); The stopButton_Click method is called when the user clicks the Stop button. The technique used to stop a service is similar to that used for starting it, with one subtle difference: You can stop a service that is in a variety of states, but not all services allow you to stop them. So, rather than checking that the service is in a particular state, the stopButton_Click method examines the CanStop property of the ServiceController and proceeds only if CanStop is true: if(services[serviceNum].get_CanStop()) { //Stoptheservice } else { statusBar.set_Text("Serviceisalreadystopped,ordoesnot supportstopping"); } |
I l @ ve RuBoard |