6.2. Auditing System ServicesMany of the subsystems running on a Windows machine run as background processes, known as services, that have no direct interaction with a user's session. The components that exist as services are varied and include everything from the application-level Internet Information Services (IIS) and DNS Server to system plumbing of the Remote Procedure Call (RPC) and logon infrastructure. Services can be configured, started, and stopped from within the Services Administrative Tool , and command-line control of system services is available through the net start and net stop commands, as well as the sc.exe tool. MSH offers several cmdlets that complement the existing management tools and allow scripts to discover, interrogate, and manage the state of services within the shell in a consistent fashion. 6.2.1. How Do I Do That?Let's start by getting a picture of the different services registered with the system. The get-service cmdlet, when called with no options, generates a list of all registered services, including their present state: MSH D:\MshScripts> get-service Status Name DisplayName ------ ---- ----------- Stopped Alerter Alerter Stopped ALG Application Layer Gateway Service Stopped AppMgmt Application Management Stopped aspnet_state ASP.NET State Service Running AudioSrv Windows Audio Stopped BITS Background Intelligent Transfer Ser... Stopped Browser Computer Browser Running CcmExec SMS Agent Host Stopped CiSvc Indexing Service Stopped ClipSrv ClipBook Stopped COMSysApp COM+ System Application Running CryptSvc Cryptographic Services Running DcomLaunch DCOM Server Process Launcher Stopped Dfs Distributed File System Running Dhcp DHCP Client Stopped dmadmin Logical Disk Manager Administrative... Running dmserver Logical Disk Manager Running Dnscache DNS Client ... Given the long list of services registered (note that not all are running), it's convenient to use where-object to reduce the list to active services only. get-service will optionally take a service name, which can include wildcard characters: MSH D:\MshScripts> get-service | where-object { $_.Status -eq "Running" } Status Name DisplayName ------ ---- ----------- Running AudioSrv Windows Audio Running CcmExec SMS Agent Host Running CryptSvc Cryptographic Services Running DcomLaunch DCOM Server Process Launcher Running Dhcp DHCP Client Running dmserver Logical Disk Manager Running Dnscache DNS Client Running ERSvc Error Reporting Service Running Eventlog Event Log Running EventSystem COM+ Event System Running helpsvc Help and Support ... MSH D:\MshScripts> get-service t* Status Name DisplayName ------ ---- ----------- Stopped TapiSrv Telephony Running TermService Terminal Services Stopped Themes Themes Stopped TlntSvr Telnet Stopped TrkSvr Distributed Link Tracking Server Running TrkWks Distributed Link Tracking Client Stopped Tssdis Terminal Services Session Directory Let's take a look at the Telnet service (TlntSvr) to see what additional information we can extract from get-service: MSH D:\MshScripts> $telnet=get-service tlntsvr MSH D:\MshScripts> $telnet | format-list Name : TlntSvr DisplayName : Telnet Status : Stopped DependentServices : {} ServicesDependedOn : {RPCSS, NTLMSSP, TCPIP} CanPauseAndContinue : False CanShutdown : False CanStop : False ServiceType : Win32OwnProcess On this machine, we can see that the service, as well as some information about related services, is currently stopped. Because the ServicesDependedOn property is actually a list of other related services, let's have MSH show the running status of each of the services that Telnet needs in order to start: MSH D:\MshScripts> foreach ($dependency in $telnet.ServicesDependedOn) { >>write-host "$($dependency.Name) is $($dependency.Status)" >>} >> RPCSS is Running NTLMSSP is Stopped TCPIP is Running On this machine, the Telnet service is not just stopped, it's actually disabled. MSH provides the set-service cmdlet for changing service configuration. In this case, we can use the -StartupType option to put the service in a position in which it can be started and use start-service to get it running. The stop-service cmdlet is used to terminate a running service and bring it back to a stopped state: MSH D:\MshScripts> set-service TlntSvr -StartupType Manual MSH D:\MshScripts> start-service TlntSvr # telnet service running MSH D:\MshScripts> stop-service TlntSvr
6.2.2. What Just Happened?The get-service cmdlet generates a series of ServiceController objects and pumps them into the pipeline. Each object contains a set of information about the service it represents, as well as a set of methods for basic service control. The start-service and stop-service cmdlets will try to make changes to the running state of a service but are still subject to the rules of the services system. In other words, trying to start a disabled service will still result in a failure, as will trying to stop a required service. Although it's tempting to run through the list of services a particular service depends on, starting each in turn, it is unnecessary. When a request to start a service is made, Windows is able to determine which services are needed and will start any stopped ones as appropriate. Both the DependentServices and ServicesDependedOn properties are useful for understanding the relationships between the different services, but it is rarely necessary to start and stop dependent services manually. set-service gives the script author the ability to update service configuration from within MSH and is a great candidate for inclusion in machine setup or deployment scripts. Exercising caution around services is recommended: starting, stopping, or disabling services without planning can cause applications and functionality to break without warning. In addition to the service-related cmdlets we saw here, there are also cmdlets for restarting (restart-service), suspending (suspend-service), and registering a service with the service subsystem (new-service). 6.2.3. What About...... Using get-service to check whether services are running before running a script? Yes; with a short foreach loop at the start of the script, it's easy to check that a list of required services is running before executing the main body. In the pseudoscript in Example 6-2, an array is used to store the list of services to be checked, and the script will exit if any of them are not in a running state. Example 6-2. Checking for dependent services for running a script$requiredServices = @("w3svc", "iisadmin", "messenger") foreach ($serviceName in $requiredServices) { $service = get-service $serviceName if ($service.Status -ne "Running") { "$serviceName not running!" exit } } # script is good to continue 6.2.4. Where Can I Learn More?More information on *-service cmdlets is available through get-help. The Services management snap-in (available in Control Panel, Administrative Tools) also contains a help system with an overview and list of standard Windows services. |