@@ -501,6 +501,135 @@ function Test-Network {
501501 } catch {
502502 Write-Host " Error getting network info" - ForegroundColor Red
503503 }
504+
505+ Test-NetworkSpeed
506+ Test-NetworkLatency
507+ }
508+
509+ function Test-NetworkSpeed {
510+ Write-Host " `n === Network Speed Test ===" - ForegroundColor Green
511+
512+ $outputLines = @ ()
513+ $status = " SUCCESS"
514+ $durationMs = 0
515+
516+ # Gather link speed information for active adapters
517+ try {
518+ $adapters = Get-NetAdapter - ErrorAction Stop | Where-Object { $_.Status -eq " Up" }
519+ if ($adapters ) {
520+ $outputLines += " Active Link Speeds:"
521+ foreach ($adapter in $adapters ) {
522+ $outputLines += " $ ( $adapter.Name ) : $ ( $adapter.LinkSpeed ) "
523+ }
524+ } else {
525+ $outputLines += " Active Link Speeds: No active adapters detected"
526+ }
527+ } catch {
528+ $status = " FAILED"
529+ $outputLines += " Active Link Speeds: Unable to query adapters ($ ( $_.Exception.Message ) )"
530+ }
531+
532+ # Perform an outbound download test to estimate internet throughput
533+ $tempFile = $null
534+ try {
535+ $testUrl = " https://speed.hetzner.de/10MB.bin"
536+ $tempFile = [System.IO.Path ]::GetTempFileName()
537+ Write-Host " Running internet download test (~10MB)..." - ForegroundColor Yellow
538+ $stopwatch = [System.Diagnostics.Stopwatch ]::StartNew()
539+ Invoke-WebRequest - Uri $testUrl - OutFile $tempFile - UseBasicParsing - TimeoutSec 120 | Out-Null
540+ $stopwatch.Stop ()
541+
542+ $fileInfo = Get-Item $tempFile
543+ $sizeBytes = [double ]$fileInfo.Length
544+ $duration = [math ]::Max($stopwatch.Elapsed.TotalSeconds , 0.001 )
545+ $sizeMB = [math ]::Round($sizeBytes / 1 MB , 2 )
546+ $mbps = [math ]::Round((($sizeBytes * 8 ) / 1 MB ) / $duration , 2 )
547+ $mbPerSec = [math ]::Round(($sizeBytes / 1 MB ) / $duration , 2 )
548+
549+ $outputLines += " Internet Download Test:"
550+ $outputLines += " URL: $testUrl "
551+ $outputLines += " File Size: $sizeMB MB"
552+ $outputLines += " Time: $ ( [math ]::Round($duration , 2 )) sec"
553+ $outputLines += " Throughput: $mbps Mbps ($mbPerSec MB/s)"
554+ $durationMs = [math ]::Round($stopwatch.Elapsed.TotalMilliseconds )
555+ } catch {
556+ if ($status -ne " FAILED" ) { $status = " FAILED" }
557+ $outputLines += " Internet Download Test: Failed - $ ( $_.Exception.Message ) "
558+ } finally {
559+ if ($tempFile -and (Test-Path $tempFile )) {
560+ Remove-Item $tempFile - ErrorAction SilentlyContinue
561+ }
562+ }
563+
564+ $script :TestResults += @ {
565+ Tool = " Network-SpeedTest" ; Description = " Local link speed and download throughput"
566+ Status = $status ; Output = ($outputLines -join " `n " ); Duration = $durationMs
567+ }
568+ }
569+
570+ function Test-NetworkLatency {
571+ Write-Host " `n === Network Latency (Test-NetConnection & PsPing) ===" - ForegroundColor Green
572+
573+ $targetHost = " 8.8.8.8"
574+ $targetPort = 443
575+ $lines = @ (" Target: $targetHost :$targetPort " )
576+ $status = " SUCCESS"
577+
578+ # Built-in Test-NetConnection results
579+ try {
580+ $tnc = Test-NetConnection - ComputerName $targetHost - Port $targetPort - InformationLevel Detailed
581+ if ($tnc ) {
582+ $lines += " Test-NetConnection:"
583+ $lines += " Ping Succeeded: $ ( $tnc.PingSucceeded ) "
584+ if ($tnc.PingReplyDetails ) {
585+ $lines += " Ping RTT: $ ( $tnc.PingReplyDetails.RoundtripTime ) ms"
586+ }
587+ $lines += " TCP Succeeded: $ ( $tnc.TcpTestSucceeded ) "
588+ }
589+ } catch {
590+ $status = " FAILED"
591+ $lines += " Test-NetConnection: Failed - $ ( $_.Exception.Message ) "
592+ }
593+
594+ # Sysinternals PsPing results
595+ try {
596+ $pspingPath = Join-Path $SysinternalsPath " psping.exe"
597+ if (Test-Path $pspingPath ) {
598+ $args = @ (" -accepteula" , " -n" , " 5" , " $targetHost :$targetPort " )
599+ Write-Host " Running PsPing latency test..." - ForegroundColor Yellow
600+ $pspingOutput = & $pspingPath $args 2>&1 | Out-String
601+ $lines += " PsPing Summary:"
602+
603+ $average = $null
604+ $minimum = $null
605+ $maximum = $null
606+ foreach ($line in $pspingOutput -split " `r ?`n " ) {
607+ if ($line -match " Minimum = ([\d\.]+)ms, Maximum = ([\d\.]+)ms, Average = ([\d\.]+)ms" ) {
608+ $minimum = [double ]$matches [1 ]
609+ $maximum = [double ]$matches [2 ]
610+ $average = [double ]$matches [3 ]
611+ }
612+ }
613+
614+ if ($average -ne $null ) {
615+ $lines += " Min: $minimum ms"
616+ $lines += " Max: $maximum ms"
617+ $lines += " Avg: $average ms"
618+ } else {
619+ $lines += " Unable to parse latency results"
620+ }
621+ } else {
622+ $lines += " PsPing Summary: psping.exe not found in Sysinternals folder"
623+ }
624+ } catch {
625+ $status = " FAILED"
626+ $lines += " PsPing Summary: Failed - $ ( $_.Exception.Message ) "
627+ }
628+
629+ $script :TestResults += @ {
630+ Tool = " Network-Latency" ; Description = " Connectivity latency tests"
631+ Status = $status ; Output = ($lines -join " `n " ); Duration = 0
632+ }
504633}
505634
506635# Test: OS Health
@@ -1067,7 +1196,24 @@ function Test-WindowsUpdate {
10671196
10681197 try {
10691198 $result = $searcher.Search (" IsInstalled=0" )
1070- $lines += " Pending: $ ( $result.Updates.Count ) "
1199+ $pendingCount = $result.Updates.Count
1200+ $lines += " Pending: $pendingCount "
1201+
1202+ if ($pendingCount -gt 0 ) {
1203+ $lines += " Pending Updates:"
1204+ $maxList = 10
1205+ for ($i = 0 ; $i -lt [math ]::Min($pendingCount , $maxList ); $i ++ ) {
1206+ $update = $result.Updates.Item ($i )
1207+ $classification = ($update.Categories | Select-Object - First 1 ).Name
1208+ if (-not $classification ) { $classification = " Unspecified" }
1209+ $lines += " - $ ( $update.Title ) [$classification ]"
1210+ }
1211+ if ($pendingCount -gt $maxList ) {
1212+ $lines += " ... ($ ( $pendingCount - $maxList ) additional updates not listed)"
1213+ }
1214+ } else {
1215+ $lines += " Pending Updates: None"
1216+ }
10711217 } catch {
10721218 $lines += " Search failed: $ ( $_.Exception.Message ) "
10731219 }
@@ -1171,6 +1317,27 @@ function Generate-Report {
11711317 }
11721318 }
11731319
1320+ $netSpeed = $TestResults | Where-Object {$_.Tool -eq " Network-SpeedTest" } | Select-Object - Last 1
1321+ if ($netSpeed ) {
1322+ $cleanReport += " "
1323+ $cleanReport += " NETWORK SPEED:"
1324+ $netSpeed.Output -split " `n " | ForEach-Object { $cleanReport += " $_ " }
1325+ }
1326+
1327+ $netLatency = $TestResults | Where-Object {$_.Tool -eq " Network-Latency" } | Select-Object - Last 1
1328+ if ($netLatency ) {
1329+ $cleanReport += " "
1330+ $cleanReport += " NETWORK LATENCY:"
1331+ $netLatency.Output -split " `n " | ForEach-Object { $cleanReport += " $_ " }
1332+ }
1333+
1334+ $updateInfo = $TestResults | Where-Object {$_.Tool -eq " Windows-Update" } | Select-Object - Last 1
1335+ if ($updateInfo ) {
1336+ $cleanReport += " "
1337+ $cleanReport += " WINDOWS UPDATE:"
1338+ $updateInfo.Output -split " `n " | ForEach-Object { $cleanReport += " $_ " }
1339+ }
1340+
11741341 # ========================================
11751342 # ENHANCED RECOMMENDATIONS ENGINE
11761343 # ========================================
@@ -1228,6 +1395,34 @@ function Generate-Report {
12281395 }
12291396 }
12301397
1398+ # === NETWORK PERFORMANCE ===
1399+ if ($netSpeed -and $netSpeed.Output -match " Throughput: ([\d\.]+) Mbps" ) {
1400+ $throughputMbps = [float ]$matches [1 ]
1401+ if ($throughputMbps -lt 25 ) {
1402+ $recommendations += " • WARNING: Internet throughput appears slow ($throughputMbps Mbps)"
1403+ $recommendations += " → Verify ISP plan and router performance"
1404+ $recommendations += " → Re-test when fewer applications are consuming bandwidth"
1405+ }
1406+ }
1407+
1408+ if ($netLatency -and $netLatency.Output -match " Avg: ([\d\.]+) ms" ) {
1409+ $avgLatency = [float ]$matches [1 ]
1410+ if ($avgLatency -gt 100 ) {
1411+ $recommendations += " • NOTICE: High network latency detected (Avg $avgLatency ms)"
1412+ $recommendations += " → Check local network congestion"
1413+ $recommendations += " → Contact ISP if latency persists"
1414+ }
1415+ }
1416+
1417+ if ($updateInfo -and $updateInfo.Output -match " Pending: (\d+)" ) {
1418+ $pendingUpdates = [int ]$matches [1 ]
1419+ if ($pendingUpdates -gt 0 ) {
1420+ $recommendations += " • ACTION: $pendingUpdates Windows update(s) pending installation"
1421+ $recommendations += " → Install updates via Settings > Windows Update"
1422+ $recommendations += " → Reboot system after installation completes"
1423+ }
1424+ }
1425+
12311426 # === STORAGE CAPACITY ===
12321427 $storageInfo = $TestResults | Where-Object {$_.Tool -eq " Storage-Overview" }
12331428 if ($storageInfo ) {
0 commit comments