Test-PowerPing.psm1
class PowerPingResult { [string]$Status [string]$IPv4Address [string]$DeviceName [string]$Time PowerPingResult( [PSCustomObject]$response ){ $this.Status = $response.Status $this.IPv4Address = $response.ipv4address $this.DeviceName = $response.DeviceName $this.Time = $response.Time } } ##Netmask table for param validation and CIDR/Netmask functionality. $script:csnl = @{ '0' = '0.0.0.0' '1' = '128.0.0.0' '2' = '192.0.0.0' '3' = '224.0.0.0' '4' = '240.0.0.0' '5' = '248.0.0.0' '6' = '252.0.0.0' '7' = '254.0.0.0' '8' = '255.0.0.0' '9' = '255.128.0.0' '10' = '255.192.0.0' '11' = '255.224.0.0' '12' = '255.240.0.0' '13' = '255.248.0.0' '14' = '255.252.0.0' '15' = '255.254.0.0' '16' = '255.255.0.0' '17' = '255.255.128.0' '18' = '255.255.192.0' '19' = '255.255.224.0' '20' = '255.255.240.0' '21' = '255.255.248.0' '22' = '255.255.252.0' '23' = '255.255.254.0' '24' = '255.255.255.0' '25' = '255.255.255.128' '26' = '255.255.255.192' '27' = '255.255.255.224' '28' = '255.255.255.240' '29' = '255.255.255.248' '30' = '255.255.255.252' '31' = '255.255.255.254' '32' = '255.255.255.255' } <# .SYNOPSIS Sends single pings (ICMP) asynchronously to devices to determine network accessibility. Returns simple ping results (Status,IPv4Address,DeviceName,Time) with status codes. Additional features: Address list generation, CIDR calculator, Range to CIDR conversion. .DESCRIPTION Test-PowerPing pings (ICMP) IPv4 addresses asynchronously within a given IPv4 address range. 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. 'ToCidr' switch can be used to convert range to CIDR or split CIDR entry into sub-blocks. 'IPFilter' parameter can be used to filter IPv4 address lists as needed. 'Sites' parameter set can be used to save collections of ranges and targets. '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. ** See Examples for Use / Syntax ** Defaults: Output: Status,IPv4Address,DeviceName,Time (Online & Offline) Timeout: 1000 ms TTL: 255 Buffer: 32bytes IPFilter: None DYNAMIC PARAMETERS -Site <String[]> Name of saved site list. Requires valid entry from Site List. -Each site can contain multiple entry types. -Use "NewSite" to enable add/remove/import/delete/list functionality [Command Example: Test-PowerPing -Site NewSite -ImportSite $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. -CIDR format supported for range, use 'AssignOnly' switch for assignable addresses. -'CIDcalc','ToCidr' & 'AddressOnly' switches available for CIDR input [Command Example: Test-PowerPing -Target 'website.com,www.anothersite.com,10.0.0.223'] [Command Example: Test-Powerping '192.168.20.0/24' -CIDcalc] Parameter Set(s): Targets .PARAMETER CIDR Address block entry using CIDR notation -Allows for targeting filtering when providing multiple entries --- '\AO' can be provided as filter entry to indicate 'AssignOnly' -Quotes required when providing filter entry -Filters must be separated by ';' following '\F:' -Targeted Filter will override default IPFilter/AssignOnly options [Command Example: Test-PowerPing -CIDR '10.0.0.18/24'] [Command Example: Test-PowerPing -CIDR '10.0.0.18/24,10.0.1.0/24\F:10.0.1.0;10.0.1.1'] Parameter Set(s): CIDR .PARAMETER Netmask Netmask for given StartIP [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. [Command Example: Test-PowerPing -StartIP '10.0.0.0' -EndIP '10.255.255.255' -AddressOnly] Parameter Set(s): Address,Mask,CIDR,Target,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,Target,Sites .PARAMETER ToCidr Converts provided Start/EndIP to CIDR -Entry must be value 0 - 31 -Enter 0 for minimum CIDR block(s) value for provided IP Range -Enter 1 - 31 to split provided range into blocks of provided factor -Can provide CIDR block or Start/End IP as input [Command Example: Test-PowerPing -StartIP '192.168.20.0' -EndIP '192.168.25.255' -ToCidr 24] Parameter Set(s): CIDR,Address,Target,Sites .PARAMETER FullCIDR Provides full CIDR conversion list when splitting CIDR blocks - used with 'ToCidr' -if Switch is not used, only blocks matching the factor provided in 'ToCidr' will be returned -Used specifically with Start/End IP [Command Example: Test-PowerPing -StartIP '192.168.20.1' -EndIP '192.168.20.255' -ToCidr 26 -FullCIDR] Parameter Set(s): CIDR,Address,Target,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 DevName Filters output to entries where DeviceName matches (partial or full) provided input. -Uses '-match' for pattern recognition. (All devices with name starting with 'Mycomputer' below) -Enables OnlineOnly parameter when used [Command Example: Test-PowerPing -Site TheBeach -DevName Mycomputer] Parameter Set(s): Address,Mask,CIDR,Sites .PARAMETER IPFilter Filters/removes IPv4 address list entries where addresses match the provided input. -Entries must match '*.*.*.*' pattern -Full addresses/wildcards can be provided to filter specific IPs ('192.168.50.1','192.168.51.*') -Range/CIDR can save filters using '\F:<filter>;<filter>' at the end of entry. [Command Example: Test-PowerPing -CIDR 10.0.0.0/14 -AddressOnly -iPFilter '*.*.*.0','10.1.1.2'] [Command Example: Test-PowerPing -CIDR '10.0.0.0/14\F:*.*.*.0;10.1.1.2' -AddressOnly] 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,ImportSite,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 RangeList List of ranges or single range for addition to Site List. Used with 'AddSite' Parameter. May require admin. -Each site entry can contain multiple entry types. Entries will be created in the order provided. -Type-Range- Provide Start/EndIP seperated by ';' (filter optional) - Ex: '10.0.0.0;10.2.255.255' -Type-CIDR- Provide CIDR entry (filter optional) - Ex: '10.0.0.0/16' -Type-Target- Provide single ipaddress, device name, or site address - Ex: 'google.com' -Excluded characters: <>^`{|} [Command Example: Test-PowerPing -Site NewSite -AddSite 'Site' -Rangelist '10.0.0.0/16,10.1.0.0;10.1.255.255'] Parameter Set(s): Sites .PARAMETER RemoveSite Site Name for removal from Site List. May require admin permissions. -Can only use one method [AddSite,RemoveSite,ImportSite,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,ImportSite,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,ImportSite,ListSites,DeleteSites] per call [Command Example: Test-PowerPing -Site NewSite -DeleteSites] Parameter Set(s): Sites .PARAMETER ImportSite Specifies PSObject or Hashtable to be used to import new entries to Sites list. May require admin. -Can only use one method [AddSite,RemoveSite,ImportSite,ListSites,DeleteSites] per call [Command Example: Test-PowerPing -Site NewSite -ImportSite $mysitelist] Parameter Set(s): Sites .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 -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, and an IPFilter. Sends Pings with the provided values for 'Timeout','TTL', and 'Buffer' Returns Ping result for successful/unsuccessful addresses that do not equal "192.168.20.3" .EXAMPLE . Saving Sites - Acceptable Formats: -Range- StartIP;EndIP\F:IPFilter;IPFilter = 192.168.0.0;192.168.0.255\F:192.168.0.0;192.168.0.255 -CIDR- CIDRBLock\F:IPFilter;IPFilter = 192.168.0.0/24\F:\AO ---- '\AO' can be provided as entry on CIDR filter to indicate 'AssignOnly' -Target- Website,Devicename,Single IP = google.com -or- MyComputer1 -or- 192.168.0.1 +Multiple formats with individual filters can be used for a single site entry Example: Test-PowerPing -Site NewSite -AddSite 'MyNewSite2' -RangeList '192.168.0.0/25,microsoft.com,192.168.0.128;192.168.0.255' PS C:\> Test-PowerPing -Site NewSite -ListSites Name Value ---- ----- MyNewSite 10.0.0.0/24,10.0.1.0/24,10.0.3.0;10.0.3.255 MyNewSite2 192.168.0.0/25,microsoft.com,192.168.0.128;192.168.0.255 NewSite "0.0.0.0";"0.0.0.0" ____________________________________________________________________ Adds new site 'MyNewSite2' to Site List with range 192.168.0.0 - 192.168.0.255 and site 'microsoft.com'. **Note Adding/Removing Sites may require admin permissions depending on module install location** .EXAMPLE Test-PowerPing -Site NewSite -Import $mylist Example List (Hashtable): $mylist = @{} $mylist.add("MyNewSite",'10.0.0.0/24,10.0.1.0/24,10.0.2.0;10.0.3.255') $mylist Name Value ---- ----- MyNewSite 10.0.0.0/24,10.0.1.0/24,10.0.2.0;10.0.3.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.3.255" to Site List using import. **Note Adding/Removing Sites may require admin permissions depending on module install location** .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 . PS C:\> 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 . Targeted filtering using CIDR: test-powerping -CIDR '10.0.0.0/11\F:10.0.2.1;10.0.2.20;10.3.*.*,10.32.0.0/11,10.64.0.0/10,10.128.0.0/9' -AddressOnly TotalSeconds : 64.4129227 Standard filtering: test-powerping -StartIP 10.0.0.0 -EndIP 10.255.255.255 -AddressOnly -IPFilter '10.0.2.1,10.0.2.20,10.3.*.*' TotalSeconds : 212.7417819 ____________________________________________________________________ Both commands return a string list containing addressess from 10.0.0.0 to 10.255.255.255, with 2 addresses and all addresses matching '10.3.*.*' filtered. + The top example uses targeted filtering and CIDR block notation to apply filters to the first entry only. --The rest of the list is generated/added without filtering. + The bottom example uses standard filtering with a start/end ip address and applies filters to the entire set. --Applying filters to large address ranges will significantly increase generation time. ** Use targeted filtering when attempting to filter larger ranges ** .EXAMPLE . Test-Powerping -StartIP '192.168.12.0' -EndIP '192.168.12.255' -ToCidr 0 192.168.12.0/24 Test-Powerping '192.168.12.0/24' -ToCidr 26 192.168.12.0/26 192.168.12.64/26 192.168.12.128/26 192.168.12.192/26 Test-Powerping -StartIP '192.168.12.1' -EndIP '192.168.12.255' -ToCidr 26 -FullCIDR 192.168.12.1/32 192.168.12.2/31 192.168.12.4/30 192.168.12.8/29 192.168.12.16/28 192.168.12.32/27 192.168.12.64/26 192.168.12.128/26 192.168.12.192/26 ____________________________________________________________________ Top command converts provided range to CIDR - providing '0' for ToCidr parameter will convert range to CIDR without splitting Second command splits provided CIDR block into subnet blocks matching /26 - providing '1 to 31' for ToCidr parameter will attempt to split provided range/CIDR into subnet blocks - can attempt split on CIDR or Start/End range Third command converts provided range to CIDR and splits into subnet blocks matching /26 - FullCIDR switch used to show complete CIDR conversion for provided Range - used with Start/EndIP Only - omitting FullCIDR switch will only return entries where block matches provided factor /26 .EXAMPLE . Using Pipeline $mytargetlist | test-powerping $mycidrlist | test-powerping -CIDcalc $mycidrlist | test-powerping -ToCidr 24 | test-powerping -CIDcalc | select-object -property BaseIP,BroadcastIP ____________________________________________________________________ All commands provide input via pipeline for actions described below + Top example will send pings to targets provided in variable '$mytargetlist' -- 'Targets' parameter set available for ping/output options. CIDR block format supported for target range. -- Filtering is not supported via pipeline / Targets parameter set --- Use standard parameter sets to use filters, or save filtered list as site / assign to variable + Middle example will provide CIDR calculator information for blocks provided in variable '$mycidrlist' + Bottom example attempts to convert CIDR list to block size /24 and return Base/BroadcastIP for new blocks. ** Available switches for CIDR input: -AdressOnly (-AssignOnly optional), -CIDCalc, -ToCIDR <value> .NOTES Running Large Range Scans or Address Lists May Increase/Max Resource Utilization - Using multiple filters or large match patterns (10.7.*.*) increases address generation time. -- Use CIDR parameter with targeted filtering to avoid large filters/large filter sets --- Targeted Filter will override default IPFilter/AssignOnly options -- See Examples for direction/syntax '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.3.1.0 --------------- Date: 7/28/2024 --------------- Author: Hunter Hirsch .LINK https://www.powershellgallery.com/packages/Test-PowerPing .LINK https://learn.microsoft.com/en-us/dotnet/api/system.net.networkinformation.ipstatus?view=netframework-4.5 .LINK https://learn.microsoft.com/en-us/windows/win32/winsock/windows-sockets-error-codes-2?redirectedfrom=MSDN #> function Test-PowerPing { [CmdletBinding(DefaultParameterSetName='Targets')] [OutputType([System.Collections.ArrayList],[PowerPingResult])] ##If/Else ValidateScript method used to allow for custom error messaging. Param( [Parameter(Mandatory,ParameterSetName='Address',HelpMessage='Enter Valid IPv4 Address (Ex: "10.0.0.0")')] [Parameter(Mandatory,ParameterSetName='Mask',HelpMessage='Enter Valid IPv4 Address (Ex: "10.0.0.0")')] [ValidateScript({ 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}$'){ $true } Else{ Throw Write-Output 'Cannot be null. Must be valid IP Address. Ex: "192.168.32.52"' } })] [ValidateLength(7,15)] [string] $StartIP, [Parameter(Mandatory,ParameterSetName="Address",HelpMessage='Enter Valid IPv4 Address (Ex: "10.0.0.0")')] [ValidateScript({ 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}$'){ $true } Else{ Throw Write-Output 'Cannot be null. Must be valid IP Address. Ex: "192.168.32.52"' } })] [ValidateLength(7,15)] [string] $EndIP, [Parameter(ParameterSetName='Targets')] [Parameter(ParameterSetName='Address')] [Parameter(ParameterSetName='Sites')] [Parameter(ParameterSetName='CIDR')] [ValidateScript({ if (([uint32]$_ -lt 32 -and [uint32]$_ -ge 0) -and !$AddressOnly -and !$CIDcalc){ $true } Else{ Throw Write-Output 'Entry must be digit 0-31. Enter "0" for minimum block list. Cannot be used with "AddressOnly" or "CIDCalc" Parameters.' } })] [string] $ToCidr, [Parameter(Mandatory,ParameterSetName="Mask",HelpMessage='Enter Valid Netmask (Ex: "255.255.255.0")')] [ValidateScript({ if ($_ -in ($csnl.Values)){ $true } Else{ Throw Write-Output 'Cannot be null. Must be valid Netmask. Example: 255.0.0.0' } })] [ValidateLength(9,15)] [string] $Netmask, [Parameter(Mandatory,ParameterSetName='CIDR',HelpMessage='Enter Valid CIDR Range (Ex: "10.0.0.0/24")')] [ValidateScript({ $z = $_.split(',') if ($z -match '\\F:'){ $z = $z -replace 'f:','F:' $z = ($z -split '\\F:')[0] } $z | 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-9]|[1-2][0-9]|3[0-2]))$'){ $true } Else{ Throw Write-Output 'Cannot be null. Entries must be separated by commas. Ex:"10.0.0.0/8","11.0.0.0/12". Filter should follow entry directly "10.0.0.0/8\F:10.0.0.255;*.2.*.*"' } } })] [string[]] $CIDR, [Parameter(ParameterSetName='Targets')] [Parameter(ParameterSetName='Sites')] [Parameter(ParameterSetName='CIDR')] [Parameter(ParameterSetName='Mask')] [ValidateScript({ if (!$AssignOnly -and !$ToCidr){ $true } Else{ Throw Write-Output 'Cannot be used with "AssignOnly" or "ToCidr" Parameters.' } })] [switch] $CIDcalc, [Parameter(ParameterSetName='Targets')] [Parameter(ParameterSetName='CIDR')] [Parameter(ParameterSetName='Mask')] [Parameter(ParameterSetName='Sites')] [ValidateScript({ if (!$CIDcalc -and !$ToCidr){ $true } Else{ Throw Write-Output 'Cannot be used with "CIDcalc" or "ToCidr" Parameters.' } })] [switch] $AssignOnly, [Parameter(ParameterSetName='Sites')] [ValidateScript({ if(!($RemoveSite) -and !($DeleteSites) -and !($ListSites) -and !($importsite) -and $_ -ne $null){ $true } Else{ Throw Write-Output 'Cannot be null. Cannot be used with RemoveSite,DeleteSites,ListSites,ImportSite Parameters.' } })] [string] $AddSite, [Parameter(ParameterSetName='Sites')] [ValidateScript({ if (!($AddSite) -and !($DeleteSites) -and !($ListSites) -and !($importsite) -and $_ -ne $null){ $true } Else{ Throw Write-Output 'Cannot be null. Cannot be used with AddSite,DeleteSites,ListSites,ImportSite Parameters.' } })] [string] $RemoveSite, [Parameter(ParameterSetName='Sites')] [ValidateScript({ if (!($RemoveSite) -and !($AddSite) -and !($ListSites) -and !($importsite)){ $true } Else{ Throw Write-Output 'Cannot be used with AddSite,RemoveSite,ListSites,ImportSite Parameters.' } })] [switch] $DeleteSites, [Parameter(ParameterSetName='Sites')] [ValidateScript({ if (!($RemoveSite) -and !($AddSite) -and !($DeleteSites) -and !($importsite)){ $true } Else{ Throw Write-Output 'Cannot be used with AddSite,RemoveSite,DeleteSites,ImportSite Parameters.' } })] [switch] $ListSites, [Parameter(ParameterSetName='Sites')] [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] $ImportSite, [Parameter(ParameterSetName='Sites')] [ValidateScript({ if (!($DeleteSites) -and !($RemoveSite) -and !($ListSites) -and !($importsite) -and $_ -ne $null){ if ($_.count -gt '1'){ $length = ($_ -join ',').Length $r = $_ -join ',' if ($length -le 30000 -and $r -notmatch '[<>^`{|}]'){ $true } } Else{ $length = $_.length if ($length -le 30000 -and $_ -notmatch '[<>^`{|}]'){ $true } } } Else{ Throw Write-Output 'Can only be used with "-Site NewSite -AddSite" Parameters. Cannot be null. Length must be less than "30000" (~500 entries). Type "Get-Help Test-PowerPing -Parameter RangeList" for further information and formatting.' } })] [String[]] $RangeList, [Parameter(Mandatory,ValueFromPipeline,ParameterSetName='Targets',Position=0,HelpMessage='Enter Device Name, Web Address, or IPv4 address.')] [ValidateScript({ if ($_ | foreach-object {$_ -ne $null -and $_ -notmatch '["<>^`{|}]'}){ $true } Else{ Throw Write-Output 'Cannot be null. Excluded characters: "<>^`{|}' } })] [string[]] $Target, [Parameter(ParameterSetName='Sites')] [Parameter(ParameterSetName='Address')] [Parameter(ParameterSetName='CIDR')] [Parameter(ParameterSetName='Mask')] [Parameter(ParameterSetName='Targets')] [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[]] $DevName, [Parameter(ParameterSetName='Targets')] [Parameter(ParameterSetName='Sites')] [Parameter(ParameterSetName='Address')] [Parameter(ParameterSetName='CIDR')] [Parameter(ParameterSetName='Mask')] [switch] $AddressOnly, [Parameter(ParameterSetName='Targets')] [Parameter(ParameterSetName='Address')] [Parameter(ParameterSetName='Sites')] [Parameter(ParameterSetName='CIDR')] [switch] $FullCIDR, [Parameter(ParameterSetName='Sites')] [Parameter(ParameterSetName='Address')] [Parameter(ParameterSetName='CIDR')] [Parameter(ParameterSetName='Mask')] [ValidateScript({ $f = $_.Split(',') $f | foreach-object {if ($_ -like '*.*.*.*' -and $_.length -le '15' -and ($_ -replace '(\d)','' -replace '\.','' -replace '\*','').Length -eq '0'){ $true } Else{ Throw Write-Ouput 'Can only filter: IP Addresses (ex:"10.2.3.200") IP Address Patterns (ex:"10.2.*.*"). Entries must be separated by commas ",". Entries must have "*.*.*.*" format' } } })] [string[]] $iPFilter, [Parameter(ParameterSetName='Sites')] [Parameter(ParameterSetName='Address')] [Parameter(ParameterSetName='Targets')] [Parameter(ParameterSetName='CIDR')] [Parameter(ParameterSetName='Mask')] [ValidateScript({[int]$_ -le '255'})] [int] $TTL, [Parameter(ParameterSetName='Sites')] [Parameter(ParameterSetName='Address')] [Parameter(ParameterSetName='Targets')] [Parameter(ParameterSetName='CIDR')] [Parameter(ParameterSetName='Mask')] [ValidateScript({[int]$_ -le '60000'})] [int] $Timeout, [Parameter(ParameterSetName='Sites')] [Parameter(ParameterSetName='Address')] [Parameter(ParameterSetName='Targets')] [Parameter(ParameterSetName='CIDR')] [Parameter(ParameterSetName='Mask')] [ValidateScript({[int]$_ -le '65500'})] [int] $Buffer, [Parameter(ParameterSetName='Sites')] [Parameter(ParameterSetName='Address')] [Parameter(ParameterSetName='Targets')] [Parameter(ParameterSetName='CIDR')] [Parameter(ParameterSetName='Mask')] [switch] $OnlineOnly, [Parameter(ParameterSetName='Sites')] [Parameter(ParameterSetName='Address')] [Parameter(ParameterSetName='Targets')] [Parameter(ParameterSetName='CIDR')] [Parameter(ParameterSetName='Mask')] [ValidateSet('NoTime','NoDeviceName','NoTime/DeviceName')] [string] $Output ) ##Site Dynamic param setup, pulls site names from PPSites.csv (if created) and adds to ValidateSet attribute. 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' $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{ $adrl = New-Object System.Collections.ArrayList if ($Site){ if ($ListSites -or $AddSite -or $RemoveSite -or $DeleteSites -or $importsite -or $RangeList -and $Site -ne 'NewSite'){ $Mant = 'Error: (-Site NewSite) Required to Modify Site List' Throw } $script:sitep = (get-module -name Test-PowerPing | Select-Object -ExpandProperty ModuleBase) + '\PPSites.csv' if (Test-Path -Path $sitep -PathType Leaf){ if (!$DeleteSites -and !$RemoveSite){ if ((Get-ItemProperty -Path $sitep -Name Length -ErrorAction Ignore | Select-Object -ExpandProperty Length) -gt 1000000){ $Mant = 'Error: Sites List exceeds max size: 1000000 (~1mb). Remove entries / Delete List to continue using Site List' Throw } } $siteimp = Import-Csv $sitep $script:Sites = @{} $siteimp | ForEach-Object {$Sites.add($_.name,$_.value)} } Else{ $script:Sites = @{'NewSite' = '"0.0.0.0";"0.0.0.0"'} } ## Saved Site Management (Add,Remove,Import,Delete,List) if ($site -eq 'NewSite'){ if (!($AddSite) -and !($RemoveSite) -and !($DeleteSites) -and !($ListSites) -and !($ImportSite)){ $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 ($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 } if ($AddSite -or $RemoveSite -or $ImportSite){ $siteparam = @{} if ($AddSite){ if (!$RangeList){ Throw Write-Output "Must Provide RangeList for AddSite Entry" } $siteparam.Add('Add',$AddSite) $siteparam.Add('OList',$RangeList) } Elseif ($RemoveSite){ $siteparam.Add('Remove',$RemoveSite) } Elseif ($ImportSite){ $siteparam.Add('Import',$ImportSite) } if ($siteparam.Count -gt 0){ Get-PowerIPSite @siteparam } return } } ## Sorting sites by type (Range,CIDR,or Target) for selected site and preparing to process Else{ $siterange = $Sites[$site] -split ',' foreach ($entry in $siterange){ if ($entry -match '\\F:'){ $entry = $entry -replace 'f:','F:' $combo = $entry -split '\\F:' | Where-Object {$_ -ne ''} $nsite = $combo[0] -replace '"','' $nfilter = $combo[1].Split(';') | Where-Object {$_ -ne ''} } Else{ $nsite = $entry } if ($nsite -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}$'){ $rngparam = @{ Start = $nsite.split(';')[0] End = $nsite.split(';')[1] } if ($nfilter){ $rngparam.Add('Filter',$nfilter) } if ($AddressOnly){ Get-PowerIPRange @rngparam } Elseif ($ToCidr){ $tocidrparam = @{ Begin = $rngparam.Start Finish = $rngparam.End Factor = $ToCidr } if ($FullCIDR){ $tocidrparam.Add('full',$true) } Get-PowerIP2CIDR @tocidrparam } Elseif (!$CIDcalc){ $null = $adrl.AddRange((Get-PowerIPRange @rngparam)) } } Elseif ($nsite -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-9]|[1-2][0-9]|3[0-2]))$'){ $cidparam = @{ Range = $nsite } if (!$CIDcalc){ if ($nfilter -contains '\AO' -or $AssignOnly){ $cidparam.Add('AssignO',$true) if ($nfilter){ $nfilter = $nfilter.Where({$_ -ne '\AO'}) } } if ($nfilter.count -gt 0){ $cidparam.Add('Filter',$nfilter) } } Else{ $cidparam.Add('Calculator',$true) } if ($AddressOnly -or $CIDcalc){ Get-PowerIPCIDR @cidparam } Elseif($ToCidr){ if ([uint32](($cidparam.Range).split('/')[1]) -le [uint32]$ToCidr){ $startend = Get-PowerIPCIDR -Range ($cidparam.Range) -Calculator | Select-Object -Property BaseIP,BroadcastIP $tocidrparam = @{ Begin = $startend.BaseIP Finish = $startend.BroadcastIP Factor = $ToCidr } Get-PowerIP2CIDR @tocidrparam } Else{ Throw 'Error: ToCidr factor cannot be greater than provided CIDR Range' } } Else{ $null = $adrl.AddRange((Get-PowerIPCIDR @cidparam)) } } Elseif ($nsite -notmatch '[<>^`{|}]'){ if ($AddressOnly){ $nsite } Elseif (!$CIDcalc -and !$ToCidr){ $null = $adrl.Add($nsite) } } } } } if ($iPFilter){ $iPFilter = $iPFilter.Split(',') } #Range processing/prep for pings or list generation 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 ($AddressOnly){ Get-PowerIPRange @rngparam return } Elseif ($ToCidr){ $tocidrparam = @{ Begin = $rngparam.Start Finish = $rngparam.End Factor = $ToCidr } if ($FullCIDR){ $tocidrparam.Add('full',$true) } Get-PowerIP2CIDR @tocidrparam return } Else{ $null = $adrl.AddRange((Get-PowerIPRange @rngparam)) } } } ## Netmask processing/prep for ping / address list generation / CIDR caclulator if ($Netmask){ $CIDR = $StartIP + '/' + ($csnl.keys | Where-Object {$csnl[$_] -eq $Netmask}) } ## CIDR processing/prep for ping / address list generation / CIDR calculator if ($CIDR){ $CIDR = [string[]]$CIDR.Split(',') $CIDR | ForEach-Object { $cidparam = @{ Range = $_ } if ($_ -match '\\F:'){ $_ = $_ -replace 'f:','F:' $cidfiltered = $_ -split '\\F:' | Where-Object {$_ -ne ''} $cblock = $cidfiltered[0] -replace '"','' $cfilter = $cidfiltered[1].Split(';') | Where-Object {$_ -ne ''} $cidparam.'Range' = $cblock } if (!$CIDcalc){ if ($AssignOnly -or $cfilter){ if ($cfilter -contains '\AO'){ $cidparam.Add('AssignO',$true) $cfilter = $cfilter.Where({$_ -ne '\AO'}) } Elseif (!$cfilter){ $cidparam.Add('AssignO',$true) } } if ($iPFilter -or $cfilter){ if (!$cfilter){ $cidparam.Add('Filter',$iPFilter) } Else{ $cidparam.Add('Filter',$cfilter) } } if ($AddressOnly){ Get-PowerIPCIDR @cidparam $cfilter = $null $cblock = $null $cidparam = $null return } Elseif ($ToCidr){ if ([uint32](($cidparam.Range).split('/')[1]) -le [uint32]$ToCidr){ $startend = Get-PowerIPCIDR -Range ($cidparam.Range) -Calculator | Select-Object -Property BaseIP,BroadcastIP $tocidrparam = @{ Begin = $startend.BaseIP Finish = $startend.BroadcastIP Factor = $ToCidr } Get-PowerIP2CIDR @tocidrparam $cfilter = $null $cblock = $null $cidparam = $null $startend = $null $tocidrparam = $null return } Else{ Throw 'Error: ToCidr factor cannot be greater than provided CIDR Range' } } Else{ $null = $adrl.AddRange((Get-PowerIPCIDR @cidparam)) } } Else{ $cidparam.Add('Calculator',$true) Get-PowerIPCIDR @cidparam $cfilter = $null $cblock = $null $cidparam = $null return } $cfilter = $null $cblock = $null $cidparam = $null } } ## Function to process Target variable/pipeline input function Get-ppingtargets { if ($Target.count -eq '1' -and $Target -match ','){ $Target = $Target.Split(',') } $Target | 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-9]|[1-2][0-9]|3[0-2]))$'){ $cidparam = @{ Range = $_ } if (!$CIDcalc -and !$ToCidr){ if ($AssignOnly){ $cidparam.Add('AssignO',$true) } if (!$AddressOnly){ $null = $adrl.AddRange((Get-PowerIPCIDR @cidparam)) } Else{ Get-PowerIPCIDR @cidparam $cidparam = $null return } } Elseif ($ToCidr){ if ([uint32](($cidparam.Range).split('/')[1]) -le [uint32]$ToCidr){ $startend = Get-PowerIPCIDR -Range ($cidparam.Range) -Calculator | Select-Object -Property BaseIP,BroadcastIP $tocidrparam = @{ Begin = $startend.BaseIP Finish = $startend.BroadcastIP Factor = $ToCidr } Get-PowerIP2CIDR @tocidrparam $tocidrparam = $null $cidparam = $null return } Else{ Throw 'Error: ToCidr factor cannot be greater than provided CIDR Range' } } Else{ $cidparam.Add('Calculator',$true) Get-PowerIPCIDR @cidparam $cidparam = $null return } $cidparam = $null } Else{ $null = $adrl.Add($_) } } } if ($Target){ Get-ppingtargets } ## List to collect pipeline input $ppinputlist = New-Object System.Collections.ArrayList ## Ping processing setup (pque = queue for ping, dque = queue for dns lookup for device name) if (!($AddressOnly) -and !($CIDcalc) -and !($ToCidr) -and $Site -ne 'NewSite' -and !($Mant)){ $pque = New-Object System.Collections.Queue $dque = New-Object System.Collections.Queue $results = @{} $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 ($DevName){ $cfnd = New-Object System.Collections.ArrayList if ($DevName.count -eq '1' -and $DevName -match ','){ $DevName = $DevName.Split(',') } $OnlineOnly = $true } [int]$so = '0' if ($OnlineOnly){ $so = '1' } ##Function below to process pings## ##Thanks to Andrew Pearce for sharing Queue logic in "FastPing" (https://www.powershellgallery.com/packages/FastPing). Logic is modified, but this was my first introduction to Queue objects - much appreciated!## function get-ppprocessing { [int]$cnt = 0 while ($adrl.count -gt 0){ if ($adrl.count -gt 256){ for ($i = 0 ; $i -lt 256; $i++){ $null = $results.Add($cnt,[System.Collections.ArrayList]::new()) $ping = new-object System.Net.NetworkInformation.Ping $newping = @{ Queue = $cnt Host = $adrl[$i] Ping = $ping Reply = $ping.SendPingAsync($adrl[$i],$time,$pbuffer,$npopt) } $pque.Enqueue($newping) $cnt++ } for ($j = 0 ; $j -lt 256; $j++){ $adrl.RemoveAt(0) } } Else{ foreach ($ad in $adrl){ $null = $results.Add($cnt,[System.Collections.ArrayList]::new()) $ping = new-object System.Net.NetworkInformation.Ping $newping = @{ Queue = $cnt Host = $ad Ping = $ping Reply = $ping.SendPingAsync($ad,$time,$pbuffer,$npopt) } $pque.Enqueue($newping) $cnt++ } $endad = $true } while ($pque.Count -gt 0){ $newreply = $pque.Dequeue() if ($newreply.reply.IsCompleted -eq $true){ $qcnt = $newreply.queue if ($NewReply.Reply.Result.Status -eq 'Success'){ if ($Output -notmatch 'device'){ if ($newreply.Host -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}$'){ $newdev = @{ Queue = $newreply.Queue Name = [net.dns]::GetHostEntryAsync($newreply.Host) } $dque.Enqueue($newdev) } } $null = $results.$qcnt.add([PSCustomObject]@{ Status ='Online' IPv4Address =if ($newreply.host -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}$'){$newreply.host}Else{$newreply.reply.Result.Address.IPAddressToString} DeviceName = if ($Output -like '*Device*'){''}Else{if ($newreply.host -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}$'){'*N / A*'}Else{$newreply.host}} Time = if ($Output -like '*Time*'){''}Else{$NewReply.reply.Result.RoundtripTime} }) } ELSEif ($so -ne '1' -and $NewReply.Reply.Status.value__ -eq '5'){ $null = $results.$qcnt.add([PSCustomObject]@{ Status =$NewReply.reply.Result.Status IPv4Address =if ($NewReply.reply.Result.Address.IPAddressToString -eq '0.0.0.0'){$newreply.host + ": " + $NewReply.reply.Result.Status.value__}Else{$newreply.host + ": " + $NewReply.reply.Result.Status.value__ + ":" + $NewReply.reply.result.Address.IPAddressToString} DeviceName = '' Time = '' }) } ELSEif ($NewReply.Reply.Status.value__ -ne '5'){ $null = $results.$qcnt.add([PSCustomObject]@{ Status ='Error' IPv4Address = $newreply.host +": "+$NewReply.reply.Exception.InnerException.InnerException.ErrorCode+": "+$NewReply.reply.Exception.InnerException.InnerException.Message DeviceName = '' Time = '' }) } } Else{ $pque.Enqueue($newreply) } } while ($dque.Count -gt 0){ $hostname = $dque.Dequeue() if ($hostname.Name.IsCompleted -eq $true){ if (($hostname.Name.result.hostname)){ $dcnt = $hostname.queue $results.$dcnt = [PSCustomObject]@{Status = ($results.$dcnt).Status; IPv4Address = ($results.$dcnt).IPv4Address; DeviceName = $hostname.name.result.hostname; Time = ($results.$dcnt).Time} if ($DevName){ $DevName | ForEach-Object { if ($hostname.Name.Result.HostName -match $_){ $null = $cfnd.Add([PSCustomObject]@{Status = ($results.$dcnt).Status; IPv4Address = ($results.$dcnt).IPv4Address; DeviceName = $hostname.name.result.hostname; Time = ($results.$dcnt).Time}) } } } } } Else{ $dque.Enqueue($hostname) } } if ($endad){ $adrl.clear() } } } } } Catch { if (!($AddressOnly) -and !($CIDcalc) -and !($ToCidr) -and $Site -ne 'NewSite' -and !($Mant)){ $pque.Clear() $dque.Clear() $adrl.Clear() $results.Clear() } ##$Mant variable is used to capture custom error messaging for events above. If variable is not present, checks for access denied error and provides message or provides direct error message.## 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 ($AddressOnly -or $CIDcalc -or $ToCidr){ [System.GC]::Collect() } ##Get-PowerIPAddress generation loop uses try/catch for generation. Error entries are expected after successful list generation. Conditional below checks for error entries matching expected loop errors and removes if present.## if (!$CIDcalc -and !$ToCidr -and $Site -ne 'NewSite'){ $global:Error.Clone() | ForEach-Object { if ($_.exception -match 'cannot convert value "256"'){ $global:Error.Remove($_) } } } } } ##Thanks to Andrew Pearce for sharing Queue logic in "FastPing" (https://www.powershellgallery.com/packages/FastPing). Logic is modified, but this was my first introduction to Queue objects - much appreciated!## Process { Try{ ## Pipeline collection ## if ($input){ $null = $ppinputlist.Add($_) } ## Standard input processing if ($adrl.Count -gt 0){ get-ppprocessing } } Catch{ $results = $null if (!($Mant)){ Throw $_.Exception.ErrorRecord } } Finally{ if (!($AddressOnly) -and !($CIDcalc) -and !($ToCidr) -and $Site -ne 'NewSite' -and !($Mant)){ $pque.Clear() $dque.Clear() $adrl.Clear() } } } end { ##Pipeline Processing## Try{ if ($ppinputlist.Count -gt 0){ [string[]]$Target = $ppinputlist | ForEach-Object {"$_"} Get-ppingtargets if ($adrl.Count -gt 0 -and !($AddressOnly) -and !($CIDcalc) -and !($ToCidr)){ get-ppprocessing } } } Catch{ $results = $null if (!($Mant)){ Throw $_.Exception.ErrorRecord } } Finally{ if (!($AddressOnly) -and !($CIDcalc) -and !($ToCidr) -and $Site -ne 'NewSite' -and !($Mant)){ $pque.Clear() $dque.Clear() $adrl.Clear() $ppinputlist = $null } } ##If Devname filter was used, 'cfnd' list is provided, containing any successful pings to devices matching the input provided for Devname. Allows for matching groups of devices with similar naming## Try{ If (!($AddressOnly) -and !($CIDcalc) -and !($ToCidr) -and $Site -ne 'NewSite'){ $rng = 0..($results.count -1) if (!($DevName)){ $rng | ForEach-Object {if ($results.$_){[PowerPingResult]::new($results.$_)}} } Else{ if ($cfnd.count -gt 0){ $cfnd | ForEach-Object {[PowerPingResult]::new($_)} } Else{ Write-Output 'No Devices found matching ComputerName(s)' } $cfnd = $null } } } Catch{ Throw $_.Exception.ErrorRecord } Finally{ $results = $null; $npopt = $null; $ping = $null; $newping = $null; $time = $null; $newdev = $null;$newreply = $null;$pbuffer = $null;$ad = $null; $pque = $null; $dque = $null; $adrl = $null if ($Target){ $Target.Clear() } if ($DevName){ $DevName.Clear() } if ($CIDR){ $CIDR.Clear() } [System.GC]::Collect() } } } |