Script
Test a list of hosts
Ping every name or address in a text file, or check a TCP port on each.
Useful as a quick "is the office printer still on the network" check. You get one row per host with Reachable and LatencyMs.
Ping (ICMP) is often blocked even when the host is up. If a server shows as unreachable but you know it is running, test the port it actually serves instead: 443 for a website, 3389 for Remote Desktop, 445 for file shares.
.\test-hosts.ps1 -HostsPath .\hosts.txt
.\test-hosts.ps1 -HostsPath .\hosts.txt -Port 443
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
-HostsPath |
string | Yes | Text file with one host per line. Blank lines and |
-Count |
int | No | Echo requests per host when pinging. Default 1. |
-Port |
int | No | TCP port to test instead of pinging, for example 443. |
-TimeoutMs |
int | No | Milliseconds to wait for each TCP connection. Default 2000. |
Source
<#
.SYNOPSIS
Ping each host listed in a text file, or test a TCP port on each.
.DESCRIPTION
Without -Port, sends ICMP echo requests (ping). Many hosts block ping
and still work, so -Port checks a TCP port instead (for example 443 for
a web server or 3389 for Remote Desktop). Works on Windows, Linux, and macOS.
.PARAMETER HostsPath
Text file, one host per line. Blank lines and lines starting with # are ignored.
.PARAMETER Count
Echo requests per host when pinging. Default 1.
.PARAMETER Port
TCP port to test instead of pinging.
.PARAMETER TimeoutMs
How long to wait for each TCP connection, in milliseconds. Default 2000.
.EXAMPLE
.\test-hosts.ps1 -HostsPath .\hosts.txt
.EXAMPLE
.\test-hosts.ps1 -HostsPath .\hosts.txt -Port 443
#>
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[string]$HostsPath,
[ValidateRange(1, 100)]
[int]$Count = 1,
[ValidateRange(1, 65535)]
[int]$Port,
[ValidateRange(100, 60000)]
[int]$TimeoutMs = 2000
)
$ErrorActionPreference = 'Stop'
if (-not (Test-Path -LiteralPath $HostsPath -PathType Leaf)) {
throw "Hosts file not found: $HostsPath"
}
$names = Get-Content -LiteralPath $HostsPath |
ForEach-Object { $_.Trim() } |
Where-Object { $_ -and ($_ -notmatch '^#') }
function Test-TcpPort {
param([string]$ComputerName, [int]$PortNumber, [int]$Timeout)
$client = New-Object System.Net.Sockets.TcpClient
$watch = [System.Diagnostics.Stopwatch]::StartNew()
try {
$task = $client.ConnectAsync($ComputerName, $PortNumber)
$ok = $task.Wait($Timeout) -and $client.Connected
} catch {
$ok = $false
} finally {
$watch.Stop()
$client.Dispose()
}
[pscustomobject]@{
Reachable = [bool]$ok
LatencyMs = if ($ok) { [int]$watch.ElapsedMilliseconds } else { $null }
}
}
foreach ($name in $names) {
if ($PSBoundParameters.ContainsKey('Port')) {
$result = Test-TcpPort -ComputerName $name -PortNumber $Port -Timeout $TimeoutMs
[pscustomobject]@{
Host = $name
Port = $Port
Reachable = $result.Reachable
LatencyMs = $result.LatencyMs
}
continue
}
# PowerShell 7 returns objects with Status and Latency; 5.1 returns
# Win32_PingStatus with StatusCode and ResponseTime.
$replies = @(Test-Connection -ComputerName $name -Count $Count -ErrorAction SilentlyContinue)
$good = @($replies | Where-Object {
if ($_.PSObject.Properties['Latency']) { "$($_.Status)" -eq 'Success' } else { $_.StatusCode -eq 0 }
})
$times = @($good | ForEach-Object {
if ($_.PSObject.Properties['Latency']) { $_.Latency } else { $_.ResponseTime }
})
[pscustomobject]@{
Host = $name
Port = $null
Reachable = $good.Count -gt 0
LatencyMs = if ($times.Count -gt 0) { [int](($times | Measure-Object -Average).Average) } else { $null }
}
}
Downloaded it? Windows blocks scripts from the internet until you unblock them: Unblock-File -Path .\test-hosts.ps1. See Run a script.
Edit this page on GitHub Edit test-hosts.ps1 Report a problem