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.
Beyond Test-NetConnection: pktmon, netsh trace and pathping
Test-NetConnection answers "can I reach this port from here, right now". The deeper questions โ is the path stable, what is the actual latency distribution, who is dropping packets โ need different tools that ship in the box.
Pathping for hop-by-hop loss
pathping sends 100 ICMP probes per hop and reports loss percentage at each. Slow but invaluable for finding the one ISP hop that is silently dropping 5% of packets.
pathping -n -q 50 -p 250 outlook.office365.com
Read the right-most "Lost/Sent" column. Loss that starts at hop 4 and persists through hop N tells you the problem is at hop 4. Loss that appears only at the destination is the destination's problem.
pktmon for in-box packet capture
Wireshark is great; it is also a download you cannot always install on a production box. pktmon is built in from Windows 10 1809 and Server 2019.
REM Capture all traffic to/from a specific IP, max 100 MB
pktmon filter add -i 10.20.30.40
pktmon start --capture -m real-time -f C:\temp\cap.etl -s 100
REM ...reproduce the issue, then stop and convert
pktmon stop
pktmon etl2pcap C:\temp\cap.etl -o C:\temp\cap.pcap
Open the PCAP in Wireshark on a workstation. The ETL file is also readable directly with Microsoft Network Monitor for offline triage.
Persistent route and DNS state
A connection that worked yesterday and fails today is often a routing or DNS change. Capture both at once:
Get-NetRoute -AddressFamily IPv4 |
Sort-Object InterfaceIndex, DestinationPrefix |
Format-Table InterfaceIndex, DestinationPrefix, NextHop, RouteMetric -AutoSize
Get-DnsClientServerAddress |
Where-Object AddressFamily -eq 2 |
Format-Table InterfaceAlias, ServerAddresses -AutoSize
Get-NetConnectionProfile |
Format-Table InterfaceAlias, NetworkCategory, IPv4Connectivity -AutoSize
Common pitfalls
- Trusting ICMP for application reachability. Many firewalls block ICMP but allow the app port. Always test the actual TCP port, not
ping. - Ignoring the source interface. A multi-homed box may route the test through the wrong NIC. Use
-SourceonTest-NetConnectionor setSet-NetIPInterface -InterfaceMetric. - Capturing on the wrong host. A capture on the server that confirms "I never received a packet" is the start of the investigation, not the end. Capture at the client and at every hop you control.
- Forgetting MTU. A path that passes
Test-NetConnectioncan fail for large payloads if PMTU discovery is broken. Test withping -f -l 1472and decrease until packets get through. - No baseline. "Latency to the file server is 80 ms" is meaningless without yesterday's value. Schedule a daily probe and store the output.
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.
Related reading
What is the modern replacement for netstat -anob?
Get-NetTCPConnection | Where-Object State -eq Established joined with Get-Process on PID. Faster, scriptable, returns objects you can filter and export.
How do I capture only DNS traffic?
pktmon filter add -p 53 before starting the capture. Combine with -i to scope to one host.
Can I run these tools remotely?
Most accept a target name (Test-NetConnection -ComputerName) but the local-host tools (pktmon, netsh trace) need to run on the target. Use PowerShell Remoting or PsExec.
What about WSL networking?
WSL2 has its own virtual NIC and a NAT layer. Test-NetConnection from Windows tests Windows; from WSL it tests WSL. Run both when the symptom involves a Linux developer's container.