Recipe 10.21. Viewing the Antecedent and Dependent Services for a Service


Problem

You want to view the services that a particular service depends on (i.e., antecedent services) and services that are dependent on that service. This is helpful to know when you want to stop a service and determine the impact it would have on other services.

Solution

Using a graphical user interface

  1. Open the Services snap-in.

  2. In the left pane, double-click on the service you want to view

  3. Click the Dependencies tab.

Using a command-line interface

The following command displays the services that depend on a service:

> sc enumdepend <ServiceName>

The following command displays the services that a service depends on:

> sc qc <ServiceName>

Using downloadable software

You can also use the Sysinternals psservice command to enumerate dependencies:

> psservice <ServiceName> depend

Using VBScript
' This code lists the antecedent and dependent services for a service ' ------ SCRIPT CONFIGURATION ------ strService = "<ServiceName>"  ' e.g. TapiSrv strComputer = "<HostName>"    ' e.g. wks01 (use . for local system) ' ------ END CONFIGURATION --------- set objWMI = GetObject("winmgmts:\\" & strComputer & "\root\cimv2") set colServices = objWMI.ExecQuery("Associators of " _                       & "{Win32_Service.Name='" & strService & "'} Where " _                       & "AssocClass=Win32_DependentService Role=Antecedent" ) WScript.Echo "Antecedent services for " & strService & ":" for each objService in colServices    Wscript.Echo vbTab & objService.DisplayName  next WScript.Echo  set colServices = objWMI.ExecQuery("Associators of " _                       & "{Win32_Service.Name='" & strService & "'} Where " _                       & "AssocClass=Win32_DependentService Role=Dependent" ) WScript.Echo "Dependent services for " & strService & ":" for each objService in colServices    Wscript.Echo vbTab & objService.DisplayName  next

A practical use of enumerating dependencies is for programmatically restarting a service. You could just call the Stop and Start methods on a service as we showed in Recipe 10.16, but if you tried to restart a service that had a dependency, the restart would fail. An alternative is to write a bit of code that can handle restarting services, regardless of dependencies. Here is that code:

' This code restarts a service by first stopping all ' dependent services before stopping the target service. ' Then the target service is started and all dependent  ' services are started. Option Explicit ' ------ SCRIPT CONFIGURATION ------ Dim strComputer : strComputer = "."        ' e.g. fs-rtp01 Dim strSvcName  : strSvcName  = "Alerter"  ' e.g. dnscache ' ------ END CONFIGURATION --------- Dim objWMI : set objWMI = GetObject("winmgmts:\\" & strComputer & _                                     "\root\cimv2") Dim objService: set objService = objWMI.Get("Win32_Service.Name='" & _                                             strSvcName & "'") WScript.Echo "Restarting " & objService.Name & "..." RecursiveServiceStop  objService RecursiveServiceStart objService WScript.Echo "Successfully restarted service" Function RecursiveServiceStop ( objSvc )     Dim colServices : set colServices = objWMI.ExecQuery("Associators of " _                  & "{Win32_Service.Name='" & objSvc.Name & "'} Where " _                  & "AssocClass=Win32_DependentService Role=Antecedent" )    Dim objS    for each objS in colServices       RecursiveServiceStop objS    next    Dim intRC : intRC = objSvc.StopService    if intRC > 0 then       WScript.Echo " Error stopping service: " & objSvc.Name       WScript.Quit    else        WScript.Echo " Successfully stopped service: " & objSvc.Name    end if End Function Function RecursiveServiceStart ( objSvc )    Dim intRC : intRC = objSvc.StartService    if intRC > 0 then       WScript.Echo " Error starting service: " & objSvc.Name       WScript.Quit    else       WScript.Echo " Successfully started service: " & objSvc.Name    end if    Dim colServices : set colServices = objWMI.ExecQuery("Associators of " _                  & "{Win32_Service.Name='" & objSvc.Name & "'} Where " _                  & "AssocClass=Win32_DependentService Role=Antecedent" )    Dim objS    for each objS in colServices       RecursiveServiceStart objS    next End Function

Discussion

Service dependencies play a role in how you can stop a service. For example, if ServiceA depends on ServiceB, then ServiceB must be running before ServiceA can start. Similarly, ServiceB cannot be stopped until ServiceA is stopped due to the dependency. A good practical example of this is the Logical Disk Manager Administrative service. It depends on the Logical Disk Manager service. It wouldn't make a lot of sense for the administrative service to be running, while the underlying disk manager service (the thing it manages) was not.

Service dependences are configured in each service's Registry entry. In the case of the Logical Disk Manager Administrative service, you can find its Registry entry in the following key:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\dmadmin

If you open Registry Editor (regedit.exe) and look at that key, you'll see a DependOnService value. The data for this REG_MULTI_SZ value is a list of the services it depends on. One of them is dmserver, which corresponds to the Logical Disk Manager service.

You may also see a DependOnGroup value under a service's Registry key. This is similar to DependOnService except that DependOnGroup corresponds to a group of services. For more on service groups, check out Recipe 10.22.

Using VBScript

To enumerate dependencies, we need to use something called a WMI associator. The Associators of clause in a WQL query is similar to a table join in a relational database. It allows you to relate two different types of classes. For services, WMI supports a class called Win32_DependentService, which defines the service dependencies for a given service. The first query finds all of the antecedent services (those that depend on the target service). Here is the query:

"Associators of {Win32_Service.Name='" & strService & "'} Where " _     "AssocClass=Win32_DependentService Role=Antecedent"

The Associators of clause tells WMI we are going to associate or join another class to the one specified within the curly braces. We set Win32_Service.Name equal to the target service. The Where clause then has two parts. The first sets the associated class, which in this case is Win32_DependentService; the second part (Role=Antecedent) limits the dependent services that are returned to just antecedent services, or ones that depend on the target service. The only difference with the second query is that the query sets Role=Dependent, which returns all of the dependent services of the target service.

In the service restart example, you have to stop all services that are dependent on the service and then stop the service itself. Then to start the service, you have to start the service followed by all dependent services. And that is exactly what that code does. It makes use of a couple of recursive functions that walk through all of the dependent services.



Windows XP Cookbook
Windows XP Cookbook (Cookbooks)
ISBN: 0596007256
EAN: 2147483647
Year: 2006
Pages: 408

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