Skip to content

Instantly share code, notes, and snippets.

@asw456
Created June 17, 2026 08:13
Show Gist options
  • Select an option

  • Save asw456/b274bd8fcc582c91eec5d8e64bf3b038 to your computer and use it in GitHub Desktop.

Select an option

Save asw456/b274bd8fcc582c91eec5d8e64bf3b038 to your computer and use it in GitHub Desktop.
# MemoryHealthReport.ps1
# Read-only memory / ECC / WHEA health report for Windows.
# Safe to run: does not change settings, install software, or reboot.
param(
[int]$DaysBack = 30,
[int]$MaxWheaEventsToRead = 20000
)
$ErrorActionPreference = "Continue"
$Report = New-Object System.Collections.Generic.List[string]
$Findings = New-Object System.Collections.Generic.List[string]
function Add-Line {
param([string]$Text = "")
$script:Report.Add($Text)
Write-Host $Text
}
function Add-Block {
param([string]$Text)
if ($null -eq $Text) { return }
foreach ($line in ($Text -split "`r?`n")) {
Add-Line $line
}
}
function Section {
param([string]$Title)
Add-Line ""
Add-Line ("=" * 78)
Add-Line $Title
Add-Line ("=" * 78)
}
function Safe-Run {
param(
[string]$Name,
[scriptblock]$Script
)
try {
& $Script
}
catch {
Add-Line "WARNING: Could not collect $Name"
Add-Line ("Reason: " + $_.Exception.Message)
$script:Findings.Add("Could not collect $Name: $($_.Exception.Message)")
return $null
}
}
function Bytes-ToGB {
param($Bytes)
if ($null -eq $Bytes -or $Bytes -eq 0) { return "Unknown" }
return ("{0:N2} GB" -f ([double]$Bytes / 1GB))
}
function KB-ToGB {
param($KB)
if ($null -eq $KB -or $KB -eq 0) { return "Unknown" }
return ("{0:N2} GB" -f ([double]$KB / 1MB))
}
function Trim-Value {
param($Value)
if ($null -eq $Value) { return "" }
return (($Value | Out-String).Trim())
}
function Get-Prop {
param($Object, [string]$Name)
if ($null -eq $Object) { return $null }
if ($Object.PSObject.Properties.Name -contains $Name) {
return $Object.$Name
}
return $null
}
function Add-Table {
param($Objects)
if ($null -eq $Objects) {
Add-Line "(none)"
return
}
$array = @($Objects)
if ($array.Count -eq 0) {
Add-Line "(none)"
return
}
Add-Block ($array | Format-Table -AutoSize | Out-String -Width 240)
}
function Add-List {
param($Object)
if ($null -eq $Object) {
Add-Line "(none)"
return
}
Add-Block ($Object | Format-List | Out-String -Width 240)
}
function Get-WheaSummary {
param([string]$Message)
if ([string]::IsNullOrWhiteSpace($Message)) {
return "(no message text)"
}
$lines = $Message -split "`r?`n" |
ForEach-Object { $_.Trim() } |
Where-Object { $_ -ne "" }
$important = $lines | Where-Object {
$_ -match "(?i)^(A .*hardware.*error|A .*memory.*error|Component:|Error Source:|Error Type:|Processor APIC ID:|Bank:|Device:|Physical Address:|Node:|Card:|Module:|Channel:|DIMM:|Rank:|Row:|Column:|FRU)"
} | Select-Object -First 10
if (@($important).Count -eq 0) {
$important = $lines | Select-Object -First 4
}
return (($important -join " | ") -replace "\s+", " ")
}
function Is-MemoryWheaMessage {
param([string]$Message)
if ([string]::IsNullOrWhiteSpace($Message)) {
return $false
}
return ($Message -match "(?i)\b(Component:\s*Memory|Memory Hierarchy|DIMM|DRAM|Channel|Rank|Bank|Row|Column|Physical Address)\b")
}
function Is-CorrectedMessage {
param([string]$Message)
if ([string]::IsNullOrWhiteSpace($Message)) {
return $false
}
return ($Message -match "(?i)\bcorrected hardware error\b|\bCorrected Machine Check\b")
}
function Is-FatalOrUncorrectedMessage {
param([string]$Message)
if ([string]::IsNullOrWhiteSpace($Message)) {
return $false
}
return ($Message -match "(?i)\bfatal\b|\buncorrected\b|\bnot corrected\b")
}
$ECCCorrectionMap = @{
0 = "Reserved"
1 = "Other"
2 = "Unknown"
3 = "None"
4 = "Parity"
5 = "Single-bit ECC"
6 = "Multi-bit ECC"
7 = "CRC"
}
$ArrayUseMap = @{
0 = "Reserved"
1 = "Other"
2 = "Unknown"
3 = "System memory"
4 = "Video memory"
5 = "Flash memory"
6 = "Non-volatile RAM"
7 = "Cache memory"
}
$FormFactorMap = @{
0 = "Unknown"
1 = "Other"
2 = "SIP"
3 = "DIP"
4 = "ZIP"
5 = "SOJ"
6 = "Proprietary"
7 = "SIMM"
8 = "DIMM"
9 = "TSOP"
10 = "PGA"
11 = "RIMM"
12 = "SODIMM"
13 = "SRIMM"
14 = "SMD"
15 = "SSMP"
16 = "QFP"
17 = "TQFP"
18 = "SOIC"
19 = "LCC"
20 = "PLCC"
21 = "BGA"
22 = "FPBGA"
23 = "LGA"
}
$MemoryTypeMap = @{
0 = "Unknown"
1 = "Other"
2 = "DRAM"
3 = "Synchronous DRAM"
4 = "Cache DRAM"
5 = "EDO"
6 = "EDRAM"
7 = "VRAM"
8 = "SRAM"
9 = "RAM"
10 = "ROM"
11 = "Flash"
12 = "EEPROM"
13 = "FEPROM"
14 = "EPROM"
15 = "CDRAM"
16 = "3DRAM"
17 = "SDRAM"
18 = "SGRAM"
19 = "RDRAM"
20 = "DDR"
21 = "DDR2"
22 = "DDR2 FB-DIMM"
24 = "DDR3"
25 = "FBD2"
26 = "DDR4"
27 = "LPDDR"
28 = "LPDDR2"
29 = "LPDDR3"
30 = "LPDDR4"
31 = "Logical non-volatile device"
34 = "DDR5"
35 = "LPDDR5"
}
$StartTime = (Get-Date).AddDays(-1 * $DaysBack)
$Now = Get-Date
$ComputerName = $env:COMPUTERNAME
$Timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
$Desktop = [Environment]::GetFolderPath("Desktop")
if ([string]::IsNullOrWhiteSpace($Desktop) -or -not (Test-Path $Desktop)) {
$Desktop = $env:TEMP
}
$OutputFile = Join-Path $Desktop ("MemoryHealthReport_{0}_{1}.txt" -f $ComputerName, $Timestamp)
Section "Memory Health Report - Summary"
Add-Line ("Generated: {0}" -f (Get-Date -Format "yyyy-MM-dd HH:mm:ss zzz"))
Add-Line ("Computer: {0}" -f $ComputerName)
Add-Line ("User: {0}\{1}" -f $env:USERDOMAIN, $env:USERNAME)
Add-Line ("Lookback: Last {0} day(s) for recent event counts" -f $DaysBack)
Add-Line ("Note: This report is read-only.")
$Identity = [Security.Principal.WindowsIdentity]::GetCurrent()
$Principal = New-Object Security.Principal.WindowsPrincipal($Identity)
$IsAdmin = $Principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
Add-Line ("Running as Administrator: {0}" -f $IsAdmin)
if (-not $IsAdmin) {
$Findings.Add("PowerShell was not run as Administrator. Some event log details may be missing.")
}
Section "System Information"
$CS = Safe-Run "Computer system information" { Get-CimInstance Win32_ComputerSystem }
$OS = Safe-Run "Operating system information" { Get-CimInstance Win32_OperatingSystem }
$BIOS = Safe-Run "BIOS information" { Get-CimInstance Win32_BIOS }
$BaseBoard = Safe-Run "Baseboard information" { Get-CimInstance Win32_BaseBoard }
$CPU = Safe-Run "CPU information" { Get-CimInstance Win32_Processor | Select-Object -First 1 }
if ($OS) {
$Boot = $OS.LastBootUpTime
$Uptime = $Now - $Boot
}
else {
$Boot = $null
$Uptime = $null
}
$SystemInfo = [PSCustomObject]@{
Manufacturer = Trim-Value $CS.Manufacturer
Model = Trim-Value $CS.Model
"System Type" = Trim-Value $CS.SystemType
"Total RAM Visible" = Bytes-ToGB $CS.TotalPhysicalMemory
OS = (Trim-Value $OS.Caption)
"OS Version" = (Trim-Value $OS.Version)
"OS Build" = (Trim-Value $OS.BuildNumber)
"Last Boot" = $Boot
Uptime = if ($Uptime) { "{0} days, {1} hours, {2} minutes" -f $Uptime.Days, $Uptime.Hours, $Uptime.Minutes } else { "Unknown" }
BIOS = (Trim-Value $BIOS.SMBIOSBIOSVersion)
"BIOS Release Date" = $BIOS.ReleaseDate
Baseboard = ("{0} {1}" -f (Trim-Value $BaseBoard.Manufacturer), (Trim-Value $BaseBoard.Product)).Trim()
CPU = (Trim-Value $CPU.Name)
}
Add-List $SystemInfo
Section "Memory Array / ECC Capability From SMBIOS"
$Arrays = Safe-Run "Physical memory array information" { Get-CimInstance Win32_PhysicalMemoryArray }
$ArrayRows = @()
foreach ($a in @($Arrays)) {
$memErrCode = [int](Get-Prop $a "MemoryErrorCorrection")
$useCode = [int](Get-Prop $a "Use")
$memErrText = if ($ECCCorrectionMap.ContainsKey($memErrCode)) { $ECCCorrectionMap[$memErrCode] } else { "Unknown code $memErrCode" }
$useText = if ($ArrayUseMap.ContainsKey($useCode)) { $ArrayUseMap[$useCode] } else { "Unknown code $useCode" }
$maxCapExKB = Get-Prop $a "MaxCapacityEx"
$maxCapKB = Get-Prop $a "MaxCapacity"
$maxText = "Unknown"
if ($maxCapExKB -and $maxCapExKB -gt 0) {
$maxText = KB-ToGB $maxCapExKB
}
elseif ($maxCapKB -and $maxCapKB -gt 0) {
$maxText = KB-ToGB $maxCapKB
}
$ArrayRows += [PSCustomObject]@{
Location = Trim-Value $a.Location
Use = $useText
"Memory Error Correction"= $memErrText
"Slots/Sockets" = $a.MemoryDevices
"Max Capacity" = $maxText
}
}
Add-Table $ArrayRows
$ECCArrayText = ($ArrayRows | Select-Object -ExpandProperty "Memory Error Correction" -ErrorAction SilentlyContinue) -join ", "
if ($ECCArrayText -match "Single-bit ECC|Multi-bit ECC") {
$Findings.Add("SMBIOS reports ECC-capable memory array: $ECCArrayText")
}
elseif ($ECCArrayText -match "None") {
$Findings.Add("SMBIOS reports no memory error correction on at least one memory array.")
}
elseif ($ECCArrayText -match "Unknown|Other|Reserved" -or [string]::IsNullOrWhiteSpace($ECCArrayText)) {
$Findings.Add("SMBIOS memory error correction status is unknown or not clearly reported.")
}
Section "Installed DIMMs / Memory Modules"
$Modules = Safe-Run "Installed physical memory modules" {
Get-CimInstance Win32_PhysicalMemory | Sort-Object BankLabel, DeviceLocator
}
$ModuleRows = @()
foreach ($m in @($Modules)) {
$dataWidth = Get-Prop $m "DataWidth"
$totalWidth = Get-Prop $m "TotalWidth"
$extraBits = $null
$eccVisible = "Unknown"
if ($null -ne $dataWidth -and $null -ne $totalWidth -and $dataWidth -gt 0 -and $totalWidth -gt 0) {
$extraBits = [int]$totalWidth - [int]$dataWidth
if ($extraBits -gt 0) {
$eccVisible = "Yes - $extraBits extra check bit(s)"
}
elseif ($extraBits -eq 0) {
$eccVisible = "No extra check bits visible"
}
else {
$eccVisible = "Unexpected width values"
}
}
$ffCode = [int](Get-Prop $m "FormFactor")
$memTypeCode = [int](Get-Prop $m "SMBIOSMemoryType")
if (-not $memTypeCode) {
$memTypeCode = [int](Get-Prop $m "MemoryType")
}
$ffText = if ($FormFactorMap.ContainsKey($ffCode)) { $FormFactorMap[$ffCode] } else { "Unknown code $ffCode" }
$memTypeText = if ($MemoryTypeMap.ContainsKey($memTypeCode)) { $MemoryTypeMap[$memTypeCode] } else { "Unknown code $memTypeCode" }
$speed = Get-Prop $m "ConfiguredClockSpeed"
if (-not $speed) { $speed = Get-Prop $m "Speed" }
$voltage = Get-Prop $m "ConfiguredVoltage"
if ($voltage) {
$voltageText = "$voltage mV"
}
else {
$voltageText = ""
}
$ModuleRows += [PSCustomObject]@{
Slot = Trim-Value $m.DeviceLocator
Bank = Trim-Value $m.BankLabel
Capacity = Bytes-ToGB $m.Capacity
Manufacturer = Trim-Value $m.Manufacturer
PartNumber = Trim-Value $m.PartNumber
SerialNumber = Trim-Value $m.SerialNumber
Type = $memTypeText
FormFactor = $ffText
Speed = if ($speed) { "$speed MT/s" } else { "" }
Voltage = $voltageText
DataWidth = $dataWidth
TotalWidth = $totalWidth
"ECC Bits Visible"= $eccVisible
}
}
Add-Table $ModuleRows
$InstalledCount = @($Modules).Count
$SlotCount = 0
foreach ($a in @($Arrays)) {
if ($a.MemoryDevices) {
$SlotCount += [int]$a.MemoryDevices
}
}
Add-Line ("Installed memory module count: {0}" -f $InstalledCount)
if ($SlotCount -gt 0) {
Add-Line ("Reported physical memory slots/sockets: {0}" -f $SlotCount)
}
$AnyExtraBits = @($ModuleRows | Where-Object { $_."ECC Bits Visible" -match "^Yes" }).Count
$AnyNoExtraBits = @($ModuleRows | Where-Object { $_."ECC Bits Visible" -match "^No extra" }).Count
if ($AnyExtraBits -gt 0) {
$Findings.Add("At least one DIMM reports extra check bits through TotalWidth > DataWidth.")
}
elseif ($InstalledCount -gt 0 -and $AnyNoExtraBits -eq $InstalledCount) {
$Findings.Add("Installed DIMMs do not show extra ECC/check bits through TotalWidth/DataWidth.")
}
else {
$Findings.Add("DIMM width data was inconclusive for ECC bit visibility.")
}
Section "WHEA Hardware Error Log Summary"
Add-Line ("Reading Microsoft-Windows-WHEA-Logger events from the System log.")
Add-Line ("Maximum WHEA events read: {0}. If there are more than this, counts may be capped." -f $MaxWheaEventsToRead)
$WheaEvents = Safe-Run "WHEA-Logger events" {
Get-WinEvent -FilterHashtable @{
LogName = "System"
ProviderName = "Microsoft-Windows-WHEA-Logger"
} -MaxEvents $MaxWheaEventsToRead -ErrorAction Stop
}
$WheaEvents = @($WheaEvents)
$WheaRecent = @($WheaEvents | Where-Object { $_.TimeCreated -ge $StartTime })
$WheaMemory = @($WheaEvents | Where-Object { Is-MemoryWheaMessage $_.Message })
$WheaMemoryRecent = @($WheaMemory | Where-Object { $_.TimeCreated -ge $StartTime })
$WheaMemory24h = @($WheaMemory | Where-Object { $_.TimeCreated -ge $Now.AddHours(-24) })
$WheaMemory7d = @($WheaMemory | Where-Object { $_.TimeCreated -ge $Now.AddDays(-7) })
$WheaMemoryCorrected = @($WheaMemory | Where-Object { Is-CorrectedMessage $_.Message })
$WheaMemoryCorrectedRecent = @($WheaMemoryRecent | Where-Object { Is-CorrectedMessage $_.Message })
$WheaMemoryFatal = @($WheaMemory | Where-Object { Is-FatalOrUncorrectedMessage $_.Message })
$WheaMemoryFatalRecent = @($WheaMemoryRecent | Where-Object { Is-FatalOrUncorrectedMessage $_.Message })
if ($WheaEvents.Count -eq 0) {
Add-Line "No WHEA-Logger events found in the current System event log."
}
else {
$OldestWhea = $WheaEvents | Sort-Object TimeCreated | Select-Object -First 1
$NewestWhea = $WheaEvents | Sort-Object TimeCreated -Descending | Select-Object -First 1
Add-Line ("Total WHEA-Logger events read: {0}" -f $WheaEvents.Count)
Add-Line ("WHEA events within last {0} day(s): {1}" -f $DaysBack, $WheaRecent.Count)
Add-Line ("Oldest WHEA event read: {0}" -f $OldestWhea.TimeCreated)
Add-Line ("Newest WHEA event read: {0}" -f $NewestWhea.TimeCreated)
Add-Line ""
Add-Line "WHEA events by Event ID:"
Add-Table (
$WheaEvents |
Group-Object Id |
Sort-Object Count -Descending |
Select-Object @{Name="EventID";Expression={$_.Name}}, Count
)
Add-Line ""
Add-Line ("Memory-keyword WHEA events read: {0}" -f $WheaMemory.Count)
Add-Line ("Memory-keyword WHEA events in last 24 hours: {0}" -f $WheaMemory24h.Count)
Add-Line ("Memory-keyword WHEA events in last 7 days: {0}" -f $WheaMemory7d.Count)
Add-Line ("Memory-keyword WHEA events in last {0} days: {1}" -f $DaysBack, $WheaMemoryRecent.Count)
Add-Line ("Corrected memory-keyword WHEA events read: {0}" -f $WheaMemoryCorrected.Count)
Add-Line ("Corrected memory-keyword WHEA events in last {0} days: {1}" -f $DaysBack, $WheaMemoryCorrectedRecent.Count)
Add-Line ("Fatal/uncorrected memory-keyword WHEA events read: {0}" -f $WheaMemoryFatal.Count)
Add-Line ("Fatal/uncorrected memory-keyword WHEA events in last {0} days: {1}" -f $DaysBack, $WheaMemoryFatalRecent.Count)
if ($WheaMemory.Count -gt 0) {
Add-Line ""
Add-Line "Memory-keyword WHEA events by Event ID:"
Add-Table (
$WheaMemory |
Group-Object Id |
Sort-Object Count -Descending |
Select-Object @{Name="EventID";Expression={$_.Name}}, Count
)
Add-Line ""
Add-Line "Most recent 20 memory-keyword WHEA events:"
Add-Table (
$WheaMemory |
Sort-Object TimeCreated -Descending |
Select-Object -First 20 `
@{Name="Time";Expression={$_.TimeCreated}},
@{Name="EventID";Expression={$_.Id}},
@{Name="Level";Expression={$_.LevelDisplayName}},
@{Name="Summary";Expression={Get-WheaSummary $_.Message}}
)
Add-Line ""
Add-Line "Full message text for most recent 5 memory-keyword WHEA events:"
$i = 0
foreach ($evt in ($WheaMemory | Sort-Object TimeCreated -Descending | Select-Object -First 5)) {
$i++
Add-Line ""
Add-Line ("--- Memory WHEA Event #{0}: {1}, Event ID {2}, Level {3} ---" -f $i, $evt.TimeCreated, $evt.Id, $evt.LevelDisplayName)
Add-Block $evt.Message
}
}
}
if ($WheaMemoryFatalRecent.Count -gt 0) {
$Findings.Add("FATAL/UNCORRECTED memory-related WHEA events were found in the recent lookback window.")
}
elseif ($WheaMemoryCorrectedRecent.Count -gt 0) {
$Findings.Add("Corrected memory-related WHEA events were found in the recent lookback window.")
}
elseif ($WheaMemory.Count -gt 0) {
$Findings.Add("Memory-related WHEA events exist in the current System log, but not within the recent lookback window.")
}
else {
$Findings.Add("No memory-keyword WHEA events were found in the WHEA events read from the current System log.")
}
Section "Windows Memory Diagnostic Results"
$MemDiagEvents = Safe-Run "Windows Memory Diagnostic results" {
Get-WinEvent -FilterHashtable @{
LogName = "System"
ProviderName = "Microsoft-Windows-MemoryDiagnostics-Results"
} -MaxEvents 20 -ErrorAction Stop
}
$MemDiagEvents = @($MemDiagEvents)
if ($MemDiagEvents.Count -eq 0) {
Add-Line "No Windows Memory Diagnostic result events found in the current System log."
}
else {
Add-Table (
$MemDiagEvents |
Sort-Object TimeCreated -Descending |
Select-Object -First 20 `
@{Name="Time";Expression={$_.TimeCreated}},
@{Name="EventID";Expression={$_.Id}},
@{Name="Level";Expression={$_.LevelDisplayName}},
@{Name="Summary";Expression={($_.Message -split "`r?`n" | Select-Object -First 4) -join " "}}
)
Add-Line ""
Add-Line "Full message text for most recent 3 Windows Memory Diagnostic results:"
$i = 0
foreach ($evt in ($MemDiagEvents | Sort-Object TimeCreated -Descending | Select-Object -First 3)) {
$i++
Add-Line ""
Add-Line ("--- Memory Diagnostic Event #{0}: {1}, Event ID {2} ---" -f $i, $evt.TimeCreated, $evt.Id)
Add-Block $evt.Message
}
$BadDiag = @($MemDiagEvents | Where-Object { $_.Message -match "(?i)hardware problems were detected|memory problems were detected|errors were detected" })
if ($BadDiag.Count -gt 0) {
$Findings.Add("Windows Memory Diagnostic has reported possible memory errors.")
}
}
Section "Crash / Unexpected Restart Context"
Add-Line "These are not proof of bad RAM, but they help correlate memory errors with crashes or power-loss symptoms."
$CrashEvents = Safe-Run "Crash and unexpected restart events" {
Get-WinEvent -FilterHashtable @{
LogName = "System"
Id = 41, 1001, 6008
} -MaxEvents 200 -ErrorAction Stop
}
$CrashEvents = @($CrashEvents)
$CrashRecent = @($CrashEvents | Where-Object { $_.TimeCreated -ge $StartTime })
Add-Line ("Crash/unexpected restart events read: {0}" -f $CrashEvents.Count)
Add-Line ("Crash/unexpected restart events in last {0} day(s): {1}" -f $DaysBack, $CrashRecent.Count)
if ($CrashEvents.Count -gt 0) {
Add-Table (
$CrashEvents |
Sort-Object TimeCreated -Descending |
Select-Object -First 30 `
@{Name="Time";Expression={$_.TimeCreated}},
@{Name="EventID";Expression={$_.Id}},
@{Name="Provider";Expression={$_.ProviderName}},
@{Name="Summary";Expression={($_.Message -split "`r?`n" | Select-Object -First 2) -join " "}}
)
}
if ($CrashRecent.Count -gt 0) {
$Findings.Add("Crash/unexpected restart events exist within the recent lookback window.")
}
Section "Preliminary Assessment"
Add-Line "This is a first-pass assessment based only on what Windows can see."
$Severity = "GREEN / NO WINDOWS-REPORTED MEMORY ERRORS FOUND"
if ($WheaMemoryFatalRecent.Count -gt 0) {
$Severity = "RED / FATAL OR UNCORRECTED MEMORY-RELATED HARDWARE ERRORS FOUND"
}
elseif ($WheaMemoryCorrectedRecent.Count -gt 0) {
$Severity = "AMBER / CORRECTED MEMORY-RELATED HARDWARE ERRORS FOUND"
}
elseif ($BadDiag.Count -gt 0) {
$Severity = "RED / WINDOWS MEMORY DIAGNOSTIC REPORTED MEMORY PROBLEMS"
}
elseif ($WheaMemory.Count -gt 0) {
$Severity = "AMBER / HISTORICAL MEMORY-RELATED WHEA EVENTS FOUND"
}
Add-Line ("Assessment: {0}" -f $Severity)
Add-Line ""
if ($Findings.Count -eq 0) {
Add-Line "No notable findings were collected."
}
else {
foreach ($f in $Findings) {
Add-Line ("- " + $f)
}
}
Add-Line ""
Add-Line "Interpretation guide:"
Add-Line "- Any fatal or uncorrected memory-related WHEA event is serious."
Add-Line "- Repeated corrected ECC/WHEA memory events usually justify replacing or reseating DIMMs, checking BIOS/firmware, disabling overclock/XMP/EXPO, and checking motherboard memory QVL support."
Add-Line "- Zero WHEA memory events does not prove the RAM is healthy; it only means Windows did not log such errors in the current retained event log."
Add-Line "- Consumer/non-ECC systems may have bad RAM without any ECC correction counts because there is no ECC telemetry to count."
Add-Line "- Server/workstation systems may also have more authoritative memory logs in BMC tools such as iDRAC, iLO, XClarity, IPMI, or vendor diagnostics."
Section "Report File"
Add-Line ("Saving report to: {0}" -f $OutputFile)
try {
$Utf8NoBom = New-Object System.Text.UTF8Encoding($false)
[System.IO.File]::WriteAllLines($OutputFile, $Report, $Utf8NoBom)
Add-Line "Saved successfully."
}
catch {
Add-Line ("WARNING: Could not save report file: " + $_.Exception.Message)
}
Add-Line ""
Add-Line "DONE. Please send the report file listed above."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment