My Five Favorite PowerShell 3.0 Tips and Tricks

My Five Favorite PowerShell 3.0 Tips and Tricks

  • Comments 9
  • Likes

Summary: Microsoft Scripting Guy, Ed Wilson, shares his top five Windows PowerShell 3.0 tips and tricks.

Microsoft Scripting Guy, Ed Wilson, is here. Today marks a red letter day. No, we have not yet sold out Windows PowerShell Saturday in Charlotte, North Carolina (but we are really close). And no, the Scripting Wife and I have not sold our house and moved to Australia (although we would not really mind doing that). No, it is something more primeval, something more substantive, and frankly, something more exciting than either of the two previous possibilities…

I restart my radio series on TechNet Radio: IT Time with Microsoft IT Pro evangelist, Blain Barton. You can catch the earlier episodes via the Learn PowerShell page if you are so inclined. For our first session of the new fiscal year, we discussed my new Microsoft Press Windows PowerShell 3.0 Step by Step book a bit. In the next episode, we will talk about my favorite Windows PowerShell 3.0 tips and tricks. Don’t worry, todays blog will not necessarily spoil the plot because Blain is an absolutely top notch interviewer. In fact, I would place him right up there will the likes of Hal Rotenberg and Jonathan Medd. Yep, he is that good.

Way cool Windows PowerShell 3.0 stuff

Much of the way cool stuff that is written about Windows PowerShell 3.0 has to do with new cmdlets—especially all the new cmdlets in Windows 8 and in Windows Server 2012. These are the bells and whistles, but some of my favorite new things in Windows PowerShell 3.0 are the stuff that makes my life easier day in and day out. For example, how often, really, will I be typing Get-NetIpAddress or Set-NetConnectionProfile? On the other hand, how many times do I need to access a single property from each object in a collection? For me, I need the latter a whole lot more times.

So here are my top five Windows PowerShell 3.0 tricks. They are all language related, and I predict that they will also become your favorites.

My favorite Windows PowerShell trick is the automatic foreach

In Windows PowerShell 1.0 and Windows PowerShell 2.0, if you have a collection of objects, you must iterate through that collection, individually retrieve a desired property, and then possibly store it back in the variable for later use. It worked, and the behavior was similar to the behavior in other languages. In fact, this behavior still works in the Windows PowerShell 3.0 world today. Here is an example of using the Get-Process cmdlet where I store the collection of process objects in a variable named $process, and then pipe the resulting objects to the Foreach-Object cmdlet to retrieve the name property from the current object in the pipeline. I store these retrieved names in a $names variable.

$process = Get-Process

$Names = $process | foreach { $_.name }

$names

This command sequence is not that difficult, and it is one that the enterprise scripter will eventually type hundreds and hundreds of times over the course of a couple years. But in Windows PowerShell 3.0 this sequence is no longer required, and entire $process pipeline to the Foreach-Object command sequence is eliminated. Instead, Windows PowerShell 3.0 makes desired properties immediately available, and directly accessible. This revision of commands is shown here.

$process = Get-Process

$process.name

Although simply displaying process names may be somewhat illuminating, this sequence saves me tons of time when I am gathering the names of servers to use in further remoting scenarios. This sequence is shown here.

$servers = Get-ADComputer –Filter *

Get-HotFix –CN ($servers.name)

Where are squiggle brackets for Where-Object?

My second favorite feature in Windows PowerShell 3.0 is the streamlined Where-Object syntax for simple where clauses. In Windows PowerShell 1.0 and in Windows PowerShell 2.0, to use the Where-Object cmdlet to filter returned information required the use of script blocks, special variables, and understanding how pipelining worked. In short, this important task was fraught with stumbling blocks for the beginner Windows PowerShell scripter.

But you may say, “YOU are not a beginner Windows PowerShell scripter. So why is this syntax so popular with you?” I will tell you…

Of all the cmdlets I use, the Where-Object cmdlet consistently ranks in the top four cmdlets I always use. In fact, I can prove this statement because I wrote a script that parses cmdlets used in scripts. In the Weekend Scripter: Hey, Scripting Guy! Blog post Playing Around With the Windows PowerShell Tokenizer, I include a script that I use to parse my scripts to reveal which cmdlets I use the most. When you have run the script against your script directory, use the following command to process the contents.

Get-Content $logpath | sort | group -NoElement | sort count

The long way of using the Where-Object is shown here.

Get-Process | where { $_.name -match 'word' }

Here is the short way of using the Where-Object.

Get-Process | where name -match 'word'

Not only is it less typing, but it is also easier to read.

Using local variables in remote sessions

With Windows PowerShell remoting gaining in popularity and importance, ease-of-use becomes vital. If I created a local variable in Windows PowerShell 2.0, and I needed to use it in a remote session, I had to write a bit of code to accomplish this feat, and I had to pass the local variable as an argument and as a parameter in the remote session. Sound confusing? Well, it wasn’t after the first 100 times doing it. By that time, it was just annoying. Here is what I am talking about (icm is an alias for the Invoke-Command cmdlet).

$class = "win32_bios"

icm -cn dc3 {param($class) gwmi -class $class} -ArgumentList $class

In Windows PowerShell 3.0, this process is much more straightforward and easier to understand. Here is the Windows PowerShell 3.0 syntax that is so sweet it checks in at number 3 on the Scripting Guy’s top five tricks list.

$class = "win32_bios"

icm -cn dc3 {gwmi -class $using:class}

Flexible script formatting

Because it seems that I am constantly writing a blog or a book, or teaching a class, I am always confronted with a narrow screen or a large font that takes up lots of screen real estate. Typically, I work with a maximum of 82 – 85 characters of width. This is a problem with a verbose easy-to-read language. Couple this with the fact that many of my readers or my audience is just learning Windows PowerShell, and I have a real problem. I have learned to despise line continuation because of the unnecessary errors that it potentially introduces. In Windows PowerShell 2.0 or Windows PowerShell 1.0, my basic choices were lots of variables, breaking at the pipeline character, or line continuation. In Windows PowerShell 3.0, flexible formatting enters the picture. This means that I can use a syntax such as the one shown here.

(get-process).

    name.

    gettype()

This feature is so cool that it deserves a picture. Seeing is believing with flexible formatting. OK, maybe it is just me, but it is good enough for number 4 in my top 5 Windows PowerShell 3.0 tricks.

Image of command output

Variable validation attributes

Windows PowerShell 2.0 had parameter validation attributes, but if I wanted to ensure that a variable value met specific requirements (other than parameters), I needed to write code to verify those requirements, or I needed to be ready to catch an error. In Windows PowerShell 3.0, the introduction of variable validation attributes can vastly simplify this error checking requirement to a single command. For people who write a lot of scripts (such as myself), this is a huge win. Here is an example of setting a validation attribute where the value of $c must be within the range of 1 to 5.

[ValidateRange(1,5)][int]$c = 1

When I run the command and exceed the permissible range, an error message appears. The following command runs 10 times and sets a random number between 1 and 8 to the value of $c.

1..10 | % {$c = Get-Random -Minimum 1 -Maximum 8 ; $c}

The command and the error are shown in the image that follows.

Image of command output

Come back tomorrow when I will talk about more Windows PowerShell cool stuff.

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 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Very good tips there, Ed.  Thanks for this excellent blog.

  • hi

    in Where clause you can alse use psitem variable:

    PS III> gci $Path | where $psitem.name.length -gt 5

    my favorite trick:

    PS III> Get-User -anr $search | Out-GridView -PassThru | Set-User -EnableAccount true

  • @BigTeddy thanks. I have been wanting to write about PowerShell 3 for some time, but also wanted to wait until it was RTM. Even if you never use any of the new cmdlets that come with Windows 8, you still are left with a much better PowerShell ... it does what PowerShell 2.0 did, only better. Really cool stuff here.

  • @Walid Toumi  yes, I thought about including that one as well. Certainly using $psitem is easier to read than $_ :-) And the -passthru on out-gridview makes that cmdlets MUCH more useful. Thanks for sharing.

  • @Ed - Absolutely cool.  I can't wait fo it ot be RTM'd so I can use it everywher.

    I haven't even tested much because I cannot use it on any domain except one test domain that is usually very busy.

    I watch you anf Grant/Wiki and the PosH Team to try and keep up.  

    Keep up the P3 blog posts.

  • Powershell is really coming into it's own with v3.

  • The "where" command can be even simpler, since you can omit the quotes:

    Get-Process | where name -match word

    instead of

    Get-Process | where name -match 'word'

  • @pyjo

    get-process *sv*

    much easier and it works in V2 and V3.

  • Maybe the wrong place to post my question so please send me in the right direction if I am wrong. I am trying to install PS 3.0 on Windows 2008 Enterprise and for the life of me cannot do it. I have .NET 4.5 and RSAT installed but my Powershell (get-host) still states 2.0 and when I try to load the Updates (KB2506143-x86) it states that the update does not apply to my system.

    ????