Last Update: Sep 04, 2024 | Published: Nov 05, 2015
One of the problems many PowerShell beginners have is getting their heads around the idea of objects in the pipeline. They see the output of a command and try to finagle something from the text they see on the screen.
This becomes tricky with object properties that contain a nested object or a collection of objects. You might start with a command like this:
$s = get-service bits
You’ll then look at $s.
If you look at the RequiredService property, then you should notice that the value is wrapped in curly brackets. This lets you know that the value is a collection of objects. You might try to look at those properties.
You still have an object, but it has a single property, and the value is still a collection. If you want to get at those objects, your might think you need to use ForEach-Object.
That didn’t work. However, this will:
Fortunately, all you need to do is tell PowerShell to expand that property.
$s | select -expandproperty RequiredServices
The only caveat is that you can only expand a single property. But you can also use this parameter if you simply want a list of values. For example, I often see people struggle with this concept, where they might run a command like this:
get-service | where {$_.status -eq 'running'} | Select name | out-file c:workrunning.txt
In their heads and perhaps based on experience with command-line tools, they are expecting a text file of only service names. But what they have really done is direct the output of a single property object to text file something that looks like this:
Name ---- Appinfo AudioEndpointBuilder Audiosrv BcmBtRSupport BFE BITS Bluetooth Device Monitor
The proper way is to expand the property so that all you get is the value.
Over time PowerShell has also gotten smarter. Let’s say that you have a variable with a collection of objects.
$running = get-service | where {$_.status -eq 'running'}
Let’s assume that all you need is the service name. In earlier versions of PowerShell, we used commands like this:
Of course, you now know you could use Select-Object.
$running | select -ExpandProperty Name
But you can also simply treat the variable as a single object and specify a property name.
You don’t even need a variable.
By wrapping the expression in parentheses, you are telling PowerShell, “run this command and treat the result as a variable.” Here’s one more example:
Going back to my original scenario, we can combine all of these ideas. We can easily expand the required services property:
And take the next step to get just the displayname.
Once you get used to thinking in this object notation, you’ll be amazed at how much can do without a lot of effort.