Access Objects Inside Other Objects in PowerShell Pipeline

Dr Scripto

December 19th, 2014

Summary: Microsoft Scripting Guy, Ed Wilson, talks about accessing objects inside other objects in the Windows PowerShell pipeline.

Hey, Scripting Guy! Yesterday in Create Custom PowerShell Objects, you talked about writing a script to access embedded objects. That seems like a lot of trouble. Is there a better or easier way to do that, for example, when working in the Windows PowerShell console?

—BZ

Hello BZ,

Microsoft Scripting Guy, Ed Wilson, is here. It is nearly here! The fifth annual Scripting Guys holiday special! Windows PowerShell MVP, Sean Kearney, has been hard at work on this series for a while. It kicks off tomorrow, December 20, 2014. The series is about Oliver Script, who is a poor IT pro, and who must overcome a series of challenges. The accompanying video, Code Glorious Code, is available now, and it should whet your appetite. The series is lots of fun, and if you aren’t careful, you might just learn something.

Note This is the third in a series of posts about working with objects inside other objects.

Understand Embedded Objects in PowerShell explains how to use Select-Object and –ExpandProperty to look inside an object. Create Custom PowerShell Objects talks about using a script and creating a custom object.



Today I will talk about working inside the pipeline.

When I try to select a property that contains another object, all I get is the name of the object. This appears when I run a command such as the following:

Get-Process | Select-Object name, id, startinfo

This is because the StartInfo property contains another object. The output is shown here:

I can use grouping and look inside the StartInfo property:

(Get-Process).startinfo

The output is shown here:

So I can now see what is inside the StartInfo property, but I have no way to relate it back to process names or process IDs. Therefore, the information is basically useless. Well…I will be honest. It is useless except for one thing—I now know what properties are actually available within StartInfo.

Suppose that I am interested in the question, "Does the process load a user profile?" The System.Diagnostics.ProcessStartInfo object has a property called LoadUserProfile. Hmmm, this sounds like exactly what I want to know.

I want the Name and ID properties from the System.Diagnostics.Process property that returns from the Get-Process cmdlet. I also want the LoadUserProfile property from the System.Diagnostics.ProcessStartInfo object contained in the StartInfo property that is returned by Get-Process.

This is the classic object contained inside another object dilemma. Because I happen to be playing around at the Windows PowerShell console, I am going to use one of my favorite Select-Object tricks. "Wait!" you may say, "The other day when you used Select-Object, it would only let you use –ExpandProperty to expand a single property. It did not let you select other properties."

…and you would be right.

But what I can do is create a custom object by using a hash table for one of my properties. It is one of my favorite techniques. So I get started. The first part is exactly the same:

Get-Process | Select-Object name, id,

Now I want to create a custom property. So I use a hash table:

Get-Process | Select-Object name, id, @{}

Inside my hash table, I use two well-known properties: Label and Expression. I can even abbreviate them as L and E. As shown here, Label becomes my custom property name:

Get-Process | Select-Object name, id, @{L='LoadProfile';}

For my expression, I use a script block. This is shown here:

Get-Process | Select-Object name, id, @{L='LoadProfile';E={}}

Inside the script block, I use $_ to represent each process as it comes across the pipeline. I then choose the StartInfo property from the process object, and I select the LoadUserProfile property from the object contained in the StartInfo property. The complete command is shown here:

Get-Process | Select-Object name, id, @{L='LoadProfile';E={$_.StartInfo.loadUserProfile}}

When I run the command, the following output appears:

When I pipe the object to Get-Member, I see that it is a selected process object. This is shown here:

BZ, that is all there is to using Windows PowerShell objects. Join me tomorrow when the fifth annual Scripting Guys holiday special begins.

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