<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://www.rabbibob.com/index.php?action=history&amp;feed=atom&amp;title=Powershell%3A_Ping_Range</id>
	<title>Powershell: Ping Range - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://www.rabbibob.com/index.php?action=history&amp;feed=atom&amp;title=Powershell%3A_Ping_Range"/>
	<link rel="alternate" type="text/html" href="https://www.rabbibob.com/index.php?title=Powershell:_Ping_Range&amp;action=history"/>
	<updated>2026-08-07T08:07:30Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.39.5</generator>
	<entry>
		<id>https://www.rabbibob.com/index.php?title=Powershell:_Ping_Range&amp;diff=1983&amp;oldid=prev</id>
		<title>Rabbi Bob: Created page with &quot;Category:Powershell Category:Weblog-2026-08  Not an original script. =Usage= &lt;pre&gt; .\Test-IPRange-Threaded.ps1 -startIP &quot;192.168.1.1&quot; -endIP &quot;192.168.1.50&quot; &lt;/pre&gt;  =Script=  &lt;pre&gt; # 10.101.50.70	255.255.0.0 &lt;# .SYNOPSIS     Pings a range of IP addresses concurrently to check their online status.  .DESCRIPTION     This script takes a start IP address and an end IP address. It iterates through     each IP address in the specified range (primarily designed for range...&quot;</title>
		<link rel="alternate" type="text/html" href="https://www.rabbibob.com/index.php?title=Powershell:_Ping_Range&amp;diff=1983&amp;oldid=prev"/>
		<updated>2026-08-06T19:58:00Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;&lt;a href=&quot;/index.php/Category:Powershell&quot; title=&quot;Category:Powershell&quot;&gt;Category:Powershell&lt;/a&gt; &lt;a href=&quot;/index.php?title=Category:Weblog-2026-08&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;Category:Weblog-2026-08 (page does not exist)&quot;&gt;Category:Weblog-2026-08&lt;/a&gt;  Not an original script. =Usage= &amp;lt;pre&amp;gt; .\Test-IPRange-Threaded.ps1 -startIP &amp;quot;192.168.1.1&amp;quot; -endIP &amp;quot;192.168.1.50&amp;quot; &amp;lt;/pre&amp;gt;  =Script=  &amp;lt;pre&amp;gt; # 10.101.50.70	255.255.0.0 &amp;lt;# .SYNOPSIS     Pings a range of IP addresses concurrently to check their online status.  .DESCRIPTION     This script takes a start IP address and an end IP address. It iterates through     each IP address in the specified range (primarily designed for range...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;[[Category:Powershell]]&lt;br /&gt;
[[Category:Weblog-2026-08]]&lt;br /&gt;
&lt;br /&gt;
Not an original script.&lt;br /&gt;
=Usage=&lt;br /&gt;
&amp;lt;pre&amp;gt; .\Test-IPRange-Threaded.ps1 -startIP &amp;quot;192.168.1.1&amp;quot; -endIP &amp;quot;192.168.1.50&amp;quot; &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Script=&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# 10.101.50.70	255.255.0.0&lt;br /&gt;
&amp;lt;#&lt;br /&gt;
.SYNOPSIS&lt;br /&gt;
    Pings a range of IP addresses concurrently to check their online status.&lt;br /&gt;
&lt;br /&gt;
.DESCRIPTION&lt;br /&gt;
    This script takes a start IP address and an end IP address. It iterates through&lt;br /&gt;
    each IP address in the specified range (primarily designed for ranges within&lt;br /&gt;
    the same /24 subnet) and sends two ping requests to each IP concurrently&lt;br /&gt;
    using PowerShell runspaces for improved efficiency.&lt;br /&gt;
&lt;br /&gt;
    - If an address responds to one or more pings, it&amp;#039;s marked as &amp;quot;Online&amp;quot;.&lt;br /&gt;
    - If an address does not respond to either ping, it&amp;#039;s marked as &amp;quot;Offline&amp;quot;.&lt;br /&gt;
    - Errors during a specific IP ping are marked as &amp;quot;Error&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
.PARAMETER startIP&lt;br /&gt;
    The starting IP address of the range (e.g., &amp;quot;192.168.1.1&amp;quot;). This is a mandatory parameter.&lt;br /&gt;
&lt;br /&gt;
.PARAMETER endIP&lt;br /&gt;
    The ending IP address of the range (e.g., &amp;quot;192.168.1.254&amp;quot;). This is a mandatory parameter.&lt;br /&gt;
&lt;br /&gt;
.PARAMETER ThrottleLimit&lt;br /&gt;
    The maximum number of concurrent ping operations. Default is 30.&lt;br /&gt;
    Adjust this based on your system&amp;#039;s resources and network considerations.&lt;br /&gt;
&lt;br /&gt;
.EXAMPLE&lt;br /&gt;
    .\Test-IPRange-Threaded.ps1 -startIP &amp;quot;192.168.1.1&amp;quot; -endIP &amp;quot;192.168.1.50&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    This command will ping IP addresses from 192.168.1.1 to 192.168.1.50 concurrently&lt;br /&gt;
    (using the default throttle limit), sending two pings to each and reporting their status.&lt;br /&gt;
&lt;br /&gt;
.EXAMPLE&lt;br /&gt;
    .\Test-IPRange-Threaded.ps1 -startIP &amp;quot;10.0.0.1&amp;quot; -endIP &amp;quot;10.0.0.254&amp;quot; -ThrottleLimit 50&lt;br /&gt;
&lt;br /&gt;
    This command will ping IPs in the 10.0.0.x range with up to 50 concurrent operations.&lt;br /&gt;
&lt;br /&gt;
.NOTES&lt;br /&gt;
    - This script uses PowerShell Runspace Pools for threading, compatible with PowerShell 5.1+.&lt;br /&gt;
    - For PowerShell 7.0 and newer, ForEach-Object -Parallel offers a simpler syntax for parallel execution.&lt;br /&gt;
    - The script assumes the IP range is primarily within the same /24 subnet. It uses the first&lt;br /&gt;
      three octets of &amp;#039;startIP&amp;#039; as the base network prefix.&lt;br /&gt;
    - If &amp;#039;startIP&amp;#039; and &amp;#039;endIP&amp;#039; have different network prefixes, a warning is displayed, and the scan&lt;br /&gt;
      proceeds using &amp;#039;startIP&amp;#039;s&amp;#039; network prefix.&lt;br /&gt;
    - To run this script:&lt;br /&gt;
        1. Save it as a .ps1 file (e.g., Test-IPRange-Threaded.ps1).&lt;br /&gt;
        2. Open PowerShell.&lt;br /&gt;
        3. Navigate to the directory where you saved the file.&lt;br /&gt;
        4. If needed, adjust your execution policy: Set-ExecutionPolicy RemoteSigned -Scope CurrentUser&lt;br /&gt;
        5. Run: .\Test-IPRange-Threaded.ps1 -startIP &amp;quot;YOUR_START_IP&amp;quot; -endIP &amp;quot;YOUR_END_IP&amp;quot; [-ThrottleLimit DESIRED_NUMBER]&lt;br /&gt;
#&amp;gt;&lt;br /&gt;
param (&lt;br /&gt;
    [Parameter(Mandatory=$true, HelpMessage=&amp;quot;Enter the starting IP address (e.g., 192.168.1.1)&amp;quot;)]&lt;br /&gt;
    [string]$startIP,&lt;br /&gt;
&lt;br /&gt;
    [Parameter(Mandatory=$true, HelpMessage=&amp;quot;Enter the ending IP address (e.g., 192.168.1.254)&amp;quot;)]&lt;br /&gt;
    [string]$endIP,&lt;br /&gt;
&lt;br /&gt;
    [Parameter(HelpMessage=&amp;quot;Maximum number of concurrent ping operations. Default is 30.&amp;quot;)]&lt;br /&gt;
    [ValidateRange(1,200)] # Practical limit for throttle&lt;br /&gt;
    [int]$ThrottleLimit = 30&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
# --- Script Body ---&lt;br /&gt;
&lt;br /&gt;
Write-Host &amp;quot;🚀 Initializing threaded ping scan...&amp;quot; -ForegroundColor Yellow&lt;br /&gt;
&lt;br /&gt;
# Basic IP address format validation (IPv4)&lt;br /&gt;
$ipPattern = &amp;#039;^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$&amp;#039;&lt;br /&gt;
if (-not ($startIP -match $ipPattern)) {&lt;br /&gt;
    Write-Error &amp;quot;Invalid format for Start IP: &amp;#039;$startIP&amp;#039;. Please use a valid IPv4 format (e.g., 192.168.1.1).&amp;quot;&lt;br /&gt;
    exit 1&lt;br /&gt;
}&lt;br /&gt;
if (-not ($endIP -match $ipPattern)) {&lt;br /&gt;
    Write-Error &amp;quot;Invalid format for End IP: &amp;#039;$endIP&amp;#039;. Please use a valid IPv4 format (e.g., 192.168.1.254).&amp;quot;&lt;br /&gt;
    exit 1&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Parse IP addresses&lt;br /&gt;
try {&lt;br /&gt;
    $startAddressBytes = [System.Net.IPAddress]::Parse($startIP).GetAddressBytes()&lt;br /&gt;
    $endAddressBytes = [System.Net.IPAddress]::Parse($endIP).GetAddressBytes()&lt;br /&gt;
} catch {&lt;br /&gt;
    Write-Error &amp;quot;Failed to parse one or both IP addresses. Ensure they are valid IPv4 addresses.&amp;quot;&lt;br /&gt;
    Write-Error &amp;quot;Error details: $($_.Exception.Message)&amp;quot;&lt;br /&gt;
    exit 1&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$networkPrefix = &amp;quot;$($startAddressBytes[0]).$($startAddressBytes[1]).$($startAddressBytes[2])&amp;quot;&lt;br /&gt;
$startHostOctet = [int]$startAddressBytes[3]&lt;br /&gt;
$endHostOctetLoopEnd = [int]$endAddressBytes[3]&lt;br /&gt;
&lt;br /&gt;
if (($startAddressBytes[0] -ne $endAddressBytes[0]) -or `&lt;br /&gt;
    ($startAddressBytes[1] -ne $endAddressBytes[1]) -or `&lt;br /&gt;
    ($startAddressBytes[2] -ne $endAddressBytes[2])) {&lt;br /&gt;
    Write-Warning &amp;quot;The Start IP ($startIP) and End IP ($endIP) do not share the same first three octets.&amp;quot;&lt;br /&gt;
    Write-Warning &amp;quot;This script will use the network prefix of the Start IP (&amp;#039;$networkPrefix.x&amp;#039;) and iterate the last octet from $startHostOctet to $endHostOctetLoopEnd.&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ($startHostOctet -gt $endHostOctetLoopEnd) {&lt;br /&gt;
    Write-Error &amp;quot;The last octet of Start IP ($startHostOctet) is greater than the last octet of End IP ($endHostOctetLoopEnd) for the determined network prefix &amp;#039;$networkPrefix.x&amp;#039;. This forms an invalid range for this script&amp;#039;s logic.&amp;quot;&lt;br /&gt;
    exit 1&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Generate list of IPs to test&lt;br /&gt;
$ipsToTest = [System.Collections.Generic.List[string]]::new()&lt;br /&gt;
for ($currentHostOctet = $startHostOctet; $currentHostOctet -le $endHostOctetLoopEnd; $currentHostOctet++) {&lt;br /&gt;
    $ipsToTest.Add(&amp;quot;$networkPrefix.$currentHostOctet&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ($ipsToTest.Count -eq 0) {&lt;br /&gt;
    Write-Warning &amp;quot;No IP addresses generated for the given range. Exiting.&amp;quot;&lt;br /&gt;
    exit 0&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$fullStartRangeIPToScan = $ipsToTest[0]&lt;br /&gt;
$fullEndRangeIPToScan = $ipsToTest[$ipsToTest.Count -1]&lt;br /&gt;
&lt;br /&gt;
Write-Host &amp;quot;Scanning IP addresses from $fullStartRangeIPToScan to $fullEndRangeIPToScan.&amp;quot;&lt;br /&gt;
Write-Host &amp;quot;Using up to $ThrottleLimit concurrent threads.&amp;quot;&lt;br /&gt;
Write-Host &amp;quot;Each IP will be pinged twice.&amp;quot;&lt;br /&gt;
Write-Host &amp;quot;--------------------------------------------------&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Define the script block to be executed in each thread&lt;br /&gt;
$scriptBlock = {&lt;br /&gt;
    param($targetIPToPing)&lt;br /&gt;
&lt;br /&gt;
    # Test-Connection sends ICMP echo requests.&lt;br /&gt;
    $pingReplies = Test-Connection -ComputerName $targetIPToPing -Count 2 -ErrorAction SilentlyContinue -WarningAction SilentlyContinue&lt;br /&gt;
    &lt;br /&gt;
    if ($pingReplies) {&lt;br /&gt;
        return [PSCustomObject]@{&lt;br /&gt;
            IPAddress = $targetIPToPing&lt;br /&gt;
            Status    = &amp;quot;Online&amp;quot;&lt;br /&gt;
            Timestamp = Get-Date&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        return [PSCustomObject]@{&lt;br /&gt;
            IPAddress = $targetIPToPing&lt;br /&gt;
            Status    = &amp;quot;Offline&amp;quot;&lt;br /&gt;
            Timestamp = Get-Date&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Initialize Runspace Pool&lt;br /&gt;
$runspacePool = [runspacefactory]::CreateRunspacePool(1, $ThrottleLimit)&lt;br /&gt;
$runspacePool.Open()&lt;br /&gt;
&lt;br /&gt;
$activeJobs = [System.Collections.Generic.List[object]]::new()&lt;br /&gt;
$finalResults = [System.Collections.Generic.List[object]]::new()&lt;br /&gt;
&lt;br /&gt;
try {&lt;br /&gt;
    foreach ($ip in $ipsToTest) {&lt;br /&gt;
        $powershell = [powershell]::Create().AddScript($scriptBlock).AddArgument($ip)&lt;br /&gt;
        $powershell.RunspacePool = $runspacePool&lt;br /&gt;
        &lt;br /&gt;
        $activeJobs.Add([PSCustomObject]@{&lt;br /&gt;
            IP          = $ip&lt;br /&gt;
            Pipe        = $powershell&lt;br /&gt;
            AsyncHandle = $powershell.BeginInvoke()&lt;br /&gt;
        })&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $totalIPs = $ipsToTest.Count&lt;br /&gt;
    $processedCount = 0&lt;br /&gt;
&lt;br /&gt;
    # Monitor and process completed jobs&lt;br /&gt;
    while ($activeJobs.Count -gt 0) {&lt;br /&gt;
        # Create a temporary list of jobs that have completed in this iteration&lt;br /&gt;
        $completedThisIteration = [System.Collections.Generic.List[object]]::new()&lt;br /&gt;
&lt;br /&gt;
        foreach ($jobHandle in $activeJobs) {&lt;br /&gt;
            if ($jobHandle.AsyncHandle.IsCompleted) {&lt;br /&gt;
                $completedThisIteration.Add($jobHandle)&lt;br /&gt;
                try {&lt;br /&gt;
                    $resultObject = $jobHandle.Pipe.EndInvoke($jobHandle.AsyncHandle)&lt;br /&gt;
                    if ($resultObject) {&lt;br /&gt;
                        $finalResults.Add($resultObject)&lt;br /&gt;
                    }&lt;br /&gt;
                } catch {&lt;br /&gt;
                    Write-Warning &amp;quot;Error processing IP $($jobHandle.IP): $($_.Exception.Message)&amp;quot;&lt;br /&gt;
                    $finalResults.Add([PSCustomObject]@{&lt;br /&gt;
                        IPAddress = $jobHandle.IP&lt;br /&gt;
                        Status    = &amp;quot;Error&amp;quot;&lt;br /&gt;
                        Message   = $_.Exception.Message&lt;br /&gt;
                        Timestamp = Get-Date&lt;br /&gt;
                    })&lt;br /&gt;
                } finally {&lt;br /&gt;
                    $jobHandle.Pipe.Dispose()&lt;br /&gt;
                    $processedCount++&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        # Remove all completed jobs from the active list&lt;br /&gt;
        if ($completedThisIteration.Count -gt 0) {&lt;br /&gt;
            $completedThisIteration | ForEach-Object { $activeJobs.Remove($_) }&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        if ($activeJobs.Count -gt 0) {&lt;br /&gt;
            Write-Progress -Activity &amp;quot;Pinging IPs&amp;quot; -Status &amp;quot;Processing... ($processedCount/$totalIPs completed)&amp;quot; -PercentComplete ([math]::Round(($processedCount / $totalIPs) * 100)) -CurrentOperation &amp;quot;$($activeJobs.Count) tasks remaining&amp;quot;&lt;br /&gt;
            Start-Sleep -Milliseconds 200 # Wait a bit before checking again&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    Write-Progress -Activity &amp;quot;Pinging IPs&amp;quot; -Completed&lt;br /&gt;
}&lt;br /&gt;
finally {&lt;br /&gt;
    # Close and dispose the runspace pool&lt;br /&gt;
    if ($runspacePool) {&lt;br /&gt;
        $runspacePool.Close()&lt;br /&gt;
        $runspacePool.Dispose()&lt;br /&gt;
    }&lt;br /&gt;
    Write-Host &amp;quot;Runspace pool closed.&amp;quot; -ForegroundColor DarkGray&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Sort and display all collected results&lt;br /&gt;
Write-Host &amp;quot;`n--- Scan Results (Sorted by IP) ---&amp;quot; -ForegroundColor Yellow&lt;br /&gt;
$sortedResults = $finalResults | Sort-Object { [System.Net.IPAddress]$_.IPAddress }&lt;br /&gt;
&lt;br /&gt;
foreach ($result in $sortedResults) {&lt;br /&gt;
    switch ($result.Status) {&lt;br /&gt;
        &amp;quot;Online&amp;quot;  { Write-Host &amp;quot;&amp;gt; $($result.IPAddress) - $($result.Status) ✅&amp;quot; -ForegroundColor Green }&lt;br /&gt;
        #&amp;quot;Offline&amp;quot; { Write-Host &amp;quot;&amp;gt; $($result.IPAddress) - $($result.Status) ❌&amp;quot; -ForegroundColor Red }&lt;br /&gt;
        #&amp;quot;Error&amp;quot;   { Write-Host &amp;quot;&amp;gt; $($result.IPAddress) - $($result.Status) ⚠️ (Message: $($result.Message))&amp;quot; -ForegroundColor Magenta }&lt;br /&gt;
        #default   { Write-Host &amp;quot;&amp;gt; $($result.IPAddress) - Status Unknown&amp;quot; }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Write-Host &amp;quot;--------------------------------------------------&amp;quot;&lt;br /&gt;
Write-Host &amp;quot;🎉 Threaded ping scan finished.&amp;quot; -ForegroundColor Yellow&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Rabbi Bob</name></author>
	</entry>
</feed>