The first network test most people reach for is ping. In 2026 that is the wrong instinct — every modern firewall drops ICMP, every cloud provider blocks pings to load balancers, and a successful ping tells you almost nothing about whether HTTPS to port 443 actually works. The PowerShell cmdlets that replaced the legacy tools (tracert, nslookup, netstat) are faster, more useful, and produce structured objects you can pipe into anything else.
This guide is the modern Windows network troubleshooting toolkit, in the order you actually use it during an outage. Free PDF cheat sheet at the bottom.
Table of Contents
- Test-NetConnection — the universal first test
- Resolve-DnsName — better nslookup
- tracert and pathping
- Get-NetTCPConnection — better netstat
- Get-NetRoute and Get-NetIPAddress
- Get-NetFirewallRule
- Interface stats and counters
- Invoke-WebRequest for HTTP-level checks
- Common troubleshooting patterns
- Cheat sheet
- FAQ
Test-NetConnection — the universal first test
Test-NetConnection (alias tnc) is the cmdlet that should replace ping in your muscle memory. It does ICMP, but more importantly it does TCP connect tests against a port:
# Just like ping
Test-NetConnection -ComputerName api.example.com
# TCP port test - the actually useful one
Test-NetConnection -ComputerName api.example.com -Port 443
# Trace the route as part of the test
Test-NetConnection -ComputerName api.example.com -TraceRoute
# Common ports as switches
Test-NetConnection -ComputerName fileserver -CommonTCPPort RDP
# CommonTCPPort options: HTTP, HTTPS, RDP, SMB, WINRM
The output object includes TcpTestSucceeded, RemoteAddress (the resolved IP), InterfaceAlias, and the source IP that would be used. Pipe it; do not parse it.
# Bulk port scan against a list of hosts
Get-Content servers.txt | ForEach-Object -Parallel {
$r = Test-NetConnection -ComputerName $_ -Port 443 -WarningAction SilentlyContinue
[PSCustomObject]@{
Host = $_
IP = $r.RemoteAddress
Up = $r.TcpTestSucceeded
}
} -ThrottleLimit 30 | Format-Table -AutoSize
Resolve-DnsName — better nslookup
# Basic A record lookup
Resolve-DnsName api.example.com
# Specific record type
Resolve-DnsName example.com -Type MX
Resolve-DnsName example.com -Type TXT
Resolve-DnsName example.com -Type AAAA # IPv6
Resolve-DnsName example.com -Type SRV -Name "_ldap._tcp.dc._msdcs.example.com"
# Force a specific DNS server
Resolve-DnsName api.example.com -Server 8.8.8.8
# Skip cache (test the actual resolver chain)
Resolve-DnsName api.example.com -DnsOnly -NoHostsFile
# Reverse lookup
Resolve-DnsName -Name 8.8.8.8 -Type PTR
The output is structured — every record's TTL, type, and value is a property. (Resolve-DnsName api.example.com).IPAddress just gives you the IP.
tracert and pathping
Despite being legacy, the two trace tools have no PowerShell equivalent worth using. Use them as-is:
tracert -d -h 20 api.example.com
# pathping - tracert + per-hop loss after a settle period (60-120 seconds)
pathping -h 20 -p 200 api.example.com
pathping is the right tool for "the connection works but feels slow" — it identifies which hop is dropping packets.
Get-NetTCPConnection — better netstat
# All listening ports (like netstat -an | findstr LISTEN)
Get-NetTCPConnection -State Listen | Format-Table LocalAddress, LocalPort, OwningProcess
# Resolve to process name
Get-NetTCPConnection -State Listen |
Select-Object LocalAddress, LocalPort,
@{n='Process';e={(Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).Name}} |
Sort-Object LocalPort
# All ESTABLISHED outbound connections
Get-NetTCPConnection -State Established |
Where-Object RemoteAddress -ne '0.0.0.0' |
Format-Table LocalAddress, LocalPort, RemoteAddress, RemotePort
# What is using port 5985?
Get-NetTCPConnection -LocalPort 5985 -ErrorAction SilentlyContinue
Get-NetRoute and Get-NetIPAddress
# Routing table (formerly route print)
Get-NetRoute | Sort-Object DestinationPrefix |
Format-Table InterfaceAlias, DestinationPrefix, NextHop, RouteMetric
# What route would be used to reach a specific destination?
Find-NetRoute -RemoteIPAddress 8.8.8.8
# IP configuration (formerly ipconfig)
Get-NetIPAddress | Format-Table InterfaceAlias, IPAddress, PrefixLength, AddressFamily
Get-NetIPConfiguration | Format-List
# Default gateway only
(Get-NetIPConfiguration).IPv4DefaultGateway.NextHop
Get-NetFirewallRule
# Find rules for a specific port
Get-NetFirewallPortFilter | Where-Object LocalPort -eq 443 |
Get-NetFirewallRule | Where-Object Enabled -eq True
# Find inbound rules currently active
Get-NetFirewallRule -Direction Inbound -Enabled True -Action Allow |
Select-Object DisplayName, Profile, Action
# Add a rule
New-NetFirewallRule -DisplayName "App-API" -Direction Inbound `
-Protocol TCP -LocalPort 8443 -Action Allow
Interface stats and counters
# Throughput counters
Get-NetAdapterStatistics |
Format-Table Name, ReceivedBytes, SentBytes, ReceivedDiscardedPackets
# Errors and discards (a healthy interface should be 0)
Get-NetAdapterAdvancedProperty | Where-Object DisplayName -like '*Error*'
# Reset counters? Restart the interface (run as admin)
Restart-NetAdapter -Name 'Ethernet'
Invoke-WebRequest for HTTP-level checks
Layer 4 success (TCP connect) does not mean layer 7 success. Invoke-WebRequest tests the actual HTTP exchange:
# Headers + status
$r = Invoke-WebRequest -Uri https://api.example.com/health -UseBasicParsing -SkipCertificateCheck
$r.StatusCode
$r.Headers
$r.RawContentLength
# Test TLS handshake without following the request
[System.Net.ServicePointManager]::SecurityProtocol = 'Tls12,Tls13'
Invoke-WebRequest -Uri https://api.example.com -Method Head
Common troubleshooting patterns
"Cannot reach api.example.com"
$h = 'api.example.com'
Resolve-DnsName $h
Test-NetConnection $h -Port 443
tracert -d -h 15 $h
Invoke-WebRequest "https://$h/" -Method Head -UseBasicParsing
"Server is up but the app does not respond"
Get-NetTCPConnection -LocalPort 443 -State Listen
Get-Process -Id (Get-NetTCPConnection -LocalPort 443).OwningProcess
Get-NetFirewallPortFilter | Where-Object LocalPort -eq 443 | Get-NetFirewallRule
"DNS is wrong somewhere"
Resolve-DnsName api.example.com -Server 8.8.8.8
Resolve-DnsName api.example.com -Server (Get-NetIPConfiguration).DNSServer.ServerAddresses[0]
Clear-DnsClientCache
ipconfig /displaydns | Select-String example.com
Cheat sheet
Every cmdlet, every flag, all troubleshooting flows on a single PDF: Windows Network Troubleshooting Cheat Sheet.
FAQ
Why does ping fail but Test-NetConnection -Port 443 succeed?
The remote firewall blocks ICMP but allows TCP/443. This is the default for almost every cloud provider's load balancer. Always test the actual port — ICMP success is irrelevant.
Test-NetConnection is slow — can I make it faster?
Add -WarningAction SilentlyContinue and use -InformationLevel Quiet for a boolean-only result. The ICMP fallback when the port test fails is what eats most of the wall-clock.
Why does Resolve-DnsName return cached results?
The DNS Client cache. Clear-DnsClientCache resets it. -DnsOnly skips the cache for one query.
How do I see what process owns port 5985?
Get-NetTCPConnection -LocalPort 5985 | Select OwningProcess; Get-Process -Id <PID>.
Tracert shows asterisks at every hop — what now?
Either ICMP TTL-expired is filtered along the path (very common in clouds), or the destination drops UDP/ICMP. Use tracert -d (skip reverse DNS), increase -w timeout, or fall back to tcping per hop.
How do I capture packets without Wireshark?
Built-in: netsh trace start capture=yes tracefile=C:\trace.etl, reproduce, netsh trace stop. Open the .etl in Microsoft Message Analyzer (legacy) or convert to .pcap with etl2pcapng.
Get-NetFirewallRule lists thousands of rules — how do I find the one I added?
Filter by DisplayName, DisplayGroup, or use Get-NetFirewallProfile to see which profile is active first.