2

I'm stumped by some of the behavior of the Select-Object cmdlet. Here is an example.

PS C:\> $object = get-item C:\windows\Temp
PS C:\> $time = $object.CreationTime
PS C:\> $time.GetType().FullName
System.DateTime
PS C:\> $result = Select-Object -InputObject $object -Property "CreationTime"
PS C:\> $result.GetType().FullName
System.Management.Automation.PSCustomObject
PS C:\>
PS C:\> $result.CreationTime.GetType().FullName
System.DateTime

Notice that CreationTime's type is System.DateTime but when I select it using Select-Object the returned object is of type System.Management.Automation.PSCustomObject. Its some new object that has CreationTime as its property.

Let's look at the help for Select-Object to explain this.

SYNOPSIS
Selects specified properties of an object or set of objects...

That's what I wanted, the property itself... not some object with the property. But if we read further...

DESCRIPTION
...If you use Select-Object to select specified properties, it copies the values of those properties from the input objects and creates new objects that have the specified properties and copied values.

I have no idea why that's useful, but it explains this object returned.

Using -ExpandProperty instead of -Property seems to give the property itself

PS C:\> $result2 = Select-Object -InputObject $object -ExpandProperty "CreationTime"
PS C:\> $result2.GetType().FullName
System.DateTime

By why does -ExpandProperty do this? Let's look at its help:

-ExpandProperty
Specifies a property to select... If the property contains an object, the properties of that object are displayed in the output.

In this case, the property is an object and we didn't get "the properties of that object" we only got the object itself.

Can someone tell me:

  1. Why does -ExpandProperty get the property-object itself when the help mentions expanding arrays and getting properties of the property-object (not the property-object itself)? This is where I am pretty confused. Am I reading this wrong? I feel like this needs another iteration of technical editing.
  2. The object that gets returned with "-Property", is it useful for something?

2 Answers 2

4

To expand on the answer to #1: The most common use of -expandproperty is to expand a property that is an array into the array elements, particularly when doing an export-csv.

PS C:\> get-process lsass | select threads | convertto-csv -notype
"Threads"
"System.Diagnostics.ProcessThreadCollection"

Not very useful. Now, use -expandproperty on that thread collection:

PS C:\> get-process lsass | select -expand threads | convertto-csv -notype

 "BasePriority","CurrentPriority","Id","IdealProcessor","PriorityBoostEnabled","PriorityLevel","PrivilegedProcessorTime"
 ,"StartAddress","StartTime","ThreadState","TotalProcessorTime","UserProcessorTime","WaitReason","ProcessorAffinity","Si
 te","Container"
 "9","10","572",,,,,"2000143616",,"Wait",,,"LpcReceive",,,
 "9","10","588",,,,,"2000143616",,"Wait",,,"UserRequest",,,
 "9","9","592",,,,,"2000143616",,"Wait",,,"UserRequest",,,
 "9","10","596",,,,,"0",,"Wait",,,"EventPairLow",,,
 "9","9","1404",,,,,"0",,"Wait",,,"UserRequest",,,
 "9","9","3896",,,,,"0",,"Wait",,,"EventPairLow",,,
 "9","9","848",,,,,"0",,"Wait",,,"EventPairLow",,,
 "9","11","6216",,,,,"2000143616",,"Wait",,,"UserRequest",,,
 "9","9","7924",,,,,"2000143616",,"Wait",,,"EventPairLow",,,
Sign up to request clarification or add additional context in comments.

3 Comments

That makes sense. What surprised me was that if the property is not an array than the cmdlet returns the property alone, where I don't see any "expand" happening :P
Think about it this way. Using $object | select -expand property will give you the same result as $object | foreach {$_.property}. If the property is a scalar (single value) you'll only get back one object. If there's more than one, you get back an array of objects.
Ah, that makes sense. A lot of cmdlets automatically handle either scalar or array values without me having to wrap the scalar in an array-of-one-element. Somehow that didn't click. For those reading for an answer to Question 2, see Mike Shepard's answer (and comments) below.
3

Select-object (without -expandproperty) returns a PSCustomObject with the set of properties you select. That's because you might want to select more than one property (and couldn't expect to get, for instance, a datetime object for 2 properies).

The answer to #2 is that sometimes it's better to have an object with fewer properties and lose the methods. Also, you can use select-object with expressions to return "calculated" properties.

2 Comments

I haven't used calculated properties yet. I'm still fuzzy on when the PSCustomObject is useful (it's MSDN documentation is a bit meager). If I wanted to receive multiple properties my first thought would be an array of properties. Is there something special about the properties being "on" an object?
Many of the "out of the box" cmdlets work with properties (where-object, sort-object, etc.) and won't be useful with an array of properties. As far as calculated properties, here's an example: Get-ChildItem C:\Test | Select-Object Name, CreationTime, @{Name="Kbytes";Expression={$_.Length / 1Kb}} taken from here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.