Scripting Games 2012 comments: #4 Beginners Event 2
Second event is to find running services that can be stopped
http://blogs.technet.com/b/heyscriptingguy/archive/2012/04/03/2012-scripting-games-beginner-event-2-find-stoppable-running-services.aspx
Lets start with the requirements we can pick out of the event information:
- Find all services that are running that will accept a Stop Command
- Need to run remotely against trusted remote computers
- Assume appropriate ports are open of firewalls
- Don’t need a second computer
- Don’t need to test or configure firewall – assume its done
- Use simplest command that will work
- Can use standard aliases – don’t have to
- Don’t use non-standard aliases
So what do we have that can work with services
PS> Get-Command *service
CommandType Name
----------- ----
Cmdlet Get-Service
Cmdlet Invoke-WebService
Cmdlet New-Service
Cmdlet Restart-Service
Cmdlet Resume-Service
Cmdlet Set-Service
Cmdlet Start-Service
Cmdlet Stop-Service
Cmdlet Suspend-Service
Get-Service looks a likely contender and it has a computername parameter
PS> Get-Help Get-Service -Parameter c*
-ComputerName <string[]>
Gets the services running on the specified computers. The default is the local computer.
Type the NetBIOS name, an IP address, or a fully qualified domain name of a remote computer. To specify the local computer, type the computer name, a dot (.), or "localhost".
This parameter does not rely on Windows PowerShell remoting. You can use the ComputerName parameter of Get-Service even if your computer is not configured to run remote commands.
Required? false
Position? named
Default value Localhost
Accept pipeline input? true (ByPropertyName)
Accept wildcard characters? false
Can we find out if services can be stopped
PS> get-service | Get-Member -MemberType property
TypeName: System.ServiceProcess.ServiceController
Name MemberType
---- ----------
CanPauseAndContinue Property
CanShutdown Property
CanStop Property
Container Property
DependentServices Property
DisplayName Property
MachineName Property
ServiceHandle Property
ServiceName Property
ServicesDependedOn Property
ServiceType Property
Site Property
Status Property
Looks like the Canstop will work for us. Its a Boolean i.e. only returns True or False so we have a little trick. Normally when we want to filter we use a where statement
get-service | where {$_.Status -eq "Running"}
The only objects that are passed along the pipeline are the ones where the filter evaluates to TRUE. So you might think this would work
get-service | where {$_.Canstop -eq "True"}
but check out this
PS> $true -eq "False"
True
What’s happening is that $_.CanStop is a Boolean so triggers the filter – the “-eq ‘True’” bit is ignored.
If you want to test Booleans use PowerShell’s $true & $false
get-service | where {$_.Canstop -eq $true}
or better still because CanStop is a Boolean we can just do a simple test
get-service | where {$_.Canstop}
To use the computer name
Get-Service -ComputerName $env:COMPUTERNAME | where {$_.Canstop }
see http://msmvps.com/blogs/richardsiddaway/archive/2012/04/11/scripting-games-2012-comments-3-beginners-event-1.aspx for a discussion on accessing the local machine using a computer name
At this point you may be asking but the scenario says we have to return running services that can be stopped. Look at the output when you use CanStop – all the statuses are running.
It can be tested like this
Compare-Object -ReferenceObject $(get-service | where {$_.Canstop}) -DifferenceObject $(get-service | where {$_.Status -eq "Running" -and $_.Canstop}) –IncludeEqual
You will get a bunch of answers like this
InputObject SideIndicator
----------- -------------
System.ServiceProcess.ServiceController ==
Which means they match
What about remote machines
Get-Service -ComputerName "Win7", "Win7test", "webr201" |
where {$_.Canstop }
will work but we don’t know which service is returned from which machine however there is a machine name property available so we could do this
Get-Service -ComputerName "Win7", "Win7test", "webr201" |
where {$_.Canstop } |
select Status, Name, Displayname, MachineName
or if you want a nice report format
Get-Service -ComputerName "Win7", "Win7test", "webr201" |
where {$_.Canstop } |
sort MachineName, Name |
Format-Table -GroupBy MachineName –AutoSize
The alternative is to use PowerShell remoting
Invoke-Command -ComputerName "Win7", "Win7test", "webr201" -ScriptBlock {
Get-Service |
where {$_.Canstop } }
This automatically gives the computername so we can do this
Invoke-Command -ComputerName "Win7", "Win7test", "webr201" -ScriptBlock {
Get-Service |
where {$_.Canstop } } |
Format-Table -GroupBy PSComputerName –AutoSize
In PoweShell v3 the syntax can be simplified
Get-Service | where CanStop
When you have a single property to test you can drop the $_ and {}
This can be aliased to
gsv | ? canstop
which must be esoteric enough for the most fanatical of alias’ fans.
If you must the other versions can be aliased
gsv -cn "Win7", "Win7test", "webr201" |
? {$_.Canstop} |
select Status, Name, Displayname, MachineName
or
icm -Cn "Win7", "Win7test", "webr201" -Sc {
gsv |
? {$_.Canstop } } |
ft -G PSComputerName –A