A network connection has a binary cruelty to it: either the host you depend on answers, or it does not, and the moment it stops answering is rarely the moment anyone happens to be looking. A critical server, an internet gateway, a remote service, all of them can vanish silently, and the first sign is often a user complaint or a failed process long after the outage began. A network availability script is the patient sentinel that pings what matters on a schedule and raises an alarm the instant something stops responding, compressing the gap between failure and awareness from hours to minutes.
The case for automating this is the same that underlies all monitoring: outages do not wait for business hours, and human vigilance is no match for a script that never blinks. Regularly testing connectivity to critical hosts proactively surfaces downtime and connectivity problems before they cascade into larger failures, and doing it automatically means the discovery happens on its own rather than depending on someone noticing. The tools are built into Windows, the logic is short, and the result is the difference between learning of an outage from your monitoring and learning of it from an angry phone call.
Two Tools for Two Kinds of Reachability Question
PowerShell offers two distinct commands for testing connectivity, and choosing the right one matters because they answer different questions. The simpler command is essentially an advanced ping, sending echo requests to a host and reporting whether they return. Its great virtue for monitoring is a quiet mode that collapses the result to a plain true or false, perfect for a script that just needs to know whether a host is up without parsing verbose output.
Test-Connection -ComputerName "server01" -Count 2 -Quiet
This returns a simple boolean: the host either answered the pings or it did not. The count parameter controls how many echo requests are sent, and a small count of two or three balances responsiveness against tolerance for a single dropped packet. For straightforward up-or-down monitoring of a host that responds to ping, this command is the lightweight, reliable choice.
The second command is more comprehensive, going beyond ping to test actual service ports and resolve names. It can verify not just that a host is reachable but that a specific service is listening, by attempting a real connection to a named port. This distinction is vital, because a host can answer pings while the service running on it has died, and only a port test catches that. When the connection to a port is checked, the authoritative result is whether the port test succeeded, separate from whether the ping succeeded.
Test-NetConnection -ComputerName "server01" -Port 443
The richer command also helps diagnose subtler failures. If a ping succeeds but the port test fails, the service is down or a firewall is blocking that specific port, a far more precise conclusion than a bare ping could offer. For monitoring services rather than mere hosts, the port-aware command is the one that actually confirms the thing users care about is working.
Checking Many Hosts and Distinguishing Failure Types
Real monitoring rarely concerns a single host, so the natural pattern reads a list of targets and tests each in turn. Because the simpler ping command does not accept a list directly through the pipeline, the script iterates over the hosts explicitly, testing each and collecting the ones that fail. This loop is the heart of an automated network audit, checking dozens or hundreds of hosts on a schedule and flagging only those that did not respond.
$hosts = Get-Content "C:\Scripts\hosts.txt"
$down = foreach ($h in $hosts) {
if (-not (Test-Connection -ComputerName $h -Count 2 -Quiet)) {
[PSCustomObject]@{ Host = $h; Status = 'Unreachable'; Time = Get-Date }
}
}
Reading the host list from an external file keeps the monitor easy to maintain, since adding or removing a target is a matter of editing a text file rather than the script. The loop produces a tidy collection of exactly the hosts that failed, which becomes the basis for the alert. Only if that collection contains anything does the script proceed to notify, keeping it silent when everything is reachable.
A more discerning monitor distinguishes between kinds of failure rather than treating all unreachability alike. Combining a ping test with a port test reveals whether a host is entirely down, reachable but with its service dead, or unreachable for reasons of name resolution or routing. There is also a quiet trap worth anticipating: if a hostname resolves to an address family the network does not support, the test may report failure even though the host is genuinely reachable by another path, so for ambiguous results it can help to resolve the name to a specific address explicitly before testing.
Building an Alert Worth Acting On
When a host fails, the alert must convey clearly what is down and since when, so the responder can act without first investigating what the alert even means. Formatting the failed hosts into a concise message, naming each unreachable host and the time the failure was detected, turns a detection into something a human can immediately act on. Including the monitoring machine's own identity is useful too, since it tells the responder which vantage point saw the failure, which matters when the problem might be the network path rather than the host itself.
if ($down) {
$body = "The following hosts are unreachable from $env:COMPUTERNAME:`n`n"
$body += $down | Format-Table Host, Status, Time -AutoSize | Out-String
# send the alert
}
The subject line of the alert carries disproportionate weight, because in a flood of messages people triage by subject first. A subject that names the problem and the affected host plainly lets a responder grasp the situation before opening the message, which during an outage is precisely when seconds count. Stating the failure rather than burying it in pleasantries respects the urgency that any availability alert implies.
A subtle but important refinement is guarding against alert storms from transient blips. A single dropped ping does not always mean a real outage, so a robust monitor often requires a host to fail several consecutive checks before alerting, and may alert only once per outage rather than every cycle. This prevents a momentary network hiccup from generating a panic and prevents a sustained outage from burying the inbox under a new alert every few minutes, both of which erode trust in the monitoring.
Remembering State to Detect Recovery and Avoid Repetition
A monitor that only knows the present moment has a blind spot: it cannot tell a host that just failed from one that has been down for an hour, nor can it announce when a host comes back. The cure is to give the monitor a memory by recording the last known state of each host between runs, so that each cycle compares the current result against the previous one. This small addition transforms a stateless checker into one that understands transitions, which is what alerting should really be built around.
$stateFile = 'C:\Scripts\hoststate.json'
$previous = if (Test-Path $stateFile) { Get-Content $stateFile | ConvertFrom-Json } else { @{} }
# compare current result for each host against $previous, then save the new state
$current | ConvertTo-Json | Set-Content $stateFile
With remembered state, the monitor alerts on change rather than on condition, which is far more useful. It can fire a single alert at the moment a host goes from up to down, stay quiet through the duration of the outage rather than repeating every cycle, and then send a recovery notice when the host returns. This change-based approach is what prevents both the alert fatigue of constant reminders during a known outage and the silence that would otherwise leave a responder wondering whether a problem ever resolved.
State tracking also enables a more honest record of availability over time. By logging each transition with its timestamp, the monitor builds a history of when each host was up and down, from which uptime can actually be calculated rather than guessed. That history answers questions a momentary check never could, such as how often a flaky host really fails and for how long, which turns anecdotal impressions of unreliability into measured fact that can justify repair or replacement.
Delivering the Notification Reliably
An alert that reaches no one protects no one, so delivery deserves as much thought as detection. The classic channel is email, sent through the organization's mail server to one or more recipients, flagged with high priority so it stands out. Sending to several addresses at once guards against the alert being missed because the one person who would have seen it is unavailable.
Send-MailMessage -SmtpServer 'smtp.example.com' `
-From Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript. ' -To @(Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript. ') `
-Subject "[NET ALERT] Host(s) unreachable from $env:COMPUTERNAME" `
-Body $body -Priority High
Where email is impractical, the same failure logic can drive other channels instead, writing to the system event log where existing tooling watches, or pushing a message into whatever chat or ticketing platform the team actually monitors during incidents. The guiding principle is that the alert must land where the responsible person is genuinely looking, not merely where it is convenient to send it, since a warning delivered to an unwatched mailbox is no warning at all.
A practical caution applies to the monitoring host itself: it must have a reachable path to its alert channel even when the network is troubled. If the same outage that takes down the monitored hosts also severs the monitor's route to its mail server, the alert will never escape, which is a painful irony to discover during a real incident. Where possible, the monitoring vantage point and its notification path should be positioned so that common failure modes do not silence the alarm at the very moment it is needed most.
Scheduling the Monitor for Round-the-Clock Coverage
A connectivity check is only as good as its frequency, so the monitor must run often enough to catch an outage promptly rather than once a day. The task scheduler supports this through a trigger that repeats at short intervals, and registering the task from PowerShell keeps it reproducible across machines. The pattern combines a base trigger with a repetition interval so the check fires every few minutes continuously.
$action = New-ScheduledTaskAction -Execute 'powershell.exe' `
-Argument '-NoProfile -WindowStyle Hidden -File "C:\Scripts\netcheck.ps1"'
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) `
-RepetitionInterval (New-TimeSpan -Minutes 5) `
-RepetitionDuration ([TimeSpan]::MaxValue)
Register-ScheduledTask -TaskName 'NetworkMonitor' `
-Action $action -Trigger $trigger -User 'SYSTEM' -RunLevel Highest `
-Description 'Check critical host availability every 5 minutes'
The interval is a balance between responsiveness and noise. A check every few minutes catches outages quickly while leaving room for the consecutive-failure logic that filters out momentary blips, whereas checking too frequently adds little and risks treating ordinary jitter as failure. Running under a system account ensures the task executes reliably without depending on a particular user being logged in, so the monitoring continues through reboots and across sessions.
Because the script, its host list, and the scheduled task are all defined in code, the identical monitor can be deployed across many machines, and even positioned at several vantage points so that a failure seen from one location but not another reveals whether the problem is the host or the path to it. This kind of distributed checking turns a simple up-or-down monitor into a tool that can localize where in the network a problem actually lies.
What Continuous Availability Monitoring Really Delivers
The deeper point is that an outage discovered late is an outage made worse, and the only reliable way to discover one early is to keep checking when no one is watching. A host that goes dark at three in the morning should not first be noticed by a failed morning process; it should already have triggered an alert hours before, while there was still time to respond. Automated availability checking closes that window, turning silent failures into prompt notifications.
A well-built monitor chooses the right test for the question, a simple ping for host reachability or a port test for service health, checks its targets often enough to matter, distinguishes real outages from transient blips so it neither cries wolf nor floods the inbox, and delivers its alerts reliably to where someone will see them. Each element is modest, but together they form a dependable watch that asks nothing of the administrator until there is genuinely something to report.
In the end, network availability monitoring is how an administrator trades anxiety for confidence. Instead of wondering whether everything is still reachable, there is a sentinel that would have spoken up if it were not, and silence becomes meaningful rather than merely uninformed. The small effort of building and scheduling the check repays itself the first time it catches an outage in its opening minutes, when a quick response can prevent the cascade of failures that a few unwatched hours would otherwise have allowed.