Keeran
Keeran

Reputation: 312

Array gives no output outside Function in PowerShell

Here is the code

$conn =  'saruspc01', '194.195.5.65'

 function lll {
    foreach($co in $conn)
    {
       $check = Test-Connection $co -Count 3 -ErrorAction SilentlyContinue
       $zugriffzeit = $check | select ResponseTime | Measure-Object ResponseTime -Average
       $avg = [system.math]::Round($zugriffzeit.Average)

        if($check -eq $null)
        {
            $pcre = Write-Output $co
            $pire = Write-Output 'False'
            $zure = 'Null'
        }
        else
        {
            $pcre = Write-Output $co
            $pire = Write-Output 'True'
            $zure = Write-Output "$avg ms"
            $zure = $zure.Replace(' ','')
        }
        $table += @( @{PCName=$pcre;    PingResult=$pire;    Zugriffszeit=$zure} )
        #$table | ForEach {[PSCustomObject]$_} | Format-Table -AutoSize
    }
}

If I execute the same code without Function, it works. I need the Funktion though and want to do this is this way. How can I fix it?

Upvotes: 2

Views: 463

Answers (1)

FoxDeploy
FoxDeploy

Reputation: 13537

The big issue is that you're adding items to $table but you don't return the table output back to the user. So, first things first, modify the end of your function to read like this. (I added the comment #EndOfForEach to help highlight where the changes need to go.

        $table += @( @{PCName=$pcre;    PingResult=$pire;    Zugriffszeit=$zure} )                
    }#EndOfForEach
    return $table
}

With that change done, your function will work but only when you call it like so:

PS:\>lll
Name                           Value                                             
----                           -----                                             
PCName                         behemoth                                          
Zugriffszeit                   1ms                                               
PingResult                     True                                              
PCName                         notonline                                         
Zugriffszeit                   Null                                              
PingResult                     False                                             

At this point, I'd recommend two changes. One, the layout is hard to read, so I'd convert the function to use a [psCustomObject] datatype instead, like so.

function lll {
    $results = New-Object System.Collections.ArrayList
    #...

   $results.Add([psCustomObject]@{PCName=$pcre;    PingResult=$pire;    Zugriffszeit=$zure})| Out-Null
    }#EndOfForEach
    return $results
}

For an output like so:

PS>lll

PCName    PingResult Zugriffszeit
------    ---------- ------------
behemoth  True       1ms         
notonline False      Null  

And if you want to take your function to the next level, you'd be well serverd to look to modify the function to accept parameters instead of relying on the $conn variable already being set. Hope this helps, let me know if you have any questions or if I could dig deeper into an area.

Why doesn't $results maintain a value?

PowerShell uses variable scoping, so the $results variable we define in this function will only exist for as long as the function is running. To keep the results, assign them to a variable when you call the function, like this.

$MyPingResults = lll
#no output is written to screen.

PS>$MyPingResults #get all results
PCName    PingResult Zugriffszeit
------    ---------- ------------
behemoth  True       1ms         
notonline False      Null     

PS>$myPingResults[0] #get first result

PCName   PingResult Zugriffszeit
------   ---------- ------------
behemoth True       7ms         

PS>$myPingResults | Where PingResult -eq $false #only get failed results

PCName    PingResult Zugriffszeit
------    ---------- ------------
notonline False      Null        

Completed Script

function lll {
    $results = New-Object System.Collections.ArrayList
    foreach($co in $conn)
    {
       $check = Test-Connection $co -Count 3 -ErrorAction SilentlyContinue
       $zugriffzeit = $check | select ResponseTime | Measure-Object ResponseTime -Average
       $avg = [system.math]::Round($zugriffzeit.Average)

        if($check -eq $null)
        {
            $pcre = Write-Output $co
            $pire = Write-Output 'False'
            $zure = 'Null'
        }
        else
        {
            $pcre = Write-Output $co
            $pire = Write-Output 'True'
            $zure = Write-Output "$avg ms"
            $zure = $zure.Replace(' ','')
        }
        $results.Add([psCustomObject]@{PCName=$pcre;    PingResult=$pire;    Zugriffszeit=$zure})| Out-Null
    }#EndOfForEach
    return $results
}

Upvotes: 1

Related Questions