header image

Scripting Games 2012 comments: #4 Beginners Event 2

Posted by: | April 12, 2012 | No Comment |

Second event is to find running services that can be stopped


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"

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


icm -Cn "Win7", "Win7test", "webr201" -Sc {
gsv |
? {$_.Canstop } } |
ft -G PSComputerName –A

under: PowerShell Basics, Scripting Games