Summary: Windows PowerShell MVP, Shane Hoey, provides expert commentary for 2012 Scripting Games Beginner Event 2.
Microsoft Scripting Guy, Ed Wilson, is here. Shane Hoey is the expert commentator for Beginner Event 2.
Shane’s scripting experience started when Windows XP was the new kid on the block, and he soon found himself scripting on a daily basis with VBScript, WMI, and ADSI. Fast forward to the Scripting Games 2009—he finally discovered Windows PowerShell, and he has been hooked ever since. One of the things he likes most about Windows PowerShell is its ability to easily automate tasks.
Twitter: @shanehoey
Aussie PowerShell Usergroup
I often talk to IT Pros who are starting to learn Windows PowerShell, and one of the first things I always say is, “Don’t overthink Windows PowerShell, it’s a shell first and foremost, so learn to use the shell first and scripting will naturally follow.” In fact, not everything needs to be made a script! And Scripting Games 2012 Beginner Event 2 is a perfect example.
When I first read the event scenario, I thought, did I miss something? There has to be a trick. Let’s break it down to what we need to do…
- We only have to find all services that can be stopped, we don’t even need to shut down the computers yet.
- No need to have a second computer to run against, which is good because I’m writing this post on the bus. So when I mention LocalHost, you could in fact be running it against a remote machine.
- No need to test firewall connections.
- Use the simplest command that will work.
- Display the output to the screen.
- Can use standard aliases.
It’s only Beginner Event 2, and many of you are new to Windows PowerShell, so now is a good time to remind you the importance of using Get-Help, Get-Command, and Get-Member.
The first command I will run is get-help get-service –online to open the Get-Service Help topic. Have a quick read of the topic to familiarize yourself with the cmdlet, and always make sure that you look at the examples because they can help us out.
Remember Windows PowerShell is object-orientated so when a cmdlet returns something, it always returns an object. We can use Get-Member to learn about more these objects, and the methods and properties that relate to the object. So I run the Get-Member cmdlet, and as you can see in the following command output, I quickly find out that I can use the CanStop property.
From running these two cmdlets, we now have all the information to get the results we need, so I run the following command:
Get-service –computername localhost | where-object {$_.canstop}
One of the design points in this event mentions that we can use aliases, so by using the Get-Alias cmdlet, I can determine each cmdlet’s alias. But a word of advice—don’t use aliases in scripts, especially when you are sharing those scripts, because aliases can be changed. If I use aliases, the command and the associated output look like this:
gsv –c localhost | ? {$_.canstop}
Based on the requirements, it looks like we have winner! But what if we want to obtain details on multiple servers? A simple addition to our command is to use parentheses, which will force the command it contains to execute first. An easy way to explain it is think of two maths equations: 5 * 5 +1 = 26 versus 5 * (5 + 1) = 30. Parentheses work exactly the same in Windows PowerShell.
gsv –c (gc servers.txt) | ? {$_.canstop}
For a final step we could format the output into something a bit more readable. For the purposes of this event, I don’t think this is needed; but it’s easy enough, so let’s do it.
gsv –c (gc servers.txt) | ?{$_.canstop} | sort machinename | ft –groupby Machinename
It can’t be this easy, can it? I wonder if the Scripting Guy is trying to trick me! I better check the 2012 Scripting Games Study Guide.
So could we use WMI? You bet we can! And the Scripting Guy mentions using WMI in his Study Guide. To get the similar results we would need to a command similar to this:
gwmi win32_service –comp localhost –filter “AcceptStop=$true” | FT state,Name,DisplayName
That’s cool, but this really does not meet our design criteria of running the simplest command that works. However, it does prove that there are many ways to do the same thing in Windows PowerShell.
We are almost finished, but before we go I want to make you aware of one last important feature in Windows PowerShell: pipeline parameter binding. From the Help page we opened earlier, you should be able to see that some parameters can accept the input of pipeline attributes ByValue and ByPropertyName. These parameters include ComputerName (ByPropertyName), InputObject (ByValue), and Name (ByPropertyName, ByValue).
Over at the PowerShell with a Purpose Blog by Don Jones, he discusses pipeline parameter binding in more detail, so I recommend that you read these blogs:
I’ve shown you two ways to get the required results for Scripting Games 2012 Beginner Event 2, and hopefully I have shown you why sometimes running a simpler command is best!
~Shane
2012 Scripting Games Guest Commentator Week will continue tomorrow when we will present the scenario for Event 3.
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