Managing Windows Services with PowerShell

Original author: Jeffery Hicks

We’re starting the translation series on managing Windows services with PowerShell 2.0 and 3.0.
This post will cover the following Windows service management issues:
  • Get the status of the service on the local computer
  • Getting the status of a service on a remote computer
  • Filtering services (for example, stopped services)
  • Dependent Services


Let us indicate the initial conditions: you work under Windows 7 and higher and you have administrator rights. All commands are recommended to be performed in a laboratory or virtual environment, before being used in “field conditions”.

GET THE STATUS OF THE SERVICE



Let's start by simply getting the status of all services running on the local computer. We use the Get-Service cmdlet for this .

PS C:\> get-service


PowerShell is generally not case sensitive. The conclusion is shown in the screenshot below.



Each line represents a service object. Each service object usually has its own properties. You can open them by simply passing these objects to another command, Get-Member .

PS C:\> get-service | get-member


The results are shown in the screenshot below.



The Typename parameter at the top indicates what kind of object is in front of us; in this case, it is System.ServiceProcess.ServiceController. The screenshot also outlines the properties of the object. These are the attributes that describe this type of object. Although most of them are not used in the default display, you can use them if you know them.
For example, we are interested in seeing information only about Windows Update. Through Get-Service we get information about only some of its properties.

PS C:\> get-service wuauserv | select Displayname,Status,Can*
DisplayName : Windows Update
Status : Stopped
CanPauseAndContinue : False
CanShutdown : False
CanStop : False
How did I know that I can print the name of the service? Looked using Get-Service.
PS C: \> help get-service



You can get full help information by typing:

PS C:\> help get-service –full


Information about the service can be obtained by its name or even the initial letters of the name.

PS C:\> get-service wi*
Status Name DisplayName
------ ---- -----------
Stopped WiaRpc Still Image Acquisition Events
Running WinDefend Windows Defender Service
Running WinHttpAutoProx... WinHTTP Web Proxy Auto-Discovery Se...
Running Winmgmt Windows Management Instrumentation
Running WinRM Windows Remote Management (WS-Manag...


Or if you are more comfortable working with display names, use the –Displayname parameter .

PS C:\> get-service -DisplayName "windows a*"
Status Name DisplayName
------ ---- -----------
Stopped AllUserInstallA... Windows All-User Install Agent
Running AudioEndpointBu... Windows Audio Endpoint Builder
Running Audiosrv Windows Audio


I have to use the parameter name so that PowerShell treats the values ​​as the display name and not the actual name of the service. The command will look like this:

PS C:\> get-service "windows a*"


The –Name parameter can be omitted .

GET THE STATUS OF SERVICE ON REMOTE COMPUTERS



Before that, we were interested in obtaining information about the status of services on the local computer. However, services are managed on remote computers. If you look at Get-Service help , you can see if this cmdlet has the –Computername parameter . In this case, the connection to the remote computers is performed without enabling the PowerShell remote management function. If you can manage services using the command line tools (sc.exe or the Service Manager management console), you can use PowerShell. Let's take a look at an example:

PS C:\> get-service spooler -ComputerName novo8
Status Name DisplayName
------ ---- -----------
Running spooler Print Spooler


Any command I demonstrated can be used to transfer to a remote computer. Even multiple computers, if you have the appropriate rights on the remote computer. If you use PowerShell v3, you can easily select one service on multiple computers.

PS C:\> get-service wuauserv -ComputerName chi-dc01,chi-dc02,chi-dc03
Status Name DisplayName
------ ---- -----------
Running wuauserv Windows Update
Stopped wuauserv Windows Update
Running wuauserv Windows Update


For clarity, format the output.

PS C:\> get-service wuauserv -ComputerName chi-dc01,chi-dc02,chi-dc03 | format-table Name,Status,Machinename -autosize
Name Status MachineName
---- ------ -----------
wuauserv Running chi-dc03
wuauserv Stopped chi-dc02
wuauserv Running chi-dc01


The same result, but in PowerShell v2.

PS C:\> 'chi-dc01','chi-dc02','chi-dc03'| foreach {get-service wuauserv -computername $_} | Format-Table Name,Status,Machinename -AutoSize
Name Status MachineName
---- ------ -----------
wuauserv Running chi-dc01
wuauserv Stopped chi-dc02
wuauserv Running chi-dc03


IMPLEMENTING FILTRATION (USING WHERE-OBJECT)



Services are filtered by using the Where-Object cmdlet (where is the shortcut for the cmdlet). All we need from PowerShell in this case is to get only those services whose status is “stopped”.

PS C:\> get-service | where {$_.status -eq 'stopped'}


PowerShell receives information about all services and passes them (using “|”) to the next command, which scans each object. If the status property of the object is “stopped”, it remains in the pipeline, otherwise it is excluded from it. At the end, the PowerShell expression displays those objects that remain in the pipeline.
The results are shown below.



Now let's try to find one service on several machines. Format the output to a table.

PS C:\> get-service -computername @('chi-dc01','chi-dc02','chi-dc03') | where {$_.name -eq 'wuauserv'} | format-table Name,Status,Machinename -autosize
Name Status MachineName
---- ------ -----------
wuauserv Running chi-dc02
wuauserv Running chi-dc01
wuauserv Running chi-dc03


We can even combine the request of individual services with their filtering.

PS C:\> get-service "win*" -comp chi-dc03 | where {$_.status -eq 'running'}
Status Name DisplayName
------ ---- -----------
Running Winmgmt Windows Management Instrumentation
Running WinRM Windows Remote Management (WS-Manag...


This command finds all services on computer CHI-DC03 that start with 'WIN', but displays only those that are running.
You can also group objects according to their status property.

PS C:\> $dc03 = get-service -computername chi-dc03 | Group-Object -Property Status


The variable $ dc03 is a GroupInfo object.

PS C:\> $dc03
Count Name Group
----- ---- -----
64 Running {System.ServiceProcess.ServiceController, Sy...
79 Stopped {System.ServiceProcess.ServiceController, Sy...


The Group property is a collection of related services.

PS C:\> $dc03.Get(0).group


The above is easier to understand if you look at the screenshot.



For me, I'd rather use a hash table.

PS C:\> $hash = get-service -computername chi-dc03 | Group-Object -Property Status -AsHashTable
PS C:\> $hash
Name Value
---- -----
Running {System.ServiceProcess.ServiceController, Sys...
Stopped {System.ServiceProcess.ServiceController, Sys...


Now each name represents a property in the hash table. If you have experience with PoweShell, you are probably considering doing the following:

PS C:\> $hash.running.count


However, nothing will happen. Because the Status property is just an enumeration for the [System.ServiceProcess.ServiceControllerStatus] .NET class and properties like Running and Stopped are integers. PowerShell performs the conversion to present in a more visual form.

PS C:\> $hash = get-service -computername chi-dc03 | Group-Object -Property Status –AsHashTable –AsString


What is the essence of the –AsString parameter, in my opinion, is quite obvious. Now working with the hash table has become easier.

PS C:\> $hash.running.count
62
PS C:\> $hash.running[0..3]
Status Name DisplayName
------ ---- -----------
Running ADWS Active Directory Web Services
Running AppHostSvc Application Host Helper Service
Running BFE Base Filtering Engine
Running BrokerInfrastru... Background Tasks Infrastructure Ser...


The next task on the agenda is to check server dependencies.

Required Services


PowerShell makes it easy to get the status of all the services that are required for a given service, even on a remote computer.

PS C:\> get-service dns -ComputerName chi-dc03 –RequiredServices
Status Name DisplayName
------ ---- -----------
Running Afd Ancillary Function Driver for Winsock
Running Tcpip TCP/IP Protocol Driver
Running RpcSs Remote Procedure Call (RPC)
Running NTDS Active Directory Domain Services


The –RequiredServices parameter will pass the object to the pipeline for each required service. You can even go further and check the required services for this service to work.

PS C:\> get-service dns -ComputerName chi-dc03 -RequiredServices | select name,@{name="computername";expression={$_.machinename}} | get-service -RequiredServices
Status Name DisplayName
------ ---- -----------
Running RpcEptMapper RPC Endpoint Mapper
Running DcomLaunch DCOM Server Process Launcher


The –Computername parameter of the Get-Service cmdlet will take the output, but only for those objects that have an object with the Computername property — which is why I use a hash table with Select-Object. As we can see, there are no problems with the DNS service on the CHI-DC03 computer.

DEPENDENT SERVICES



We can do the same with dependent services. If there are none, nothing will be transferred to the conveyor.

PS C:\> get-service dns -ComputerName chi-dc03 -DependentServices
PS C:\> get-service lanmanworkstation -ComputerName chi-dc03 -DependentServices
Status Name DisplayName
------ ---- -----------
Stopped SessionEnv Remote Desktop Configuration
Running Netlogon Netlogon
Running Dfs DFS Namespace
Running Browser Computer Browser


Required and dependent services are also part of each service object.

PS C:\> get-service rpcss | Select *services
RequiredServices DependentServices
---------------- -----------------
{RpcEptMapper, DcomLaunch} {WwanSvc, wuauserv, WSearch, wscsvc...}


In the meantime, you can get all the dependencies for all services, the following command

PS C:\> get-service –DependentServices


This will not give you particularly useful information, so I recommend that you make a request for specific services. The team works much better than PowerShell v3.

PS C:\> get-service dns -comp chi-dc01,chi-dc03 -RequiredServices | Sort Machinename,Name | Format-table -GroupBy machinename


The results are visible in the screenshot below.



To get similar results in PowerShell v2, you have to pass the names of the computers (computernames) to Get-Service.
PS C:\> "chi-dc01","chi-dc03" | foreach { get-service dns -comp $_ -RequiredServices} | Sort Machinename,Name | format-table -GroupBy machinename


The following article will start, stop, and restart services.
The end of the translation.

Upd:
The post contains translations of articles from the 4sysops.com portal
Managing Services the PowerShell way - Part 1
Managing Services the PowerShell way - Part 2

P.S. We also want to share our free program for managing Windows services - NetWrix Service Monitor. The program monitors all automatically launched services on a group of servers and, in the event of a sudden failure of one or more of them, sends notifications by e-mail. The restart function ensures that all controlled services will operate without downtime. The program is easy to configure: install, enter computer names and specify the desired email address.

Also popular now: