Say what’s up to PowerShell 5 (Part 18/27)

So in our previous posts, you learned all about PowerShell objects, how to use Select-Object to select specific properties of that object, how to use Sort-Object to order the output and even how to use hash tables to create computed columns on the fly (that’s that @{n=blah;e=1 -gt 2;} business)

In this post I want to show you the last command you need to gain complete control over what PowerShell shows you.  It’s called Where-Object and it’s awesome.

When I started learning PowerShell the thing that gave me the greatest trepidation were those blasted hash tables and also the comparison syntax.

In most progrmaming langauges the greater than symbol, >, is used to indicate that what’s on hte left is greater than what’s on the right.  And the equal symbol, =, is used to show equivalency.  Not so in PowerShell!

If you type:

get-help *operators"

Comparison operators in PowerShell

you can learn how PowerShell thinks about operators but I’ll spare you the trouble by breaking it down for you right here, right now.

Go ahead and type 1 < 10 in PowerShell.

PowerShell less than symbol

This fails because in the shell the less than symbol already serves a purpose: it’s the redirection operator.  In other words, it redirect output.

So we can’t use that.

Here’s how you do comparisons in PowerShell:

  • -lt is less than
  • -le is less than or equal
  • -gt is greater than
  • -ge is greater than or equal
  • -eq is equal
  • -ne is not equal

So if we type:

1 -lt 10

we get success!

1 is -lt 10

Having fun Where-Object

So let’s say you only want to see services that are running.

You could type:

gsv | where-object { $_.status -eq "stopped" }

or you could use the where-object alias of a question mark to achieve the same goal:

gsv | ? { $_.status -eq "stopped" }

Where-Object

But let’s say we only want the stopped services that have names that begin with an “m”.

We could use the -and parameter with a wildcard character like this…

gsv | ? { $_.status -eq "stopped" -and $_.name -like "m*"}

PowerShell -and operator

Cool, but here’s the thing:

Whenever you start filtering you always need to filter as far left as possible.

PowerShell doesn’t have the word Power in there by accident.  You can use PowerShell to pull data from thousands of computers and if you’re filtering isn’t setup right you’ll waste precious computer resources trying to display your data.

Let’s take a look at the command we just typed again without the cryptic partial parameters:

Get-Service | Where-Object { $_.status -eq "stopped" -and $_.name -like "m*"}

The far left contains no filters.  In other words, the Get-Service cmdlet isn’t doing anything to narrow down the results.  So all the results are getting sent to Where-Object and then and ONLY THEN are they being filtered.  This could be a huge problem if you’re pulling data from thousands of hosts across a network.  You could oversaturate the link.

So we need to see how we can do our filtering in Get-Service. We should filter as much as we can to the left as early as possible.

You can figure this out by looking in the help cmdlet for any parameters that can restrict your results.

I just happen to know that Get-Service let’s us do the name filtering like so:

Get-Service m*

Filtering Get-Service

 

So let’s rewrite our where-object clause so that name filtering is done to the left in Get-Service.

Get-Service -Name m* | Where-Object { $_.status -eq "stopped"}

Filtering to the left

or

gsv m* | ? { $_.status -eq "stopped" }

Filtering to the left 2

Same difference.

That way if we ever decide to use this to pull data from multiple  computers it won’t kill the network.

Get-Service -Name m* -ComputerName dc17alx1, ws11alx1 | Where-Object { $_.status -eq "stopped"}

About

Connect with Vonnie on Twitter

Posted in Windows, Windows 10 Tagged with: