To complement LotPings' helpful answer, which offers effective solutions:
As for why your code didn't work:
While Select-Object
's -Property
parameter accepts hashtables that define calculated properties (such as in your code), the -ExpandProperty
parameter only accepts a property name, as a string.
Therefore, your hashtable is simply stringified, resulting in string literal System.Collections.Hashtable
, causing Select-Object
to complain, given that there is no property by that name.
The purpose of -ExpandProperty
is to output just a property value rather than a custom object with that property.
You therefore do not need a detour via Select-Object
, and can just use the value-outputting script block - { $_.Created.ToString("yyyy-MM-dd") }
- directly with ForEach-Object
instead, as shown at the bottom of LotPings' answer.
However, there is an obscure feature that you forgo by using ForEach-Object
: Select-Object
allows combining -ExpandProperty
with -Property
, in which case the properties specified via -Property
are added as NoteProperty
members to the value of the property specified via -ExpandProperty
:
PS> $val = [pscustomobject] @{ one = 'uno'; two = 2 } |
Select-Object -ExpandProperty one -Property two; $val; $val.two
uno
2
Note how the output string value, 'uno'
has a copy of the input object's .two
property attached to it.
To emulate that with ForEach
requires more work:
PS> $val = [pscustomobject] @{ one = 'uno'; two = 2 } | ForEach-Object {
$_.one + '!' | Add-Member -PassThru two $_.two
}; $val; $val.two
uno!
2