Question:
Why does
1 2 3 |
$a = GPS AcroRd32 | Measure $a.Count |
work, when
1 2 |
GPS AcroRd32 | Measure -Property Count |
doesn’t?
The first example returns a value of 2
, which is what I want, an integer.
The second example returns this:
1 2 3 4 5 6 |
Measure-Object : Property "Count" cannot be found in any object(s) input. At line:1 char:23 + GPS AcroRd32 | Measure <<<< -Property Count + CategoryInfo : InvalidArgument: (:) [Measure-Object], PSArgumentException + FullyQualifiedErrorId : GenericMeasurePropertyNotFound,Microsoft.PowerShell.Commands.MeasureObjectCommand |
This Scripting Guy entry is where I learned how to use the “Count” Property in the first code sample.
The second code sample is really confusing. In this Script Center reference, the following statement works:
1 2 |
Import-Csv c:\scripts\test.txt | Measure-Object score -ave -max -min |
It still works even if it’s re-written like so:
1 2 |
Import-Csv c:\scripts\test.txt | Measure-Object -ave -max -min -property score |
I don’t have too many problems with accepting this until I consider the Measure-Object help page. The parameter definition for -Property <string[]>
states:
The default is the Count (Length) property of the object.
If Count
is the default, then shouldn’t an explicit pass of Count
work?
1 2 |
GPS AcroRd32 | Measure -Property Count # Fails |
The following provides me the information I need, except it doesn’t provide me with an integer to perform operations on, as you’ll see:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
PS C:\Users\Me> $a = GPS AcroRd32 | Measure PS C:\Users\Me> $a Count : 2 Average : Sum : Maximum : Minimum : Property : PS C:\Users\Me> $a -is [int] False |
So, why does Dot Notation ($a.count
) work, but not an explicitly written statement (GPS | Measure -Property Count
)?
If I’m supposed to use Dot Notation, then I will, but I’d like to take this opportunity to learn more about how and *why PowerShell works this way, rather than just building a perfunctory understanding of PowerShell’s syntax. To put it another way, I want to avoid turning into a Cargo Cult Programmer/ Code Monkey.
Answer:
One thing you need to know is that in PowerShell generally, and particulary in CmdLets you manipulate objects or collection of objects.
Example: if only one ‘AcroRd32’ is running Get-Process
will return a [System.Diagnostics.Process]
, if more than one are running it will return a collection of [System.Diagnostics.Process]
.
In the second case you can write:
1 2 |
(GPS AcroRd32).count |
Because a collection has a count property. The duality object collection is also valid in CmdLets parameters that most of the time supports objects or list of objects (collection built with the operator
,
).
1 2 3 |
PS C:\> (gps AcroRd32) -is [object[]] True |
Just use the Get-Member cmdlet:
1 2 3 4 5 6 7 8 9 |
PS C:\> (gps AcroRd32) | Get-Member TypeName: System.Diagnostics.Process Name MemberType Definition ---- ---------- ---------- Handles AliasProperty Handles = Handlecount ... ... |
And
1 2 3 4 5 6 7 8 9 |
PS C:\> Get-Member -InputObject (gps AcroRd32) TypeName: System.Object[] Name MemberType Definition ---- ---------- ---------- Count AliasProperty Count = Length ... ... |