Vainolo's Blog

Filtering PowerShell Output as Text


The PowerShell command-line shell is very powerful, and for people coming from *nix backgrounds (like me), it is the closest thing in Windows to the *nix command line. Today, I wanted to find if I had installed one service in my computer, and instead of going through all the required clicks in the UI, I decided to try and do this using PowerShell.

Fetching all the services is very simple, using the Get-Service cmdlet. Now I want to filter them for specific text (as I would have done in *nix with grep). A quick Google search returned the Select-String cmdlet as the best way to do this. So I naively wrote Get-Service | Select-String "Family" (using the Family Safety service for this example). No output… What am I doing wrong?

What happened here is that PowerShell is an Object-Oriented shell, which in lay-terms means that it doesn’t treat input and output as strings, but as Objects. In this specific case, the Get-Service cmdlet return an array of System.ServiceProcess.ServiceController objects, and when they are passed to Select-String they are transformed to their type, so what Select-String is filtering is a list of elements with the text System.ServiceProcess.ServiceController (no idea why this happens, because if I store the value of Get-Service into a variable and apply toString() to it, I get the name of the service and not it’s type).

So in order to transform the output of the cmdlet to a string, we have to invoke Out-String. I executed Get-Service | Out-String | Select-String "Family" and… wrong again! Got a list of all the services in my computer. The problem now is that Out-String not only transforms the output of the previous command to a string, but if the result is an array, it will also concatenate ALL the outputs into one big string. So Select-String is not lying, I’m just giving it wrong input. Again, a quick search returned that I needed to use Out-String -stream for the output to be sent to Select-String one by one.

To conclude, the working on-liner is:

Get-Service  | Out-String -stream | Select-String "Family"

Which gives me this nice output:

Stopped  WPCSvc             Family Safety

And as it turns out, I could also have done this using a parameter to Get-Service:

Get-Service -DisplayName "Family*"

Oh… the joys of automation… XKCD is always right

Written by vainolo

September 30th, 2014 at 12:33 pm

2 Responses to 'Filtering PowerShell Output as Text'

Subscribe to comments with RSS or TrackBack to 'Filtering PowerShell Output as Text'.

  1. || || findstr || go Cygwin!!!

    (…yes, I know you work for Microsoft…)

    Eli Savransky

    30 Sep 14 at 19:29

  2. Do you really think I am not aware of Cygwin? :-). But I like knowing the tools that best work in my platform, and PowerShell is VERY powerful, and you can do incredible stuff. And learning new things is always good for the brain.


    2 Oct 14 at 11:00

Leave a Reply

%d bloggers like this: