Share via


ExpandProperty in Select-Object

While discussing about the Select-Object cmdlet, I love to mention about the ExpandProperty parameter since it is cool and of great utility. Sometimes the utility of the ExpandProperty parameter is better understood by looking at examples. So here are some examples which will help you understand the ExpandProperty parameter of the Select-Object cmdlet:

Before diving into examples, lets go through the Get-Help information of ExpandProperty parameter of Select-Object cmdlet. It states - Specifies a property to select, and indicates that an attempt should be made to expand that property.

In other words - ExpandProperty expands the collections. That is, it will output the properties of every object in the collection.

Following examples will make ExpandProperty more clear. Let's start with Get-Process cmdlet.

Get-Process | Get-Member gives us different properties of "process" object. Let's focus on  the Modules property which is a ProcessModuleCollection:

 

 

Now, lets select the property Modules:

You will see that the output does not seem to be complete. That's because Modules is a collection and it has a collection of objects inside it. In order to display each object and its properties, you will have to use the ExpandProperty parameter of Select-Object. Let's look at the output generated using -ExpandProperty parameter before we discuss more about it:

Now you can see that since we used the ExpandProperty parameter, Select-Object "expanded" on the collection and displayed properties (Size, ModuleName and FileName) of each object inside the collection.

(Just a note: In the above example, I used Get-Process notepad just to reduce the output on my screen (by getting only notepad process related information) to give you a better view of what was happening. If you are using the same example, be sure to start a notepad process on your machine. Get-Process | Select-Object -ExpandProperty Modules would also give us a similar result, just that in that case it would be a lot of data outputted).

Let's look at another example here. Lets look at DependentServices property of "service" object. Let's start with Get-Service | Get-Member:

 

You see that DependentServices is an array of "service" (ServiceController) object. In other words, it can be looked at as a collection of service objects. That's the reason if we try to just Select-Object -Property DependentServices on Get-Service, we wont be able to get a complete view of the DependentServices.

 

 

Now. let's use the ExpandProperty on DependentServices and see the difference..

 

 

Because we used ExpandProperty we are able to see the expanded collection.

(Another note: In this case, rather than getting all the services, I just got the "samss" service (Get-Service samss), that's just to give you a better view of how the ExpandProperty parameter works. The service name is not important in this example, however what is important is that you need to get service which has some dependent services. In case you don't have the same service or if you want to check the property for some other service, here is a statement to fetch the services which have some dependent services:

Get-Service | Where-Object { $_.DependentServices }

To get an even better view you can fetch services which have more than 1 dependent services. For that, you can use the following statement:

Get-Service | Where-Object { ($_.DependentServices).count -gt 1 } )

Hopefully, these examples gave you a good understanding of ExpandProperty parameter of Select-Object cmdlet.

There is one another interesting and useful aspect to the ExpandProperty parameter. Till now, we applied ExpandProperty to the properties which were "collection" of some kind. If you apply ExpandProperty to a property which is not a collection, it gives you just the values not the object with properties. This example below should make it more clear:

 

If you pipe this is to Get-Member cmdlet, you will be able to see that the output is of "string" type and not anymore a "selected" object with "name" as a property of that object. And if you pipe this output to Get-Member you will see that the output is of type string.

You can use this output in multiple ways,depending on your requirements. One example would be - check if any service related cmdlets (Start-Service, Stop-Service) have parameter which "Accepts Pipeline Input" by value in "string" type. Now you can pipe this string output into your specific *service cmdlet and generate the required result. Once you go through my "Pipeline in PowerShell" blog, I am sure you will get why Accept Pipeline by value will work..

 

Another example of ExpandProperty on similar lines: This time lets expand the Id property of Get-Process cmdlet. Before that, let's do a Get-Member on Get-Process and take a look at the Id property:

Get-Process | Get-Member:

 

So we know that Id is a property of "process" object and it is of type integer. Now, lets expand the property and check the output:

 

This time as well, you see that we get the Id of processes as values not as properties of "selected" object. Pipe this output to Get-Member and you will see that the values are of type int.

 

Now you can see that when ExpandProperty is applied on properties which are not collections, we get the values (not "selected" objects with properties) and the values retain the original datatype of the properties. 

Hopefully, these examples helped you to understand in detail the ExpandProperty parameter of Select-Object cmdlet.