To complement zdan's helpful answer[1]
with alternatives:
If you just want the value of a given object's property, simply wrap the command in (...) and use .<propertyName>:
(Get-ItemProperty 'C:\Program Files\McAfee').LastWriteTime # returns a [datetime] instance
In PSv3+, the above also works with commands returning multiple items (arrays), in which case an array of the input items' individual property values is output - this feature is called member-access enumeration.
PSv3 introduced a shortcut syntax for % / ForEach-Object (and also ? / Where-Object) that can be leveraged here as well :
Get-ItemProperty 'C:\Program Files\McAfee' | % LastWriteTime # ditto
This is the equivalent of the more verbose (which also works in PSv2-):
Get-ItemProperty 'C:\Program Files\McAfee' | % { $_.LastWriteTime }
These two pipeline-based syntax forms are slower, but have two advantages:
Large input collections are better processed in pipelines one by one in order to keep memory use constant (if feasible; if you need to collect the entire output in memory, there is no advantage).
This syntax unambiguously references an individual item's property rather than a property of the collection as a whole.
- E.g.,
(Get-ChildItem -File C:\Windows).Length returns the count of files in C:\Windows, because Length is interpreted as the collection's (array's) property;
by contrast, Get-ChildItem -File C:\Windows | % Length returns an array of the individual files' .Length (file-size) property values.
Finally, in PSv4+, you may also use the .ForEach() collection method, which doesn't use the pipeline and is therefore faster (though slightly slower than member-access enumeration), but, like member-access enumeration, requires that the input collection be in memory in full:
(Get-ItemProperty 'C:\Program Files\McAfee').ForEach('LastWriteTime')
[1] A quick overview of Select-Object's behavior:
Select-Object [-Property] <string[]> returns a custom object for each input object, containing only the specified properties; even with only a single property specified, the results are custom objects with that single property, not the property values themselves.
By contrast, using -ExpandProperty <string> returns the given, single property's value from each input object (typed as-is) instead.
A simple example: extract the Year property value from a Get-Date call:
# WRONG: with (implied) -Property
PS> $val = Get-Date | Select-Object Year; "$val"
@{Year=2018} # !!
# A custom object with a Year property was returned and the above is its
# string representation, the equivalent of:
# "$([pscustomobject] @{ Year = 2018 })"
# CORRECT: with -ExpandProperty
PS> $val = Get-Date | Select-Object -ExpandProperty Year; "$val"
2018 # OK: -ExpandProperty extracted just the property's *value*