Test-PowerPing.psm1
if (!$env:NUMBER_OF_PROCESSORS){ if ($ismacos){ $env:NUMBER_OF_PROCESSORS = ((sysctl -a | grep 'machdep.cpu.thread_count') -replace'(.*):','').trim() } Elseif ($isLinux){ $env:NUMBER_OF_PROCESSORS = ((lscpu | grep '^CPU(s):') -replace '(.*):','').trim() } } function get-ppruns { $runspace = [PowerShell]::Create() $null = $runspace.AddScript($pblock) $null = $runspace.AddArgument($time) $null = $runspace.AddArgument($NPReply) $null = $runspace.AddArgument($ad) $null = $runspace.AddArgument($npopt) $null = $runspace.AddArgument($pbuffer) $null = $runspace.AddArgument($Output) $null = $runspace.AddArgument($cnt) $null = $runspace.AddArgument($results) $null = $runspace.AddArgument($cfnd) $null = $runspace.AddArgument($Cpnms) $null = $runspace.AddArgument($so) $runspace.RunspacePool = $pool $null = $runspaces.Add([PSCustomObject]@{Pipe = $runspace; Status = $runspace.BeginInvoke()}) } function get-pping { $NPReply = (new-object System.Net.NetworkInformation.Ping).SendPingAsync("$ad",$time,$pbuffer,$npopt) if ($NPReply.Result.Status -eq 'Success'){ if ($Output.length -gt '0'){ if ($Output -eq 'NoTime/DeviceName'){ $null = $results.$cnt.add([PSCustomObject]@{Status="{0,-11}" -f 'Online'; IPv4Address = if ($ad -like "*.*.*.*"){"{0,-23}" -f "$ad"}Else{"{0,-17}" -f $NPReply.Result.Address.IPAddressToString}}) } elseif ($Output -eq 'NoDeviceName'){ $null = $results.$cnt.add([PSCustomObject]@{Status="{0,-11}" -f 'Online'; IPv4Address =if ($ad -like "*.*.*.*"){"{0,-23}" -f "$ad"}Else{"{0,-17}" -f $NPReply.Result.Address.IPAddressToString};Time = "{0,-5}" -f $NPReply.Result.RoundtripTime}) } elseif ($Output -eq 'NoTime'){ $null = $results.$cnt.add([PSCustomObject]@{Status="{0,-11}" -f 'Online'; IPv4Address =if ($ad -like "*.*.*.*"){"{0,-23}" -f "$ad"}Else{"{0,-17}" -f $NPReply.Result.Address.IPAddressToString};DeviceName = if ($ad -like "*.*.*.*"){([Net.DNS]::GetHostByAddress($NPReply.Result.Address.IPAddressToString).HostName)}Else{$ad}}) } } Else{ $null = $results.$cnt.add([PSCustomObject]@{Status="{0,-11}" -f 'Online'; IPv4Address =if ($ad -like "*.*.*.*"){"{0,-23}" -f "$ad"}Else{"{0,-17}" -f $NPReply.Result.Address.IPAddressToString};DeviceName = if ($ad -like "*.*.*.*"){([Net.DNS]::GetHostByAddress($NPReply.Result.Address.IPAddressToString).HostName)}Else{$ad};Time = "{0,-5}" -f $NPReply.Result.RoundtripTime}) } if ($Cpnms){ if ($Cpnms -contains $results.$cnt.DeviceName){ $null = $cfnd.add($results.$cnt) } } } ELSEif ($so -ne '1' -and $NPReply.Status.value__ -eq '5'){ if ($Output.length -gt '0'){ if ($Output -eq 'NoTime/DeviceName'){ $null = $results.$cnt.add([PSCustomObject]@{Status="{0,-11}" -f $NPReply.Result.Status;IPv4Address = if ($NPReply.Result.Address.IPAddressToString -eq '0.0.0.0'){"{0,-23}" -f ($ad + ": " + $NPReply.Result.Status.value__)}Else{"{0,-23}" -f ($ad + ": " + $NPReply.Result.Status.value__ + ":" + $NPReply.result.Address.IPAddressToString)}}) } elseif ($Output -eq 'NoDeviceName'){ $null = $results.$cnt.add([PSCustomObject]@{Status="{0,-11}" -f $NPReply.Result.Status;IPv4Address = if ($NPReply.Result.Address.IPAddressToString -eq '0.0.0.0'){"{0,-23}" -f ($ad + ": " + $NPReply.Result.Status.value__)}Else{"{0,-23}" -f ($ad + ": " + $NPReply.Result.Status.value__ + ":" + $NPReply.result.Address.IPAddressToString)}; Time =''}) } elseif ($Output -eq 'NoTime'){ $null = $results.$cnt.add([PSCustomObject]@{Status="{0,-11}" -f $NPReply.Result.Status;IPv4Address = if ($NPReply.Result.Address.IPAddressToString -eq '0.0.0.0'){"{0,-23}" -f ($ad + ": " + $NPReply.Result.Status.value__)}Else{"{0,-23}" -f ($ad + ": " + $NPReply.Result.Status.value__ + ":" + $NPReply.result.Address.IPAddressToString)}; DeviceName = ''}) } } Else{ $null = $results.$cnt.add([PSCustomObject]@{Status="{0,-11}" -f $NPReply.Result.Status;IPv4Address = if ($NPReply.Result.Address.IPAddressToString -eq '0.0.0.0'){"{0,-23}" -f ($ad + ": " + $NPReply.Result.Status.value__)}Else{"{0,-23}" -f ($ad + ": " + $NPReply.Result.Status.value__ + ":" + $NPReply.result.Address.IPAddressToString)}; DeviceName = ''; Time = ''}) } } ELSEif ($NPReply.Status.value__ -ne '5'){ if ($Output){ if ($Output -eq 'NoTime/DeviceName'){ $null = $results.$cnt.add([PSCustomObject]@{Status = "{0,-11}" -f 'Error'; IPv4Address = "{0,-23}" -f ($ad+": "+$NPReply.Exception.InnerException.InnerException.ErrorCode+": "+$NPReply.Exception.InnerException.InnerException.Message)}) } elseif ($Output -eq 'NoDeviceName'){ $null = $results.$cnt.add([PSCustomObject]@{Status = "{0,-11}" -f 'Error'; IPv4Address = "{0,-23}" -f ($ad+": "+$NPReply.Exception.InnerException.InnerException.ErrorCode+": "+$NPReply.Exception.InnerException.InnerException.Message); Time = ''}) } elseif ($Output -eq 'NoTime'){ $null = $results.$cnt.add([PSCustomObject]@{Status = "{0,-11}" -f 'Error'; IPv4Address = "{0,-23}" -f ($ad+": "+$NPReply.Exception.InnerException.InnerException.ErrorCode+": "+$NPReply.Exception.InnerException.InnerException.Message); DeviceName = ''; Time = ''}) } } Else{ $null = $results.$cnt.add([PSCustomObject]@{Status = 'Error'; IPv4Address = "{0,-23}" -f ($ad+": "+$NPReply.Exception.InnerException.InnerException.ErrorCode+": "+$NPReply.Exception.InnerException.InnerException.Message); DeviceName = ''; Time = ''}) } } $NPReply = $null } <# .SYNOPSIS Sends single pings asynchronously to remote computers to determine network accessibility. Can be used as IP range scanner, ping utility, CIDR calculator, or address list generator. Returns simple ping results (Status,IPv4Address,DeviceName,Time) with status codes. .DESCRIPTION Test-PowerPing pings IPv4 addresses asynchronously within a given IPv4 address range using PowerShell Runspaces. Ranges can be provided as: Start/EndIP, CIDR, or StartIP with Netmask. 'AddressOnly' switch can be used to calculate IPv4 addresses within a given start/end range. 'IPFilter' parameter can be used to filter IPv4 address lists as needed. 'Sites' parameter set can be used to save IPv4 address ranges, target lists, and CIDR lists. 'CIDR' parameter set can be used to send pings to given CIDR block, provide CIDR block information, or generate address lists for given block(s). 'Mask' parameter set can be used to send pings to given range using Start IP and Netmask, provide CIDR block information, or generate an address list for the given range. 'Address' parameter set can be used to generate/ping addresses within a given range. 'Targets' parameter set (Default) can be used to send pings to a list of targets. Defaults: Output: Status,IPv4Address,DeviceName,Time (Online & Offline) Timeout: 1000 ms TTL: 255 Buffer: 32bytes Throttle(Threads): Number of Available Processors IPFilter: None Stream: Disabled Address Multithreading (AMT): Disabled DYNAMIC PARAMETERS -Site <String[]> Name of saved IPv4 address range, CIDR list, or Target list. Requires valid entry from Site List. -Use "NewSite" to enable add/remove/import/delete/list functionality [Command Example: Test-PowerPing -Site NewSite -Import $mylist] Parameter Set(s): Sites Required? true Position? named DefaultValue Accept pipeline input? true (ByValue) Accept wildcard characters? false .PARAMETER StartIP Beginning address in IPv4 address range. [Command Example: Test-PowerPing -StartIP '10.0.0.0' -Netmask '255.255.255.0'] Parameter Set(s): Address,Mask .PARAMETER EndIP Ending address in IPv4 address range. [Command Example: Test-Powerping -StartIP '10.0.0.0' -EndIP '10.0.0.255'] Parameter Set(s): Address .PARAMETER Target Single device name/IPv4 address, or list of device names/IPv4 addresses to be pinged. [Command Example: Test-PowerPing -Target 'website.com,www.anothersite.com,10.0.0.223'] Parameter Set(s): Targets .PARAMETER CIDR Address block entry using CIDR notation -Minimum MaskBits: 8 [Command Example: Test-PowerPing -CIDR '10.0.0.18/24'] Parameter Set(s): CIDR .PARAMETER Netmask Netmask for given StartIP -Minimum Value: 255.0.0.0 [Command Example: Test-PowerPing -StartIP '10.0.0.18' -Netmask '255.255.255.0'] Parameter Set(s): Mask .PARAMETER AddressOnly Switch to provide IPv4 address list only for Start/EndIP, CIDR Block, or Start with Netmask. -Multithreading available with AMT Parameter [Command Example: Test-PowerPing -StartIP '10.0.0.0' -EndIP '10.255.255.255' -AddressOnly] Parameter Set(s): Address,Mask,CIDR,Sites .PARAMETER CIDcalc Provides CIDR block information about provided block. -Available for both CIDR and Netmask entries [Command Example: Test-PowerPing -CIDR '10.0.0.0/8' -CIDcalc] Parameter Set(s): Mask,CIDR,Sites .PARAMETER AssignOnly Only returns/pings assignable addressess for given CIDR or Netmask Range. [Command Example: Test-PowerPing -StartIP '192.168.20.0' -Netmask '255.255.255.0' -AssignOnly] Parameter Set(s): Mask,CIDR .PARAMETER AMT Maximum number of runspaces used to compile address list. See Notes for qualifying ranges. -Maximum input = $env:NUMBER_OF_PROCESSORS, Minimum input = 1 [Command Example: Test-PowerPing -StartIP '10.0.0.0' -Netmask '255.0.0.0' -AddressOnly -AMT 4] Parameter Set(s): Address,Mask,CIDR,Sites .PARAMETER Throttle Maximum number of runspaces used to send asynchronous pings on a given scan. -Maximum input = 256, Minimum input = 1 [Command Example: Test-PowerPing -CIDR '10.0.0.0/24' -Throttle 64] Parameter Set(s): Address,Mask,CIDR,Sites,Targets .PARAMETER ComputerName Filters output to entries where DeviceName resolves to the provided input. -Enables OnlineOnly parameter when used [Command Example: Test-PowerPing -Site TheBeach -ComputerName "MyComputerA","MyComputerB"] Parameter Set(s): Address,Mask,CIDR,Sites .PARAMETER IPFilter Filters/removes IPv4 address list entries where addresses match the provided input. -Whole number entries (0-255) will be filtered from the 4th octet for all range entries -Full addresses can be provided to filter specific IPs ('192.168.50.1') -Wildcards can be used for pattern filtering ('10.2.*.*') -Having multiple filters may increase address list calculation time [Command Example: Test-PowerPing -CIDR 10.0.0.0/14 -AddressOnly -iPFilter '0','10.1.1.2'] Parameter Set(s): Address,Mask,CIDR,Sites .PARAMETER TTL Sets 'TimeToLive' option property for asynchronous pings. -Maximum Input = '255' [Command Example: Test-PowerPing -Target mysite.com -TTL 128] Parameter Set(s): Address,Mask,CIDR,Sites,Targets .PARAMETER Timeout Sets response time maximum property for asynchronous pings in milliseconds. -Maximum Input = '60000' [Command Example: Test-PowerPing -Target mydevice -Timeout 3000] Parameter Set(s): Address,Mask,CIDR,Sites,Targets .PARAMETER Buffer Sets buffer data property for asynchronous pings in bytes. -Maximim Input = '65500' [Command Example: Test-PowerPing -Target mydevice -Timeout 3000 -Buffer 64] Parameter Set(s): Address,Mask,CIDR,Sites,Targets .PARAMETER OnlineOnly Resulting output will only display pings with a successful response. [Command Example: Test-PowerPing -CIDR 192.168.50.0/24 -OnlineOnly] Parameter Set(s): Address,Mask,CIDR,Sites,Targets .PARAMETER Output Reduces available output properties based on selection. [Command Example: Test-PowerPing -Site TheBeach -Output NoTime/DeviceName] Parameter Set(s): Address,Mask,CIDR,Sites,Targets .PARAMETER AddSite Site Name for addition to Site List. May require admin permissions. -Can only use one method [AddSite,RemoveSite,Import,ListSites,DeleteSites] per call [Command Example: Test-PowerPing -Site NewSite -AddSite 'Site' -Range '"10.0.0.0","10.0.0.255"'] Parameter Set(s): Sites .PARAMETER Range Site Range for addition to Site List. Used with 'AddSite' Parameter. May require admin. -Must Provide 2 IPv4 addresses (Start & End), separated by commas, contained in single quotes [Command Example: Test-PowerPing -Site NewSite -AddSite 'Site' -Range '"10.0.0.0","10.0.0.255"'] Parameter Set(s): Sites .PARAMETER nTargetList List of new Targets for addition to Site List. Used with 'AddSite' Parameter. May require admin. -Can enter single Target or list of multiple Targets [Command Example: Test-PowerPing -Site NewSite -AddSite 'Site' -nTargetList "site.com,MYPC"] Parameter Set(s): Sites .PARAMETER nCIDRList List of CIDR blocks for addition to Site List. Used with 'AddSite' Parameter. May require admin. -Can enter single block or list of multiple blocks -Each entry in list must be quoted as example below [Command Example: Test-PowerPing -Site NewSite -AddSite 'Site' -nCIDRList "1.0.0.0/8","8.0.0.0/13"] Parameter Set(s): Sites .PARAMETER RemoveSite Site Name for removal from Site List. May require admin permissions. -Can only use one method [AddSite,RemoveSite,Import,ListSites,DeleteSites] per call [Command Example: Test-PowerPing -Site NewSite -RemoveSite 'TheBeach'] Parameter Set(s): Sites .PARAMETER ListSites Lists saved Site names and ranges. -Can only use one method [AddSite,RemoveSite,Import,ListSites,DeleteSites] per call [Command Example: Test-PowerPing -Site NewSite -ListSites] Parameter Set(s): Sites .PARAMETER DeleteSites Deletes Site List CSV and resets Site List. May require admin permissions. -Can only use one method [AddSite,RemoveSite,Import,ListSites,DeleteSites] per call [Command Example: Test-PowerPing -Site NewSite -DeleteSites] Parameter Set(s): Sites .PARAMETER Import Specifies PSObject or Hashtable to be used to import new entries to Sites list. May require admin. -Can only use one method [AddSite,RemoveSite,Import,ListSites,DeleteSites] per call [Command Example: Test-PowerPing -Site NewSite -Import $mysitelist] Parameter Set(s): Sites .PARAMETER Stream Enable streaming ping output. Stream count matches Throttle. [Command Example: Test-PowerPing -Site MySite -Stream] Parameter Set(s): Address,Mask,CIDR,Sites,Targets .EXAMPLE Test-PowerPing -StartIP '192.168.20.0' -EndIP '192.168.20.255' Status IPv4Address DeviceName Time ------ ----------- ---------- ---- TimedOut 192.168.20.0: 11010 Online 192.168.20.1 XT8 1 (...) ____________________________________________________________________ Ping addresses within the range 192.168.20.0 - 192.168.20.255 with 32byte buffer, 1000ms timeout, and 255 ttl. .EXAMPLE Test-PowerPing -CIDR 192.168.20.0/23 -Throttle 64 -Timeout '300' -TTL '128' -Buffer '64' -IPFilter "192.168.20.3" Status IPv4Address DeviceName Time ------ ----------- ---------- ---- TimedOut 192.168.20.2: 11010 TimedOut 192.168.20.4: 11010 (...) ____________________________________________________________________ Ping addresses within the range 192.168.20.0 - 192.168.21.255 with custom ping options, increased runspaces (Throttle), and an IPFilter. Sends Pings with the provided values for 'Timeout','TTL', and 'Buffer' using a runspace pool with 64 runspaces. Returns Ping result for successful/unsuccessful addresses that do not equal "192.168.20.3" .EXAMPLE Test-PowerPing -Site NewSite -AddSite "MyNewSite" -Range '"192.168.20.0","192.168.20.255"' ********-OR-******** PS C:\> Test-PowerPing -Site NewSite -AddSite "MyNewSitenCIDR" -nCIDRList "192.168.20.0/25","192.168.20.128/25" ********-OR-******** PS C:\> Test-PowerPing -Site NewSite -AddSite "MyNewSitenTarget" -nTargetList "192.168.20.0,192.168.20.1,..." PS C:\> Test-PowerPing -Site NewSite -ListSites Name Value ---- ----- MyNewSitenCIDR CIDRList,192.168.20.0/25,192.168.20.128/25 (single entry-192.168.20.0/24) MyNewSite "192.168.20.0","192.168.20.255" MyNewSitenTarget TargetList,192.168.20.0,192.168.20.1,192.168.20.2,192.168.20.3,... NewSite "0.0.0.0","0.0.0.0" ____________________________________________________________________ Adds new site 'MyNewSite' to Site List with range '"192.168.20.0","192.168.20.255"'. **Note Adding/Removing Sites may require admin permissions depending on module install location** .EXAMPLE Test-PowerPing -Site NewSite -RemoveSite "MyNewSite" PS C:\> Test-PowerPing -Site NewSite -ListSites Name Value ---- ----- MyNewSitenCIDR CIDRList,192.168.20.0/25,192.168.20.128/25 MyNewSitenTarget TargetList,192.168.20.0,192.168.20.1,192.168.20.2,192.168.20.3,... NewSite "0.0.0.0","0.0.0.0" ____________________________________________________________________ Removes site 'MyNewSite' and corresponding range from Site List. **Note Adding/Removing Sites may require admin permissions depending on module install location** .EXAMPLE Test-PowerPing -Site NewSite -Import $mylist nCIDRList requires first value 'CIDRList' as example above nTargetList requires first value 'TargetList' as example above Example List (Hashtable): $mylist = @{} $mylist.add("MyNewSite",'"10.0.0.0","10.0.0.255"') $mylist Name Value ---- ----- MyNewSite "10.0.0.0","10.0.0.255" --|||--Equivalent Object can also be used for Import--|||--- Example .CSV (Object): $mylist.GetEnumerator() | Select-Object -Property Name,Value | Export-Csv <YourPathHere> -NoTypeInformation $mycsv = import-csv <YourPathHere> Test-PowerPing -Site NewSite -Import $mycsv ____________________________________________________________________ Adds list containing entry "MyNewSite" with range "10.0.0.0" - "10.0.0.255" to Site List using import. .EXAMPLE Test-PowerPing -Target 'powershellgallery.com,www.powershellgallery.com,mozilla.com,TestComputer' Status IPv4Address DeviceName Time ------ ----------- ---------- ---- Online 20.236.44.162 powershellgallery.com 77 DestinationHostUnreachable www.powershellgallery.com: 11003:40.122.208.145 TimedOut mozilla.com: 11010 Error TestComputer: 11001: No such host is known ____________________________________________________________________ Returns ping results for 4 targets: powershellgallery.com, www.powershellgallery.com, mozilla.com,TestComputer .EXAMPLE Test-PowerPing -CIDR 192.168.20.0/24 -CIDcalc ********-OR-******** PS C:\> Test-PowerPing -StartIP '192.168.20.0' -Netmask '255.255.255.0' -CIDcalc CIDR : 192.168.20.0/24 BaseIP : 192.168.20.0 BroadcastIP : 192.168.20.255 AddressCount : 256 FirstAssignable : 192.168.20.1 LastAssignable : 192.168.20.254 AssignableAddresses : 254 Netmask : 255.255.255.0 ____________________________________________________________________ Returns CIDR block information for the provided CIDR block, or StartIP with the provided Netmask. .EXAMPLE measure-command {$test = test-powerping -CIDR '10.168.50.0/8' -AssignOnly -AddressOnly -AMT 4} TotalSeconds : 63.4740016 $test.count 16777214 $test[0..-1] 10.0.0.1 10.255.255.254 ____________________________________________________________________ Returns a string list containing addressess from 10.0.0.1 to 10.255.255.254 and assigns to $test. Unassignalbe addresses from the given CIDR block are removed with 'AssignOnly' parameter. Multithreading used for address generation with 'AMT' parameter, using 4 threads (times may vary). **Note large address ranges will increase address list calculation time** **Note pinging or creating large address ranges may max resources or exceed memory resource limitations** .NOTES Running Large Range Scans or Address Lists May Increase/Max Resource Utilization - Using max Throttle (256) may significantly increase memory utilization - Using multiple filters or large match patterns (10.7.*.*) will increase address generation time. -- Use CIDR parameter with multiple block entries to avoid large filters Qualifying Ranges for AMT -With AMT enabled, multithreading will be used to calculate address lists if the range size meets requirements. -To run with Multithreading, the 2nd octet must have a difference of 7 or greater. -Example Range (does not qualify) '10.0.0.0' - '10.3.255.255' The range above will be split into 2 sections, each will run in the parent function. -Example Range (Minimum) '10.0.0.0' - '10.6.*.*' The range above will be split into 4 sections equivalent to '10.0.0.0' - '10.1.255.255' First and last sections will run in parent function, all others will run in runspaces. 'Sites' functionality is dependent on saving a .CSV file to Module install directory. Modifying Sites/SiteList May Require Admin Permissions All Site Modification Switches/Parameters require 'NewSite' selection for 'Site' Parameter Version: 1.0 --------------- Date: 9/16/2023 --------------- Author: Hunter Hirsch #> function Test-PowerPing { [CmdletBinding(DefaultParameterSetName='Targets')] Param( [Parameter(Mandatory,ParameterSetName='Address',ValueFromPipeline,HelpMessage='Enter Valid IPv4 Address (Ex: "10.0.0.0")')] [Parameter(Mandatory,ParameterSetName='Mask',ValueFromPipeline,HelpMessage='Enter Valid IPv4 Address (Ex: "10.0.0.0")')] [ValidatePattern('^(([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5])\.){3}([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5]){1}$')] [ValidateLength(7,15)] [string] $StartIP, [Parameter(Mandatory,ParameterSetName="Address",ValueFromPipeline,HelpMessage='Enter Valid IPv4 Address (Ex: "10.0.0.0")')] [ValidatePattern('^(([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5])\.){3}([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5]){1}$')] [ValidateLength(7,15)] [string] $EndIP, [Parameter(Mandatory,ParameterSetName="Mask",ValueFromPipeline,HelpMessage='Enter Valid Netmask (Ex: "255.255.255.0")')] [ValidateScript({if ($_ -in ('255.0.0.0','255.128.0.0','255.192.0.0','255.224.0.0','255.240.0.0','255.248.0.0','255.252.0.0','255.254.0.0','255.255.0.0','255.255.128.0','255.255.192.0','255.255.224.0','255.255.240.0','255.255.248.0','255.255.252.0','255.255.254.0','255.255.255.0','255.255.255.128','255.255.255.192','255.255.255.224','255.255.255.240','255.255.255.248','255.255.255.252','255.255.255.254','255.255.255.255')){$true} Else{ Throw Write-Output 'Cannot be null. Must be valid Netmask. Subnet Bit Minimum = 8 (255.0.0.0)' } })] [ValidateLength(9,15)] [string] $Netmask, [Parameter(Mandatory,ParameterSetName='CIDR',ValueFromPipeline,HelpMessage='Enter Valid CIDR Range (Ex: "10.0.0.0/24")')] [ValidateScript({ $_ | foreach-object {if ($_ -match '^(([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5])\.){3}([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5]){1}(\/([8-9]|[1-2][0-9]|3[0-2]))$'){ $true } Else{ Throw Write-Output 'Cannot be null. Entries must be enclosed with quotes, then separated by commas. Ex:"10.0.0.0/8","11.0.0.0/12" Subnet Bit Minimum = 8' } } })] [string[]] $CIDR, [Parameter(ValueFromPipeline,ParameterSetName='Sites')] [Parameter(ValueFromPipeline,ParameterSetName='CIDR')] [Parameter(ValueFromPipeline,ParameterSetName='Mask')] [ValidateScript({ if (!$AssignOnly){ $true } Else{ Throw Write-Output 'Cannot be used with "AssignOnly" Parameter.' } })] [switch] $CIDcalc, [Parameter(ParameterSetName='CIDR',ValueFromPipeline)] [Parameter(ParameterSetName='Mask',ValueFromPipeline)] [Parameter(ParameterSetName='Sites',ValueFromPipeline)] [ValidateScript({ if (!$CIDcalc){ $true } Else{ Throw Write-Output 'Cannot be used with "CIDcalc" Parameter.' } })] [switch] $AssignOnly, [Parameter(ParameterSetName='Sites',ValueFromPipeline)] [ValidateScript({ if(!($RemoveSite) -and !($DeleteSites) -and !($ListSites) -and !($Import) -and $_ -ne $null){ $true } Else{ Throw Write-Output 'Cannot be null. Cannot be used with RemoveSite,DeleteSites,ListSites,Import Parameters.' } })] [string] $AddSite, [Parameter(ParameterSetName='Sites',ValueFromPipeline)] [ValidateScript({ if (!($AddSite) -and !($DeleteSites) -and !($ListSites) -and !($Import) -and $_ -ne $null){ $true } Else{ Throw Write-Output 'Cannot be null. Cannot be used with AddSite,DeleteSites,ListSites,Import Parameters.' } })] [string] $RemoveSite, [Parameter(ParameterSetName='Sites',ValueFromPipeline)] [ValidateScript({ if (!($RemoveSite) -and !($AddSite) -and !($ListSites) -and !($Import)){ $true } Else{ Throw Write-Output 'Cannot be used with AddSite,RemoveSite,ListSites,Import Parameters.' } })] [switch] $DeleteSites, [Parameter(ParameterSetName='Sites',ValueFromPipeline)] [ValidateScript({ if (!($RemoveSite) -and !($AddSite) -and !($DeleteSites) -and !($Import)){ $true } Else{ Throw Write-Output 'Cannot be used with AddSite,RemoveSite,DeleteSites,Import Parameters.' } })] [switch] $ListSites, [Parameter(ParameterSetName='Sites',ValueFromPipeline)] [ValidateScript({ if(!($RemoveSite) -and !($DeleteSites) -and !($ListSites) -and !($Import) -and !($nTargetList) -and !($nCIDRList) -and $_ -match '^"(([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5])\.){3}([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5]){1}","(([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5])\.){3}([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5]){1}"$' -and $_.split(',')[0] -ne $_.split(',')[1]){ $true } Else{ Throw Write-Output 'Can only be used with "-Site NewSite -AddSite" Parameters. Cannot be null. Must be 2 valid IP addresses. IP Addresses cannot be the same. Type "Get-Help Test-PowerPing -Parameter Range" for further information.' } })] [string] $Range, [Parameter(ParameterSetName='Sites',ValueFromPipeline)] [ValidateScript({ if (!($AddSite) -and !($DeleteSites) -and !($RemoveSite) -and !($ListSites) -and $_.gettype().name -eq 'PSCustomObject' -or $_.gettype().name -eq 'Hashtable'){ $true } Else{ Throw Write-Output 'Cannot be used with AddSite,RemoveSite,ListSites,DeleteSites Parameters.' } })] [object] $Import, [Parameter(ParameterSetName='Sites',ValueFromPipeline)] [ValidateScript({ if (!($DeleteSites) -and !($RemoveSite) -and !($ListSites) -and !($Import) -and !($Range) -and !($nTargetList) -and ($_ | foreach-object {$_ -match '^(([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5])\.){3}([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5]){1}(\/([8-9]|[1-2][0-9]|3[0-2]))$'})){ $true } Else{ Throw Write-Output 'Must be used with AddSite parameter. Cannot be null. Entries must be enclosed with quotes, then separated by commas. Ex:"10.0.0.0/8","11.0.0.0/12" Subnet Bit Minimum = 8' } })] [string[]] $nCIDRList, [Parameter(ParameterSetName='Sites',ValueFromPipeline)] [ValidateScript({ if (!($DeleteSites) -and !($RemoveSite) -and !($ListSites) -and !($Import) -and !($Range) -and !($nCIDRList) -and $_ -ne $null){ $true } Else{ Throw Write-Output 'Can only be used with "-Site NewSite -AddSite" Parameters. Cannot be used with "Range" Parameter. Cannot be null. Type "Get-Help Test-PowerPing -Parameter nTargetList" for further information.' } })] [String[]] $nTargetList, [Parameter(Mandatory,ParameterSetName='Targets',ValueFromPipeline,Position=0,HelpMessage='Enter Device Name, Web Address, or IPv4 address.')] [ValidateScript({$_ -ne $null})] [string[]] $Target, [Parameter(ValueFromPipeline,ParameterSetName='Sites')] [Parameter(ValueFromPipeline,ParameterSetName='Address')] [Parameter(ValueFromPipeline,ParameterSetName='CIDR')] [Parameter(ValueFromPipeline,ParameterSetName='Mask')] [ValidateScript({ if ($_ -ne $null -and $Output -ne 'NoDeviceName' -and $Output -ne 'NoTime/DeviceName'){ $true } Else{ Throw Write-Output 'Cannot be null. Cannot be used with "Output NoDeviceName" and "Output NoTime/DeviceName" Parameters.' } })] [string[]] $ComputerName, [Parameter(ValueFromPipeline,ParameterSetName='Sites')] [Parameter(ValueFromPipeline,ParameterSetName='Address')] [Parameter(ValueFromPipeline,ParameterSetName='CIDR')] [Parameter(ValueFromPipeline,ParameterSetName='Mask')] [switch] $AddressOnly, [Parameter(ValueFromPipeline,ParameterSetName='Sites')] [Parameter(ValueFromPipeline,ParameterSetName='Address')] [Parameter(ValueFromPipeline,ParameterSetName='CIDR')] [Parameter(ValueFromPipeline,ParameterSetName='Mask')] [ValidateScript({ if($_ -in (1..[int]$env:NUMBER_OF_PROCESSORS)){ $true } Else{ Throw Write-Output 'Must be an integer between "1" and "$env:Number_of_Processors" (inclusive). Enter "$env:Number_of_Processors" for max performance.' } })] [int] $AMT, [Parameter(ValueFromPipeline,ParameterSetName='Sites')] [Parameter(ValueFromPipeline,ParameterSetName='Address')] [Parameter(ValueFromPipeline,ParameterSetName='CIDR')] [Parameter(ValueFromPipeline,ParameterSetName='Mask')] [ValidateScript({ if ($_ | foreach-object {if ($_.length -gt '3'){$_ -like '*.*.*.*' -and $_.length -le '15'}Else{$_.length -le '3' -and $_ -notmatch '[a-zA-Z]' -and ($_ -replace '\d','').Length -eq '0'}}){ $true } Else{ Throw Write-Ouput 'Can only filter: End Octets (ex:"0" or "255") IP Addresses (ex:"10.2.3.200") IP Address Patterns (ex:"10.2.*.*") Lists must be quoted and comma separated (ex:"255","10.2.*.*")' } })] [string[]] $iPFilter, [Parameter(ValueFromPipeline,ParameterSetName='Sites')] [Parameter(ValueFromPipeline,ParameterSetName='Address')] [Parameter(ValueFromPipeline,Position=3,ParameterSetName='Targets')] [Parameter(ValueFromPipeline,ParameterSetName='CIDR')] [Parameter(ValueFromPipeline,ParameterSetName='Mask')] [ValidateScript({[int]$_ -le '255'})] [int] $TTL, [Parameter(ValueFromPipeline,ParameterSetName='Sites')] [Parameter(ValueFromPipeline,ParameterSetName='Address')] [Parameter(ValueFromPipeline,Position=1,ParameterSetName='Targets')] [Parameter(ValueFromPipeline,ParameterSetName='CIDR')] [Parameter(ValueFromPipeline,ParameterSetName='Mask')] [ValidateScript({[int]$_ -le '60000'})] [int] $Timeout, [Parameter(ValueFromPipeline,ParameterSetName='Sites')] [Parameter(ValueFromPipeline,ParameterSetName='Address')] [Parameter(ValueFromPipeline,Position=2,ParameterSetName='Targets')] [Parameter(ValueFromPipeline,ParameterSetName='CIDR')] [Parameter(ValueFromPipeline,ParameterSetName='Mask')] [ValidateScript({[int]$_ -le '65500'})] [int] $Buffer, [Parameter(ValueFromPipeline,ParameterSetName='Sites')] [Parameter(ValueFromPipeline,ParameterSetName='Address')] [Parameter(ValueFromPipeline,Position=7,ParameterSetName='Targets')] [Parameter(ValueFromPipeline,ParameterSetName='CIDR')] [Parameter(ValueFromPipeline,ParameterSetName='Mask')] [switch] $Stream, [Parameter(ValueFromPipeline,ParameterSetName='Sites')] [Parameter(ValueFromPipeline,ParameterSetName='Address')] [Parameter(ValueFromPipeline,Position=6,ParameterSetName='Targets')] [Parameter(ValueFromPipeline,ParameterSetName='CIDR')] [Parameter(ValueFromPipeline,ParameterSetName='Mask')] [ValidateScript({$_ -in (1..256)})] [int] $Throttle, [Parameter(ValueFromPipeline,ParameterSetName='Sites')] [Parameter(ValueFromPipeline,ParameterSetName='Address')] [Parameter(ValueFromPipeline,Position=4,ParameterSetName='Targets')] [Parameter(ValueFromPipeline,ParameterSetName='CIDR')] [Parameter(ValueFromPipeline,ParameterSetName='Mask')] [switch] $OnlineOnly, [Parameter(ValueFromPipeline,ParameterSetName='Sites')] [Parameter(ValueFromPipeline,ParameterSetName='Address')] [Parameter(ValueFromPipeline,Position=5,ParameterSetName='Targets')] [Parameter(ValueFromPipeline,ParameterSetName='CIDR')] [Parameter(ValueFromPipeline,ParameterSetName='Mask')] [ValidateSet('NoTime','NoDeviceName','NoTime/DeviceName')] [string] $Output ) DynamicParam{ $pdic = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary $pcol = New-Object System.Collections.ObjectModel.Collection[System.Attribute] $patt = New-Object System.Management.Automation.ParameterAttribute $plist = Test-Path ((get-module Test-PowerPing | Select-Object -ExpandProperty ModuleBase) + '\PPSites.csv') -PathType Leaf if ($plist){ $pexp = (get-module Test-PowerPing | Select-Object -ExpandProperty ModuleBase) + '\PPSites.csv' | Import-Csv | Select-Object -ExpandProperty Name } Else{ $pexp = 'NewSite' } $pexps = $pexp -join ',' $patt.Mandatory = $true $patt.HelpMessage = "Enter Site name for existing saved Site, or 'NewSite' to modify Site List. SiteList: $pexps" $patt.ParameterSetName = 'Sites' $patt.ValueFromPipeline = $true $pcol.Add($patt) $pvsa = New-Object System.Management.Automation.ValidateSetAttribute(($pexp)) $pcol.Add($pvsa) $RParam = New-Object System.Management.Automation.RuntimeDefinedParameter('Site', [string], $pcol) $RParam.Value = 'NewSite' $pdic.Add('Site',$RParam) return $pdic } begin { $Site = $PSBoundParameters.Site Try{ if ($Site){ if ($ListSites -or $AddSite -or $RemoveSite -or $DeleteSites -or $Import -or $nTargetList -or $nCIDRList -or $Range -and $Site -ne 'NewSite'){ $Mant = 'Error: (-Site NewSite) Required to Modify Site List' Throw } $sitep = (get-module -name Test-PowerPing | Select-Object -ExpandProperty ModuleBase) + '\PPSites.csv' if (Test-Path -Path $sitep -PathType Leaf){ $siteimp = Import-Csv $sitep $Sites = @{} $siteimp | ForEach-Object {$Sites.add($_.name,$_.value)} } Else{ $Sites = @{'NewSite' = '"0.0.0.0","0.0.0.0"'} } if ($Site -eq 'NewSite'){ if (!($AddSite) -and !($RemoveSite) -and !($DeleteSites) -and !($ListSites) -and !($Import)){ $Mant = 'Error: No Action Selected for "NewSite"' Throw } if ($ListSites){ $Sites return } Try{ $null = new-item -Path ((get-module -name Test-PowerPing | Select-Object -ExpandProperty ModuleBase) + '\accesstest.txt') -ErrorAction Stop $null = remove-item -path ((get-module -name Test-PowerPing | Select-Object -ExpandProperty ModuleBase) + '\accesstest.txt') -Force -ErrorAction Stop } Catch{ $Mant = '###Error: Access Denied. Must run PowerShell as Admin to modify Sites ###' Throw } if ($AddSite){ if ($Sites.Count -ge '5000'){ Throw Write-Output '###Error: Sitelist limit reached. Please remove Sites to add New Site ###' } if ((Get-ItemProperty -Path $sitep -Name Length -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Length) -ge '1000000'){ Throw Write-Output '###Error: Sitelist size limit reached (1MB). Please remove Sites to add New Site ###' } if ($Sites.Keys -notcontains $AddSite -and !($nTargetList) -and !($nCIDRList)){ $AddSite = $AddSite.Trim() -replace '"','' -replace "'",'' $Sites.Add("$AddSite","$Range") $Sites.GetEnumerator() | Select-Object -Property Name,Value | Export-Csv $sitep -NoTypeInformation -ErrorAction Stop Write-Output '<<< Update Successful - Module Re-import may be needed>>>' Remove-Item -Path Function:\Test-PowerPing return } Elseif ($Sites.Keys -notcontains $AddSite -and !($Range) -and !($nCIDRList)){ $AddSite = $AddSite.Trim() -replace '"','' -replace "'",'' if ($nTargetList.Count -gt '1'){ if ($nTargetList.count -gt '65536'){ Throw Write-Output '###Error: Targetlist too large- Max Entry Count: 65536 ###' } $nTargetList = 'TargetList,' + ($nTargetList -join ',') } Else{ if ($nTargetList.Length -gt '795658'){ Throw Write-Output '###Error: Targetlist too large- Max Entry Length: 795658 ###' } $nTargetList ='TargetList,' + $nTargetList } $Sites.Add("$AddSite","$nTargetList") $Sites.GetEnumerator() | Select-Object -Property Name,Value | Export-Csv $sitep -NoTypeInformation -ErrorAction Stop Write-Output '<<< Update Successful - Module Re-import may be needed>>>' Remove-Item -Path Function:\Test-PowerPing return } Elseif ($Sites.Keys -notcontains $AddSite -and !($Range) -and !($nTargetList)){ $AddSite = $AddSite.Trim() -replace '"','' -replace "'",'' if ($nCIDRList.Count -gt '1'){ if ($nCIDRList.count -gt '65536'){ Throw Write-Output '###Error: CIDRlist too large- Max Entry Count: 65536 ###' } $aCIDRList = 'CIDRList,' + ($nCIDRList -join ',') } Else{ $aCIDRList = 'CIDRList,' + ($nCIDRList -join ',') } $Sites.Add("$AddSite","$aCIDRList") $Sites.GetEnumerator() | Select-Object -Property Name,Value | Export-Csv $sitep -NoTypeInformation -ErrorAction Stop Write-Output '<<< Update Successful - Module Re-import may be needed>>>' Remove-Item -Path Function:\Test-PowerPing $aCIDRList = $null return } Else{ Write-Output 'Duplicate entry, check value and try again' return } } Elseif ($RemoveSite){ if ($Sites.Keys -contains $RemoveSite -and $RemoveSite -ne 'NewSite'){ $Sites.Remove("$RemoveSite") $Sites.GetEnumerator() | Select-Object -Property Name,Value | Export-Csv $sitep -NoTypeInformation -ErrorAction Stop Write-Output '<<< Update Successful - Module Re-import may be needed >>>' Remove-Item -Path Function:\Test-PowerPing return } Else{ Write-Output 'No entry found matching RemoveSite name, check value and try again' return } } Elseif ($Import){ if ($Import.GetType().name -eq 'Hashtable'){ $vtest = $Import.values | ForEach-Object { if ($_ -match '^"(([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5])\.){3}([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5]){1}","(([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5])\.){3}([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5]){1}"$'){ $true } Elseif ($_ -match 'CIDRList,'){ [int]$nccnt = $_.count -1 $cidfl = $_.split(',')[1..$nccnt] $cidfl | ForEach-Object { if ($_ -match '^(([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5])\.){3}([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5]){1}(\/([8-9]|[1-2][0-9]|3[0-2]))$'){ $true } Else{ $false } } } Elseif ($_ -match 'TargetList,'){ if ($_.length -le '795658'){ $true } } Else{ $false } } $klist = $Import.Keys | Where-Object {$Sites.Keys -notcontains $_} if ($vtest -notcontains $false -and $klist.count -gt '0'){ $klist | ForEach-Object {$Sites.Add("$_",$import[$_])} -ErrorAction Stop $Sites.GetEnumerator() | Select-Object -Property Name,Value | Export-Csv $sitep -NoTypeInformation -ErrorAction Stop Write-Output '<<< Update Successful - Module Re-import may be needed >>>' Remove-Item -Path Function:\Test-PowerPing return } Else{ Write-Output 'Bad Import List. Review List for Errors/Duplicates and try again. Enter "Get-Help Test-PowerPing -Examples" for entry syntax (Example#:5).' return } } if ($Import.GetType().name -eq 'Object[]'){ $vtest = $Import.value | ForEach-Object { if ($_ -match '^"(([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5])\.){3}([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5]){1}","(([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5])\.){3}([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5]){1}"$'){ $true } Elseif ($_ -match 'CIDRList,'){ [int]$nccnt = $_.count -1 $cidfl = $_.split(',')[1..$nccnt] $cidfl | ForEach-Object { if ($_ -match '^(([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5])\.){3}([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5]){1}(\/([8-9]|[1-2][0-9]|3[0-2]))$'){ $true } Else{ $false } } } Elseif ($_ -match 'TargetList,'){ if ($_.length -le '795658'){ $true } } Else{ $false } } $klist = $Import | Where-Object {$Sites.Keys -notcontains $_.name} if ($vtest -notcontains $false -and $klist.count -gt '0'){ $klist | ForEach-Object {$Sites.Add($_.name,$_.value)} -ErrorAction Stop $Sites.GetEnumerator() | Select-Object -Property Name,Value | Export-Csv $sitep -NoTypeInformation -ErrorAction Stop Write-Output '<<< Update Successful - Module Re-import may be needed >>>' Remove-Item -Path Function:\Test-PowerPing return } Else{ Write-Output 'Bad Import List. Review List for Errors/Duplicates and try again' return } } } Elseif ($DeleteSites){ if (Test-Path $sitep -PathType Leaf){ Remove-Item -Path $sitep -Force -ErrorAction Stop } Write-Output '<<< Update Successful - Module Re-import may be needed >>>' Remove-Item -Path Function:\Test-PowerPing return } } Else{ if ((($Sites[$Site]) -split ',')[0] -eq 'TargetList'){ $Target = ($Sites[$Site]) -replace 'TargetList,','' } Elseif ((($Sites[$Site]) -split ',')[0] -eq 'CIDRList'){ $CIDR = (($Sites[$Site]) -replace 'CIDRList,','').Split(',') } Elseif ($Sites[$Site] -match '^"(([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5])\.){3}([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5]){1}","(([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5])\.){3}([0-1]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5]){1}"$'){ $StartIP = (($Site | ForEach-Object {$Sites[$_]}) -split ',' -replace '"','')[0] $EndIP = (($Site | ForEach-Object {$Sites[$_]}) -split ',' -replace '"','')[1] } } } if ($StartIP -and !($Netmask)){ if ($StartIP -eq $EndIP){ $Target = $StartIP if ($AddressOnly){ $Target return } } Else{ $rngparam = @{ Start = $StartIP End = $EndIP } if ($iPFilter){ $rngparam.Add('Filter',$iPFilter) } if ($AMT){ $rngparam.Add('MT',$AMT) } if ($AddressOnly){ Get-PowerIPRange @rngparam return } Else{ $aexp = {Get-PowerIPRange @rngparam} } } } if ($Netmask){ $nl = @{ '255.0.0.0' = '8' '255.128.0.0' = '9' '255.192.0.0' = '10' '255.224.0.0' = '11' '255.240.0.0' = '12' '255.248.0.0' = '13' '255.252.0.0' = '14' '255.254.0.0' = '15' '255.255.0.0' = '16' '255.255.128.0' = '17' '255.255.192.0' = '18' '255.255.224.0' = '19' '255.255.240.0' = '20' '255.255.248.0' = '21' '255.255.252.0' = '22' '255.255.254.0' = '23' '255.255.255.0' = '24' '255.255.255.128' = '25' '255.255.255.192' = '26' '255.255.255.224' = '27' '255.255.255.240' = '28' '255.255.255.248' = '29' '255.255.255.252' = '30' '255.255.255.254' = '31' '255.255.255.255' = '32' } $CIDR = $StartIP + '/' + $nl.$Netmask } if ($CIDR){ $cidparam = @{ Range = $CIDR } if (!$CIDcalc){ if ($AssignOnly){ $cidparam.Add('AssignO',$true) } if ($iPFilter){ $cidparam.Add('Filter',$iPFilter) } if ($AMT){ $cidparam.Add('MT',$AMT) } if ($AddressOnly){ Get-PowerIPCIDR @cidparam return } Else{ $aexp = {Get-PowerIPCIDR @cidparam} } } Else{ $cidparam.Add('Calculator',$true) Get-PowerIPCIDR @cidparam return } } if ($Target){ if ($Target.count -eq '1' -and $Target -match ','){ $Target = $Target.Split(',') } } if (!($AddressOnly) -and !($CIDcalc) -and !($Mant) -and $Site -ne 'NewSite'){ if ($Throttle){ [int]$thrt = $Throttle } Else{ [int]$thrt = $env:NUMBER_OF_PROCESSORS } $powpng = Get-Content function:\get-pping $spng = new-object System.Management.Automation.Runspaces.SessionStateFunctionEntry -ArgumentList 'get-pping',$powpng $powiss = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault2() $powiss.Commands.Add($spng) $pool = [RunspaceFactory]::CreateRunspacePool(1,($thrt+1),$powiss,$Host) $pool.ApartmentState = 'MTA' $pool.ThreadOptions = 'ReuseThread' $pool.Open() $results = [hashtable]::Synchronized(@{}) $runspaces = New-Object System.Collections.ArrayList $npopt = new-object System.Net.NetworkInformation.PingOptions $npopt.Ttl = '255' if ($TTL){ $npopt.Ttl = $TTL } [int]$buf = '32' if ($buffer){ [int]$buf = $buffer } $pbuffer = [byte[]]::new($buf) $time = '1000' if ($Timeout){ $time = $Timeout } if ($ComputerName){ $cfnd = [System.Collections.ArrayList]::Synchronized((New-Object System.Collections.ArrayList)) if ($ComputerName.count -eq '1' -and $ComputerName -match ','){ $ComputerName = $ComputerName.Split(',') } $OnlineOnly = $true if (!$Stream){ $Cpnms = $ComputerName } } Else{ $Cpnms = $null $cfnd = $null } $NPReply = $null [int]$so = '0' if ($OnlineOnly){ $so = '1' } $pblock = { Param( $time, $NPReply, $ad, $npopt, $pbuffer, $output, $cnt, $results, $cfnd, $Cpnms, $so ) get-pping return } } } Catch { if (!($AddressOnly) -and !($CIDcalc) -and $Site -ne 'NewSite' -and !($Mant)){ $pool.close() $pool.dispose() } if (!($Mant)){ If ($_.Exception.Message -match "PPSites.csv' is denied" -or $_.Exception.Message -match 'Access to the path is denied'){ Throw Write-Output '###Error: Access Denied. Must run PowerShell as Admin to modify Sites ###' } Else{ Throw $_.Exception.ErrorRecord } } Else{ Throw Write-Output $Mant } } Finally{ $Sites = $null $siteimp = $null if ($Netmask){ $nl = $null } if ($AddressOnly -or $CIDcalc){ [System.GC]::Collect() } } } Process { Try{ if (!($AddressOnly) -and !($CIDcalc) -and $Site -ne 'NewSite'){ [int]$cnt = 0 if (!($Stream)){ if (!($Target)){ foreach ($ad in (Invoke-Command $aexp)){ $results.Add($cnt,([System.Collections.ArrayList]::new())) get-ppruns $cnt++ } } Else{ foreach ($ad in $Target){ $results.Add($cnt,([System.Collections.ArrayList]::new())) get-ppruns $cnt++ } } while ($runspaces.Status.IsCompleted -contains $false -and !$pool.IsDisposed) { if ($ComputerName -and $cfnd){ if (!(Compare-Object ($cfnd.DeviceName) -DifferenceObject $ComputerName)){ $pool.Close() $pool.Dispose() } } if (!$pool.IsDisposed){ $runspaces.Where({$_.Status.IsCompleted -eq $true}) | ForEach-Object{ $_.Pipe.EndInvoke($_.Status) $_.Pipe.Dispose() $_.Pipe = $null $_.Status = $null $_ = $null } } Start-Sleep -Milliseconds 10 } } Elseif($Stream){ [int]$si = 0 [int]$sj = ($thrt) -1 [int]$sji = $thrt $pcnt = [System.Collections.ArrayList]::new() if (!($Target)){ foreach ($ad in (Invoke-Command $aexp)){ $results.Add($cnt,([System.Collections.ArrayList]::Synchronized((New-Object System.Collections.ArrayList)))) get-ppruns $cnt++ } } Else{ foreach ($ad in $Target){ $results.Add($cnt,([System.Collections.ArrayList]::Synchronized((New-Object System.Collections.ArrayList)))) get-ppruns $cnt++ } } while ($runspaces.Status.IsCompleted -contains $false -and !$pool.IsDisposed) { $pcmp = '' $srg = $si..$sj $srg | ForEach-Object { if ($results.$_.count -ne '1'){ $pcmp = '1' } } if ($pcmp.Length -eq '0'){ if (!$ComputerName){ $srg | ForEach-Object {$results.$_} $si = $sj + 1 $sj = $sj + $sji $null = $pcnt.Add('1') } Else{ $srg | ForEach-Object {if ($ComputerName -contains $results.$_.DeviceName){$null = $cfnd.Add($results.$_); if (!(Compare-Object ($cfnd.DeviceName) -DifferenceObject $ComputerName)){$pool.close();$cfnd;$pool.dispose()}}} $si = $sj + 1 $sj = $sj + $sji $null = $pcnt.Add('1') } } if (!$pool.IsDisposed){ $runspaces.Where({$_.Status.IsCompleted -eq $true}) | ForEach-Object{ $_.Pipe.EndInvoke($_.Status) $_.Pipe.Dispose() $_.Pipe = $null $_.Status = $null $_ = $null } } Start-Sleep -Milliseconds 10 } if ($thrt -lt $results.Count -and !$pool.IsDisposed){ [int]$sed = $results.Count -1 [int]$sdl = $pcnt.Count * $sji $srg = $sdl..($sed) if ($sdl -lt $sed){ if (!$ComputerName){ $srg | ForEach-Object {$results.$_} } Else{ $srg | ForEach-Object {if ($ComputerName -contains $results.$_.DeviceName){$null = $cfnd.Add($results.$_); if (!(Compare-Object ($cfnd.DeviceName) -DifferenceObject $ComputerName)){$pool.close();$cfnd;$pool.dispose()}}} } } } $pcnt = $null if (!$pool.IsDisposed){ if ($ComputerName){ if ($cfnd.count -gt 0){ $cfnd } Else{ Write-Output 'No Devices found matching ComputerName(s)' } } } } } } Catch{ $results = $null if (!($Mant)){ Throw $_.Exception.ErrorRecord } } Finally{ if (!($AddressOnly) -and !($CIDcalc) -and $Site -ne 'NewSite' -and !($Mant)){ $runspaces = $null if (!$pool.IsDisposed){ $pool.Close() $pool.Dispose() } if ($Stream){ $results = $null } } [System.GC]::Collect() } } end { Try{ If (!($Stream) -and !($AddressOnly) -and !($CIDcalc) -and $Site -ne 'NewSite'){ if (!($ComputerName)){ $rng = 0..($results.count -1) $rng | ForEach-Object {$results.$_} } Else{ if ($cfnd.count -gt 0){ $cfnd } Else{ Write-Output 'No Devices found matching ComputerName(s)' } $cfnd = $null; $Cpnms = $null } } } Catch{ Throw $_.Exception.ErrorRecord } Finally{ $results = $null; $aexp = $null; $npopt = $null; $NPReply = $null; $ad = $null; $time = $null; $pblock = $null;$pool = $null;$pbuffer = $null; if ($Target){ $Target.Clear() } if ($ComputerName){ $ComputerName.Clear() } if ($CIDR){ $CIDR.Clear() } [System.GC]::Collect() } } } |