Created
February 25, 2026 19:55
-
-
Save faishal/68edb817ab37ab269831f5c3c03f6a5f to your computer and use it in GitHub Desktop.
PowerShell connectivity triage script for a Windows user, It collects the most common root-cause signals in one go: link/IP/DNS, proxy/VPN, routes, firewall profile, WinHTTP proxy, NRPT (DoH/DirectAccess-related DNS rules), captive portal, and a few targeted tests (ping + TCP connect + HTTP).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <# | |
| .SYNOPSIS | |
| Color-coded Windows Internet Connectivity Diagnostic (read-only) | |
| .DESCRIPTION | |
| Prints quick PASS/FAIL checks in color and writes a detailed report to C:\Temp. | |
| Checks: adapter up, IP/default gateway, DNS resolve, TCP 443, HTTP/HTTPS fetch, | |
| proxy (user + winhttp), VPN-ish adapters, NCSI hints. | |
| #> | |
| param( | |
| [string]$OutDir = "C:\Temp", | |
| [string[]]$DnsTestNames = @("www.microsoft.com","www.cloudflare.com","www.google.com"), | |
| [string[]]$TcpTestHosts = @("1.1.1.1","8.8.8.8","www.microsoft.com"), | |
| [int]$TcpTestPort = 443, | |
| [string[]]$HttpTestUrls = @( | |
| "http://www.msftconnecttest.com/connecttest.txt", | |
| "http://www.msftncsi.com/ncsi.txt", | |
| "https://www.microsoft.com" | |
| ) | |
| ) | |
| # ---------- helpers ---------- | |
| function Write-Status { | |
| param( | |
| [ValidateSet("PASS","FAIL","WARN","INFO")][string]$Level, | |
| [string]$Message | |
| ) | |
| switch ($Level) { | |
| "PASS" { Write-Host ("[PASS] " + $Message) -ForegroundColor Green } | |
| "FAIL" { Write-Host ("[FAIL] " + $Message) -ForegroundColor Red } | |
| "WARN" { Write-Host ("[WARN] " + $Message) -ForegroundColor Yellow } | |
| "INFO" { Write-Host ("[INFO] " + $Message) -ForegroundColor Cyan } | |
| } | |
| } | |
| function Write-Section($Title) { | |
| Write-Host "`n==== $Title ====" -ForegroundColor Magenta | |
| } | |
| function Safe($Name, [scriptblock]$Block) { | |
| try { & $Block } catch { Write-Status FAIL "$Name error: $($_.Exception.Message)" } | |
| } | |
| # ---------- output prep ---------- | |
| if (!(Test-Path $OutDir)) { New-Item -ItemType Directory -Path $OutDir -Force | Out-Null } | |
| $ts = Get-Date -Format "yyyyMMdd_HHmmss" | |
| $reportPath = Join-Path $OutDir "NetDiagColor_$env:COMPUTERNAME`_$ts.txt" | |
| $log = New-Object System.Collections.Generic.List[string] | |
| function Log($s) { $log.Add($s) | Out-Null } | |
| # ---------- header ---------- | |
| Write-Section "Header" | |
| $admin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent() | |
| ).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) | |
| Write-Status INFO "Computer: $env:COMPUTERNAME | User: $env:USERNAME | Admin: $admin" | |
| Log "Computer: $env:COMPUTERNAME" | |
| Log "User: $env:USERNAME" | |
| Log "Admin: $admin" | |
| Log "Timestamp: $(Get-Date -Format o)" | |
| Log "" | |
| # ---------- adapters / IP ---------- | |
| Write-Section "Adapters / IP" | |
| Safe "Adapters" { | |
| $up = Get-NetAdapter | Where-Object Status -eq "Up" | |
| if (-not $up) { | |
| Write-Status FAIL "No network adapters are Up." | |
| Log "FAIL: No network adapters are Up." | |
| } else { | |
| Write-Status PASS ("Up adapters: " + ($up.Name -join ", ")) | |
| Log "PASS: Up adapters: $($up.Name -join ", ")" | |
| } | |
| $cfg = Get-NetIPConfiguration | Where-Object { $_.NetAdapter.Status -eq "Up" } | |
| $hasIPv4 = $cfg | Where-Object { $_.IPv4Address -ne $null } | |
| if ($hasIPv4) { | |
| Write-Status PASS "IPv4 address present on at least one Up adapter." | |
| Log "PASS: IPv4 address present." | |
| } else { | |
| Write-Status FAIL "No IPv4 address detected on Up adapters (DHCP issue?)." | |
| Log "FAIL: No IPv4 address detected." | |
| } | |
| $gws = ($cfg | Where-Object { $_.IPv4DefaultGateway -ne $null }).IPv4DefaultGateway.NextHop | Select-Object -Unique | |
| if ($gws) { | |
| Write-Status PASS ("Default gateway(s): " + ($gws -join ", ")) | |
| Log "PASS: Default gateway(s): $($gws -join ", ")" | |
| } else { | |
| Write-Status FAIL "No IPv4 default gateway detected." | |
| Log "FAIL: No IPv4 default gateway detected." | |
| } | |
| Log "`r`n--- Get-NetIPConfiguration ---" | |
| Log ((Get-NetIPConfiguration | Out-String)) | |
| } | |
| # ---------- proxy ---------- | |
| Write-Section "Proxy" | |
| Safe "User proxy" { | |
| $reg = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings" | |
| $p = Get-ItemProperty -Path $reg -ErrorAction Stop | |
| if ($p.ProxyEnable -eq 1 -and $p.ProxyServer) { | |
| Write-Status WARN "User proxy ENABLED: $($p.ProxyServer)" | |
| Log "WARN: User proxy enabled: $($p.ProxyServer)" | |
| } else { | |
| Write-Status PASS "User proxy appears disabled." | |
| Log "PASS: User proxy appears disabled." | |
| } | |
| Log "`r`n--- User proxy registry ---" | |
| Log ("ProxyEnable: {0}`r`nProxyServer: {1}`r`nAutoConfigURL: {2}`r`nAutoDetect: {3}" -f ` | |
| $p.ProxyEnable, $p.ProxyServer, $p.AutoConfigURL, $p.AutoDetect) | |
| } | |
| Safe "WinHTTP proxy" { | |
| $winhttp = (netsh winhttp show proxy) 2>&1 | Out-String | |
| if ($winhttp -match "Direct access \(no proxy server\)") { | |
| Write-Status PASS "WinHTTP proxy: Direct (no proxy)." | |
| Log "PASS: WinHTTP proxy: Direct." | |
| } else { | |
| Write-Status WARN "WinHTTP proxy may be set. See report." | |
| Log "WARN: WinHTTP proxy may be set." | |
| } | |
| Log "`r`n--- netsh winhttp show proxy ---" | |
| Log $winhttp | |
| } | |
| # ---------- DNS ---------- | |
| Write-Section "DNS" | |
| Safe "DNS tests" { | |
| $dnsFail = 0 | |
| foreach ($name in $DnsTestNames) { | |
| try { | |
| $r = Resolve-DnsName -Name $name -ErrorAction Stop | |
| $ips = ($r | Where-Object {$_.Type -in "A","AAAA"} | Select-Object -ExpandProperty IPAddress -ErrorAction SilentlyContinue) | |
| if ($ips) { | |
| Write-Status PASS "Resolve $name -> $($ips -join ", ")" | |
| Log "PASS: Resolve $name -> $($ips -join ", ")" | |
| } else { | |
| Write-Status WARN "Resolved $name but no A/AAAA returned." | |
| Log "WARN: Resolved $name but no A/AAAA returned." | |
| } | |
| } catch { | |
| $dnsFail++ | |
| Write-Status FAIL "Resolve failed: $name ($($_.Exception.Message))" | |
| Log "FAIL: Resolve failed $name : $($_.Exception.Message)" | |
| } | |
| } | |
| if ($dnsFail -eq 0) { | |
| Write-Status PASS "DNS resolution looks OK." | |
| Log "PASS: DNS resolution looks OK." | |
| } else { | |
| Write-Status FAIL "DNS failures detected: $dnsFail" | |
| Log "FAIL: DNS failures detected: $dnsFail" | |
| } | |
| Log "`r`n--- DNS servers ---" | |
| Log ((Get-DnsClientServerAddress | Out-String)) | |
| } | |
| # ---------- TCP 443 ---------- | |
| Write-Section "TCP 443" | |
| Safe "TCP tests" { | |
| $tcpFail = 0 | |
| foreach ($h in $TcpTestHosts) { | |
| try { | |
| $t = Test-NetConnection -ComputerName $h -Port $TcpTestPort -WarningAction SilentlyContinue | |
| if ($t.TcpTestSucceeded) { | |
| Write-Status PASS "TCP ${h}:$TcpTestPort succeeded (Source: $($t.SourceAddress) via $($t.InterfaceAlias))" | |
| Log "PASS: TCP ${h}:$TcpTestPort succeeded" | |
| } else { | |
| $tcpFail++ | |
| Write-Status FAIL "TCP ${h}:$TcpTestPort FAILED (Ping: $($t.PingSucceeded))" | |
| Log "FAIL: TCP ${h}:$TcpTestPort FAILED (Ping: $($t.PingSucceeded))" | |
| } | |
| Log "`r`n--- Test-NetConnection ${h}:$TcpTestPort ---" | |
| Log (($t | Out-String)) | |
| } catch { | |
| $tcpFail++ | |
| Write-Status FAIL "TCP test error for ${h}:$TcpTestPort : $($_.Exception.Message)" | |
| Log "FAIL: TCP test error for ${h}:$TcpTestPort : $($_.Exception.Message)" | |
| } | |
| } | |
| if ($tcpFail -eq 0) { | |
| Write-Status PASS "Outbound TCP 443 looks OK." | |
| Log "PASS: Outbound TCP 443 looks OK." | |
| } else { | |
| Write-Status FAIL "TCP 443 failures detected: $tcpFail" | |
| Log "FAIL: TCP 443 failures detected: $tcpFail" | |
| } | |
| } | |
| # ---------- HTTP/HTTPS ---------- | |
| Write-Section "HTTP/HTTPS" | |
| Safe "HTTP tests" { | |
| $httpFail = 0 | |
| foreach ($u in $HttpTestUrls) { | |
| try { | |
| $resp = Invoke-WebRequest -Uri $u -UseBasicParsing -TimeoutSec 15 -ErrorAction Stop | |
| Write-Status PASS "GET $u -> $($resp.StatusCode) (Len: $($resp.RawContentLength))" | |
| Log "PASS: GET $u -> $($resp.StatusCode) (Len: $($resp.RawContentLength))" | |
| } catch { | |
| $httpFail++ | |
| Write-Status FAIL "GET failed $u : $($_.Exception.Message)" | |
| Log "FAIL: GET failed $u : $($_.Exception.Message)" | |
| } | |
| } | |
| if ($httpFail -eq 0) { | |
| Write-Status PASS "HTTP/HTTPS fetch looks OK." | |
| Log "PASS: HTTP/HTTPS fetch looks OK." | |
| } else { | |
| Write-Status FAIL "HTTP/HTTPS failures detected: $httpFail" | |
| Log "FAIL: HTTP/HTTPS failures detected: $httpFail" | |
| } | |
| } | |
| # ---------- VPN-ish adapters ---------- | |
| Write-Section "VPN Indicators" | |
| Safe "VPN adapters" { | |
| $vpn = Get-NetAdapter | Where-Object { | |
| $_.InterfaceDescription -match "VPN|Virtual|TAP|TUN|WireGuard|AnyConnect|Forti|Pulse|GlobalProtect|Zscaler|Netskope" | |
| } | |
| if ($vpn) { | |
| Write-Status WARN ("VPN/Virtual adapters detected: " + ($vpn.Name -join ", ")) | |
| Log "WARN: VPN/Virtual adapters detected: $($vpn.Name -join ", ")" | |
| } else { | |
| Write-Status PASS "No obvious VPN/virtual adapters detected." | |
| Log "PASS: No obvious VPN/virtual adapters detected." | |
| } | |
| Log "`r`n--- VPN adapter list ---" | |
| Log (($vpn | Format-Table -Auto | Out-String)) | |
| } | |
| # ---------- save + print ---------- | |
| Write-Section "Save Report" | |
| $reportText = ($log -join "`r`n") | |
| $reportText | Out-File -FilePath $reportPath -Encoding UTF8 | |
| Write-Status INFO "Report saved to: $reportPath" | |
| Write-Host "`n---- FULL REPORT (also saved) ----" -ForegroundColor DarkGray | |
| Write-Output $reportText | |
| # Open in Notepad for easy sharing | |
| $reportText | Tee-Object -FilePath $reportPath |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment