Functions/Test-ConnectionAsync.ps1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
function Test-ConnectionAsync { <# .SYNOPSIS Performs a ping test asynchronously .DESCRIPTION Performs a ping test asynchronously .PARAMETER ComputerName List of computers to test connection. Aliased to 'CN', 'Server' .PARAMETER Timeout Timeout in milliseconds. Default 2000 ms. .PARAMETER TimeToLive Sets a time to live on ping request. Default 128. .PARAMETER BufferSize How large you want the buffer to be. Valid range 32-65500, default of 32. If the buffer is 1501 bytes or greater then the ping can fragment. .PARAMETER IncludeSource A switch determining if you want the source computer name to appear in the output .PARAMETER Full A switch determining if full output appears .NOTES Inspired by Test-ConnectionAsync by 'Boe Prox' https://gallery.technet.microsoft.com/scriptcenter/Asynchronous-Network-Ping-abdf01aa * fixed logic around processing pipeline * removed $Buffer parameter * added $BufferSize parameter and dynamically create $Buffer from $BufferSize * added $IncludeSource so that source computer would be included in output * added $Full so that default output is brief * changed datatype of .IPAddress to [version] so that it can be sorted properly .OUTPUTS [pscustomobject] with output from Net.AsyncPingResult and optionally the source address .EXAMPLE Test-ConnectionAsync -ComputerName server1,server2 ComputerName IPAddress Result ------------ --------- ------ server1 192.168.1.31 Success server2 192.168.1.41 Success Description ----------- Performs asynchronous ping test against listed systems and lists brief output. .EXAMPLE Test-ConnectionAsync -ComputerName server1,server2 -Full ComputerName IPAddress BufferSize Result ResponseTime ------------ --------- ---------- ------ ------------ server1 192.168.1.31 32 Success 86 server2 192.168.1.41 32 Success 79 Description ----------- Performs asynchronous ping test against listed systems and lists full output. .EXAMPLE Test-ConnectionAsync -ComputerName server1,server2 -Full -BufferSize 1500 ComputerName IPAddress BufferSize Result ResponseTime ------------ --------- ---------- ------ ------------ server1 192.168.1.31 1500 Success 140 server2 192.168.1.41 1500 Success 137 Description ----------- Performs asynchronous ping test against listed systems and lists full output with a buffersize of 1500 bytes. #> #Requires -Version 3.0 [OutputType('Net.AsyncPingResult')] [CmdletBinding(ConfirmImpact = 'None')] Param ( [parameter(ValueFromPipeline, Position = 0)] [string[]] $ComputerName, [parameter()] [int] $Timeout = 2000, [parameter()] [Alias('Ttl')] [int] $TimeToLive = 128, [parameter()] [validaterange(32, 65500)] [int] $BufferSize = 32, [parameter()] [switch] $IncludeSource, [parameter()] [switch] $Full ) begin { Write-Verbose -Message "Starting [$($MyInvocation.Mycommand)]" if ($IncludeSource) { $Source = $env:COMPUTERNAME } $Buffer = New-Object -TypeName System.Collections.ArrayList 1..$BufferSize | ForEach-Object { $null = $Buffer.Add(([byte] [char] 'A')) } $PingOptions = New-Object -TypeName System.Net.NetworkInformation.PingOptions $PingOptions.Ttl = $TimeToLive If ($BufferSize -gt 1500) { $DontFragment = $false } else { $DontFragment = $true } Write-Verbose -Message "ComputerName [$($ComputerName -join ',')]" Write-Verbose -Message "BufferSize [$BufferSize]" Write-Verbose -Message "Timeout [$Timeout]" Write-Verbose -Message "TimeToLive [$TimeToLive]" Write-Verbose -Message "IncludeSource [$IncludeSource]" Write-Verbose -Message "Full [$Full]" Write-Verbose -Message "DontFragment [$DontFragment]" $PingOptions.DontFragment = $DontFragment $Computerlist = New-Object -TypeName System.Collections.ArrayList } process { foreach ($Computer in $ComputerName) { [void] $Computerlist.Add($Computer) } } end { $Task = foreach ($Computer in $ComputerList) { [pscustomobject] @{ ComputerName = $Computer Task = (New-Object -TypeName System.Net.NetworkInformation.Ping).SendPingAsync($Computer, $Timeout, $Buffer, $PingOptions) } } try { [void] [Threading.Tasks.Task]::WaitAll($Task.Task) } catch { Write-Error -Message "Error checking [$Computer]" } $Task | ForEach-Object { if ($_.Task.IsFaulted) { $Result = $_.Task.Exception.InnerException.InnerException.Message $IPAddress = $Null $ResponseTime = $Null } else { $Result = $_.Task.Result.Status $IPAddress = $_.task.Result.Address.ToString() $ResponseTime = $_.task.Result.RoundtripTime } $Layout = [ordered] @{ ComputerName = $_.ComputerName IPAddress = if ($IPAddress) { [version] $IPAddress } else { $Null } Result = $Result BufferSize = $BufferSize ResponseTime = $ResponseTime DontFragment = $DontFragment Timeout = $Timeout TimeToLive = $TimeToLive } if ($IncludeSource) { $Layout.Insert(0,'Source',$Source) } $Object = New-Object -TypeName psobject -Property $Layout $Object.pstypenames.insert(0, 'Net.AsyncPingResult') if ($Full) { $Object } else { if ($IncludeSource) { $Object | Select-Object -Property Source, ComputerName, IPAddress, Result } else { $Object | Select-Object -Property ComputerName, IPAddress, Result } } } Write-Verbose -Message "Ending [$($MyInvocation.Mycommand)]" } } |