3

I have a foreach loop that currently puts three entries in my hashtable:

$result = foreach($key in $serverSpace.Keys){
    if($serverSpace[$key] -lt 80){
        [pscustomobject]@{
            Server = $key
            Space = $serverSpace[$key]}}}

When I use

$result.count

I get 3 as expected. I changed the foreach loop to exlude the entries less than or equal to one using

$result = foreach($key in $serverSpace.Keys){
    if($serverSpace[$key] -lt 80 -and $serverSpace[$key] -gt 1){
        [pscustomobject]@{
            Server = $key
            Space = $serverSpace[$key]}}}

$result.count should have 1 as its output but it doesn't recognize .count as a suggested command and $result.count doesn't output anything anymore. I'm assuming when theres only one entry in the hash table it won't allow a count? Not sure whats going on but my conditions for my script are dependent on the count of $result. Any help would be appreciated.

Tabiat1739
  • 87
  • 5
  • 2
    Force it to be an array: `@($result).count` – Theo Jul 12 '21 at 15:28
  • 1
    [1] that PSCO is NOT a hashtable. [*grin*] [2] if you want a single object to have a `.Count` property, you need to make that object into a collection. the easiest way is to prefix the $Var name with `[array]`. – Lee_Dailey Jul 12 '21 at 15:29
  • Oh wow I'm dumb. That makes sense. Thank you to both of you – Tabiat1739 Jul 12 '21 at 15:32
  • Does this answer your question? [Powershell being too clever](https://stackoverflow.com/questions/913788/powershell-being-too-clever) – iRon Jul 12 '21 at 16:12
  • Terminology note: What your `foreach` loop is returning is one or more _custom objects_ (`[pscustomobject]` instances), not [hashtables](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_Hash_Tables). – mklement0 Jul 13 '21 at 02:37

2 Answers2

2

$result is not a hashtable so I prefixed it with @($result).count. Thank you to @Theo and @Lee_Dailey

Tabiat1739
  • 87
  • 5
1

What you're seeing is a bug in Windows PowerShell (as of the latest and final version, 5.1), which has since been corrected in PowerShell (Core) - see GitHub issue #3671 for the original bug report.

That is, since v3 all objects should have an intrinsic .Count property , not just collections, in the interest of unified treatment of scalars and collections - see this answer for more information.

The workaround for Windows PowerShell is indeed to force a value to be an array via @(...), the array-subexpression operator, which is guaranteed to have a .Count property, as shown in your answer, but it shouldn't be necessary and indeed isn't anymore in PowerShell (Core, v6+)

# !! Due to a BUG, this outputs $null in *Windows PowerShell*,
# !! but correctly outputs 1 in PowerShell (Core).
([pscustomobject] @{}).Count

# Workaround for Windows PowerShell that is effective in *both* editions,
# though potentially wasteful in PowerShell (Core):
@([pscustomobject] @{}).Count
mklement0
  • 382,024
  • 64
  • 607
  • 775