Expert Solution for 2011 Scripting Games Beginner Event 2: Use PowerShell to Find Windows Services You Can Pause

ScriptingGuy1

Summary: Microsoft Windows PowerShell MVP, Shane Hoey, solves 2011 Scripting Games Event 2 by finding services that he can pause.

Microsoft Scripting Guy, Ed Wilson, here. Our expert commentator for Beginner Event 2 is Shane Hoey.

Photo of Shane Hoey

This is what Shane has to say about himself and his scenario:

My scripting experience started back when Windows XP was the new kid on the block, and I dabbled with VBScript, WMI, and ADSI. Fast forward to the 2009 Summer Scripting Games when I finally discovered Windows PowerShell—I have been hooked ever since. One of the things I like most about Windows PowerShell is its ability to easily automate, especially daily repetitive tasks. My background is system and network administration, but at work they just call me the PowerShell Geek these days. By the way, I also run the PowerShell Usergroup in Brisbane Australia (http://powershelldownunder.com), and you can follow me on twitter @shanehoey.

When I first started learning Windows PowerShell during the 2009 Scripting Games, I found one of the most challenging aspects was the concept of objects. With my sys-admin background, the GUI had always been my tool of choice, so understanding Windows PowerShell was a very foreign concept. PowerShell just seemed so complex and confusing with its execution policies, cmdlets, and a syntax that I thought only a developer would understand.

After the games finished, I decided to challenge myself and continue to learn PowerShell. One of the things I quickly learned was that Windows PowerShell is highly discoverable, and great amounts of information can be discovered by using the Get-Help, Get-Command, and Get-Member cmdlets. Never underestimate the importance of these three cmdlets.

Before we start today’s event, I’d like to explain how I came to script my solution. Generally whenever I start to write a new script I break it down to smaller steps, then while working interactively with the console, I’ll try to figure out how I can perform those smaller steps. Finally, I’ll start to create my script based on the information I learned while working interactively in the console.

Worked solution

Let’s start by using the Get-Command cmdlet to find the cmdlets that are related to services.

get-command *service

From this list, we can see that we need to use the Get-Service cmdlet. Now we use the Get-Help cmdlet to learn about using Get-Service.

get-help get-service -online

You may have noticed that I used the online parameter. This is a really cool parameter of the Get-Help cmdlet that can be used with cmdlet, function, and script Help topics. It will display the Help topic in the default browser.

After a quick read of the Help topic, you’ll notice that this cmdlet supports the computername parameter, which means that it will work on a local and on a remote computer. That’s a bonus for us because it will be easy to receive some bonus points for this event!

Now that we know how to use the Get-Service cmdlet, we need to find out what other bits of information Windows PowerShell can tell us. Remember everything that PowerShell returns is an object, and that object will have properties and methods. So to find this extra information, we pipe the Get-Service cmdlet to the Get-Member cmdlet, which returns a list of all the methods and properties of the objects.

get-service | get-member

The command and its associated output are shown in the following image.

From the output of this command, we can quickly find the properties that are required to complete our task, which in this case are CanPauseAndContinue, Status, Name, and DisplayName.

This is a good of example of how we can quickly discover information in PowerShell by using the Get-Help, Get-Command, and Get-Member cmdlets. We now have the information we need for a quick one-liner that meets the primary requirement and the first bonus item for today’s event.

Get-Service –ComputerName localhost | Where-Object { $_.CanPauseAndContinue} | Format-Table –Property Status,Name,DisplayName -Autosize

But we are not quite finished yet, let’s progress this one-liner into a script and try for a few more bonus points by taking the following into account:

  • By utilizing Help function tags, we can quickly produce standardized Help for our scripts, with the added benefit that they will integrate with the Get-Help cmdlet.
  • Ensure that a #requires –version 2.0 statement is included because the script will only execute in PowerShell 2.0
  • Use a Param statement so that we can use named arguments and validate parameter input.
  • Because the script will try to access remote computers, we should test the connection first with Test-Connection.
  • Whenever we have three or more conditional tests, use a switch statement as opposed to multiple if then else statements.
  • When using a switch statement it is a best practice to include a default condition. However, because we have already validated the parameter’s input, we can ignore a default condition.
  • Let’s aim for some bonus pointsby creating a switch parameter called GridView. When we include this parameter, it will display the results in a grid view window rather than in the console.

And here is our finished script…

<#

            .SYNOPSIS

            Script to retrieve information about services.

      .EXAMPLE

            .\Get-ServiceInfo.ps1

            Retrieve all services running on the local computer that can be Paused.

      .EXAMPLE

            .\Get-ServiceInfo.ps1 -CurrentState All -GridView

            Retrieve all services running on the local computer and display in a GridView.     

      .EXAMPLE

            .\Script.ps1 -Services S* -ComputerName <computername> -CurrentState CanStop -Sort DisplayName

            Retrieve all services starting with S, on a remote computer, that can be stopped, and sort by the DisplayName.

      .NOTES

            NAME: Get-ServiceInfo.ps1

            AUTHOR: Shane Hoey, powershelldownunder.com

            DATE: 3rd April 2011

#Requires -Version 2.0

#>

 

param(

 [string]$Name = ‘*’,

 [string]$ComputerName = $env:computername,

 [ValidateSet(‘All’,’CanPause’,’CanContinue’,’CanPauseAndContinue’,’CanStop’,’CanShutdown’)]

 [string]$CurrentState = ‘CanPause’,

 [ValidateSet(‘Status’,’Name’,’DisplayName’)]

 [string]$Sort = ‘Name’,

 [switch]$GridView

)

 

If (Test-connection -ComputerName $ComputerName -count 1 -quiet)

{

 $svc = get-service $Name -computername $ComputerName

 

 switch($CurrentState)

 {

  ‘All’ { }

  ‘CanPause’ { $svc = $svc | Where-Object {$_.status -eq ‘running’ -and $_.CanPauseAndContinue} }

  ‘CanContinue’ { $svc = $svc | Where-Object {$_.status -eq ‘paused’ -and $_.CanPauseAndContinue} }

  ‘CanPauseAndContinue’ { $svc = $svc | Where-Object {$_.CanPauseAndContinue} }

  ‘CanStop’{ $svc = $svc | Where-Object {$_.CanStop} }

  ‘CanShutdown’{ $svc = $svc | Where-Object {$_.CanShutdown} }

 }

 if ($GridView)

 {    $svc | Select-Object -Property Status,Name,DisplayName | Sort-Object -Property $Sort | Out-GridView -Title ‘Services – $CurrentState’ }

 else

 { $svc | Select-Object -Property Status,Name,DisplayName | Sort-Object -Property $Sort | Format-Table -Autosize}

}

else

{

 “$ComputerName is Unreachable”

}

Thank you for writing this solution for Beginner Event 2, Shane.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy