1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
| function Invoke-FullSystemDiagnostic { [CmdletBinding()] param( [string]$OutputPath = "$env:TEMP\SystemDiagnosticReport.html", [double]$CpuThreshold = 80, [double]$MemoryThreshold = 85, [double]$DiskThreshold = 90 )
Write-Host "开始全量系统诊断..." -ForegroundColor Cyan $diagStart = Get-Date
Write-Host " [1/4] 采集硬件指标..." -ForegroundColor Gray $os = Get-CimInstance -ClassName Win32_OperatingSystem $cpuSample = (Get-Counter -Counter '\Processor(_Total)\% Processor Time' -SampleInterval 1 -MaxSamples 3).CounterSamples $cpuAvg = [math]::Round(($cpuSample | Measure-Object -Property CookedValue -Average).Average, 2) $memUsedPercent = [math]::Round(($os.TotalVisibleMemorySize - $os.FreePhysicalMemory) / $os.TotalVisibleMemorySize * 100, 2) $disks = Get-CimInstance -ClassName Win32_LogicalDisk -Filter 'DriveType=3'
Write-Host " [2/4] 检查服务状态..." -ForegroundColor Gray $criticalSvcs = @('WinRM', 'EventLog', 'LanmanServer', 'LanmanWorkstation', 'Schedule') $svcResults = foreach ($name in $criticalSvcs) { $s = Get-Service -Name $name -ErrorAction SilentlyContinue @{ Name = $name; Status = if ($s) { $s.Status.ToString() } else { 'NotFound' } } }
Write-Host " [3/4] 扫描事件日志..." -ForegroundColor Gray $startTime = (Get-Date).AddHours(-24) $errors = @(Get-WinEvent -FilterHashtable @{ LogName = 'System'; Level = 2; StartTime = $startTime } -MaxEvents 100 -ErrorAction SilentlyContinue) $warnings = @(Get-WinEvent -FilterHashtable @{ LogName = 'System'; Level = 3; StartTime = $startTime } -MaxEvents 100 -ErrorAction SilentlyContinue)
Write-Host " [4/4] 计算健康评分..." -ForegroundColor Gray
$score = 100
$cpuDeduction = [math]::Min(20, [math]::Max(0, ($cpuAvg - $CpuThreshold) * 0.5)) $score -= $cpuDeduction
$memDeduction = [math]::Min(20, [math]::Max(0, ($memUsedPercent - $MemoryThreshold) * 0.5)) $score -= $memDeduction
foreach ($disk in $disks) { $diskUsedPercent = [math]::Round(($disk.Size - $disk.FreeSpace) / $disk.Size * 100, 2) if ($diskUsedPercent -gt $DiskThreshold) { $score -= [math]::Min(10, [math]::Max(0, ($diskUsedPercent - $DiskThreshold) * 0.3)) } }
$stoppedSvcs = @($svcResults | Where-Object { $_.Status -ne 'Running' }) $svcDeduction = [math]::Min(25, $stoppedSvcs.Count * 5) $score -= $svcDeduction
$logDeduction = [math]::Min(15, [math]::Round($errors.Count / 5, 0)) $score -= $logDeduction
$score = [math]::Max(0, [math]::Round($score, 0))
$overallStatus = if ($score -ge 80) { 'Healthy' } elseif ($score -ge 50) { 'Warning' } else { 'Critical' }
$diagDuration = [math]::Round(((Get-Date) - $diagStart).TotalSeconds, 1)
$html = @" <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>系统诊断报告 - $($env:COMPUTERNAME) - $(Get-Date -Format 'yyyy-MM-dd')</title> <style> body { font-family: 'Segoe UI', sans-serif; margin: 20px; background: #f5f5f5; } .container { max-width: 960px; margin: auto; background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } h1 { color: #0078d4; border-bottom: 2px solid #0078d4; padding-bottom: 10px; } .score { font-size: 48px; font-weight: bold; text-align: center; padding: 20px; } .score.healthy { color: #107c10; } .score.warning { color: #ff8c00; } .score.critical { color: #d13438; } table { width: 100%; border-collapse: collapse; margin: 10px 0; } th, td { border: 1px solid #ddd; padding: 8px 12px; text-align: left; } th { background: #0078d4; color: white; } tr:nth-child(even) { background: #f9f9f9; } .badge { padding: 3px 8px; border-radius: 4px; font-size: 12px; font-weight: bold; } .badge-ok { background: #dff6dd; color: #107c10; } .badge-warn { background: #fff4ce; color: #ff8c00; } .badge-error { background: #fde7e9; color: #d13438; } </style> </head> <body> <div class="container"> <h1>系统诊断报告</h1> <p>计算机: <strong>$($env:COMPUTERNAME)</strong> | 生成时间: <strong>$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')</strong> | 耗时: ${diagDuration}s</p> <div class="score $overallStatus.ToLowerInvariant()">$score / 100</div> <p style="text-align:center; font-size:18px;">总体状态: <strong>$overallStatus</strong></p>
<h2>CPU 使用率</h2> <p>平均使用率: <strong>${cpuAvg}%</strong> (阈值: ${CpuThreshold}%)</p>
<h2>内存使用率</h2> <p>已用: <strong>${memUsedPercent}%</strong> (阈值: ${MemoryThreshold}%)</p>
<h2>磁盘空间</h2> <table> <tr><th>驱动器</th><th>总容量</th><th>可用空间</th><th>可用百分比</th></tr> $(foreach ($d in $disks) { $freePct = [math]::Round($d.FreeSpace / $d.Size * 100, 2) $badge = if ($freePct -gt 20) { 'badge-ok' } elseif ($freePct -gt 10) { 'badge-warn' } else { 'badge-error' } "<tr><td>$($d.DeviceID)</td><td>$([math]::Round($d.Size/1GB,2)) GB</td><td>$([math]::Round($d.FreeSpace/1GB,2)) GB</td><td><span class=`"badge $badge`">${freePct}%</span></td></tr>" })
<h2>关键服务状态</h2> <table> <tr><th>服务名</th><th>状态</th></tr> $(foreach ($s in $svcResults) { $badge = if ($s.Status -eq 'Running') { 'badge-ok' } else { 'badge-error' } "<tr><td>$($s.Name)</td><td><span class=`"badge $badge`">$($s.Status)</span></td></tr>" })
<h2>事件日志摘要(最近 24 小时)</h2> <p>错误: <strong>$($errors.Count)</strong> 条 | 警告: <strong>$($warnings.Count)</strong> 条</p>
</div> </body> </html> "@
$html | Out-File -FilePath $OutputPath -Encoding UTF8 -Force Write-Host "诊断完成!健康评分: $score / 100 [$overallStatus]" -ForegroundColor $(if ($overallStatus -eq 'Healthy') { 'Green' } elseif ($overallStatus -eq 'Warning') { 'Yellow' } else { 'Red' }) Write-Host "HTML 报告已保存至: $OutputPath" -ForegroundColor Cyan
return [PSCustomObject]@{ ComputerName = $env:COMPUTERNAME Score = $score Status = $overallStatus CpuUsage = "$cpuAvg%" MemoryUsage = "$memUsedPercent%" Errors24h = $errors.Count Warnings24h = $warnings.Count ReportPath = $OutputPath } }
$report = Invoke-FullSystemDiagnostic -OutputPath "$env:TEMP\SystemDiagnosticReport.html" $report
|