Excel keeps crashing? Collect a full diagnostic report with one PowerShell script
A free PowerShell script that collects everything needed to find out why Excel crashes, freezes or runs slowly, in one zip file.
- 1Download
- 2Right-click › Run with PowerShell
- 3Results open in Downloads
- 1Copy script
- 2Open PowerShell from Start
- 3Paste and press Enter
Safety & file details
Free to use, provided as-is. It doesn't install anything or send data anywhere, and it runs without admin rights. As with any script, read it before you run it — or ask us.
PowerShell · Version 2.2 · 432 lines
SHA-256 (to check the download wasn't altered: Get-FileHash .\ExcelSupportReport.ps1)
2cd098683b2c16fd573b7fa00d17dcf65908f67c0ef6c89f8e66d65a5bdb068c
View the script
#Requires -Version 5.1
<#
.SYNOPSIS
Excel Crash & Performance Support Report
.DESCRIPTION
Collects read-only diagnostics that help work out why Microsoft Excel is
crashing, freezing or running slowly: hardware and memory, graphics driver,
Office version and update channel, add-ins, hardware-acceleration setting,
recent Excel crash/hang events, Windows Error Reporting entries and any
local crash dumps. Everything is saved to a folder in your Downloads
folder and zipped, ready to send to whoever is helping you.
The script does NOT change any settings, install anything or send data
anywhere. The only things it writes are the report folder and zip file.
.NOTES
Source : https://techs4u.com.au/resources
Version : 2.2
Requires : Windows 10/11, Windows PowerShell 5.1 or PowerShell 7+
Licence : MIT - free to use and modify. Provided as-is, without warranty.
HOW TO RUN
1. Download - your browser saves it to your Downloads folder.
2. Run it - right-click ExcelSupportReport.ps1 > Run with PowerShell
(Windows 11: right-click > Show more options first).
3. Results - saved to your Downloads folder, which opens for you.
IF RIGHT-CLICK DOESN'T WORK (the most reliable method):
1. Copy the whole script (the "Copy script" button on the web page,
or open the file in Notepad, Ctrl+A, Ctrl+C).
2. Open Windows PowerShell from the Start menu.
3. Paste it in (right-click inside the window, or Ctrl+V) and press
Enter. If Windows warns about pasting multiple lines, choose
"Paste anyway".
Results are saved to your Downloads folder the same way.
TIP: Reproduce the Excel crash or error FIRST, then run this script
straight away - do not reboot in between.
PRIVACY: the report includes your computer name, Windows username and
folder paths. Review it before sharing it with anyone.
#>
Clear-Host
Write-Host "==============================================" -ForegroundColor Cyan
Write-Host " Excel Crash & Performance Support Report" -ForegroundColor Cyan
Write-Host " techs4u.com.au" -ForegroundColor Cyan
Write-Host "==============================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "This script only READS system information - it changes nothing." -ForegroundColor Gray
Write-Host "The report includes your computer name and username." -ForegroundColor Gray
Write-Host ""
Start-Sleep -Seconds 2
# --- Techs4U standard: output goes to the user's real Downloads folder ---
# Downloads is where browsers save by default and, unlike the Desktop, it is
# not redirected or synced by OneDrive, so large crash dumps and personal
# details are not uploaded to the cloud.
function Get-DownloadsFolder {
$path = $null
try { $path = (New-Object -ComObject Shell.Application).Namespace('shell:Downloads').Self.Path } catch {}
if (-not $path -or -not (Test-Path $path)) {
try {
$raw = (Get-ItemProperty 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders' -ErrorAction Stop).'{374DE290-123F-4565-9164-39C4925E467B}'
if ($raw) { $path = [Environment]::ExpandEnvironmentVariables($raw) }
} catch {}
}
if (-not $path -or -not (Test-Path $path)) { $path = Join-Path $env:USERPROFILE 'Downloads' }
if (-not (Test-Path $path)) { $path = $env:TEMP }
return $path
}
function Wait-BeforeClose {
Write-Host ""
Write-Host "Press Enter to close this window..." -ForegroundColor DarkGray
[void](Read-Host)
}
# --- Report folder (timestamped, so earlier reports are never overwritten) ---
try {
$OutputRoot = Get-DownloadsFolder
$Stamp = Get-Date -Format 'yyyyMMdd-HHmm'
$Folder = Join-Path $OutputRoot "ExcelSupportReport_$Stamp"
New-Item -ItemType Directory -Path $Folder -Force -ErrorAction Stop | Out-Null
$ReportPath = Join-Path $Folder "ExcelSupportReport.txt"
} catch {
Write-Host ""
Write-Host "SETUP FAILED - could not create the report folder" -ForegroundColor Red
Write-Host "Attempted path: $Folder" -ForegroundColor Red
Write-Host "Error: $($_.Exception.Message)" -ForegroundColor Red
Wait-BeforeClose
exit
}
$Steps = @(
"System Information","Memory Usage","Disk Space","Graphics Driver",
"Excel Install Info","Office Version & Update Channel","Excel Add-ins",
"Hardware Acceleration Setting","Running Excel Processes",
"Excel Crash & Hang Events","Office Alerts","Display / GPU Events",
"Unexpected Shutdown / Thermal Events","Windows Error Reports",
"Crash Dump Files","Uptime"
)
$Total = $Steps.Count
$Current = 0
function Show-Progress {
param([string]$Status)
$script:Current++
$pct = [math]::Round(($script:Current / $Total) * 100)
Write-Host "[$pct%] $Status..." -ForegroundColor Yellow
}
function Add-Section {
param([string]$Title, [scriptblock]$Content)
Add-Content -Path $ReportPath -Value "`r`n===== $Title =====`r`n"
try {
$out = & $Content | Out-String -Width 300
if ([string]::IsNullOrWhiteSpace($out)) { $out = "(nothing found)" }
Add-Content -Path $ReportPath -Value $out
} catch {
Add-Content -Path $ReportPath -Value "ERROR collecting $Title : $($_.Exception.Message)"
}
}
# First 4 non-empty lines of an event message - for crash events this keeps
# the faulting module and exception code, which is usually the useful part.
function Get-ShortMessage {
param([string]$Message)
(($Message -split "`r?`n") | Where-Object { $_.Trim() } | Select-Object -First 4) -join ' | '
}
Add-Content -Path $ReportPath -Value "EXCEL SUPPORT REPORT (techs4u.com.au)"
Add-Content -Path $ReportPath -Value "Generated: $(Get-Date)"
Add-Content -Path $ReportPath -Value "Computer: $env:COMPUTERNAME | User: $env:USERNAME"
Add-Content -Path $ReportPath -Value "Report Folder: $Folder"
Write-Host ""
Write-Host "Collecting Excel support report - please wait..." -ForegroundColor Cyan
Write-Host ""
Show-Progress "System Information"
Add-Section "System Information" {
$os = Get-CimInstance Win32_OperatingSystem
$cs = Get-CimInstance Win32_ComputerSystem
[PSCustomObject]@{
Manufacturer = $cs.Manufacturer
Model = $cs.Model
OS = $os.Caption
OSVersion = $os.Version
OSBuild = $os.BuildNumber
TotalRAMGB = [math]::Round($cs.TotalPhysicalMemory/1GB,2)
}
}
Show-Progress "Memory Usage"
Add-Section "Current Memory Usage" {
$os = Get-CimInstance Win32_OperatingSystem
[PSCustomObject]@{
TotalGB = [math]::Round($os.TotalVisibleMemorySize/1MB,2)
FreeGB = [math]::Round($os.FreePhysicalMemory/1MB,2)
UsedPercent = [math]::Round((($os.TotalVisibleMemorySize-$os.FreePhysicalMemory)/$os.TotalVisibleMemorySize)*100,1)
}
}
Show-Progress "Disk Space"
Add-Section "Disk Space (local drives)" {
Get-CimInstance Win32_LogicalDisk -Filter "DriveType=3" |
Select-Object DeviceID,
@{N='SizeGB';E={[math]::Round($_.Size/1GB,1)}},
@{N='FreeGB';E={[math]::Round($_.FreeSpace/1GB,1)}},
@{N='FreePercent';E={ if ($_.Size) { [math]::Round(($_.FreeSpace/$_.Size)*100,1) } }}
}
Show-Progress "Graphics Driver"
Add-Section "Graphics Driver Info" {
# Note: AdapterRAM is a 32-bit value, so cards with more than 4 GB report 4 GB.
Get-CimInstance Win32_VideoController |
Select-Object Name,DriverVersion,DriverDate,
@{N='AdapterRAM_MB';E={[math]::Round($_.AdapterRAM/1MB)}},VideoModeDescription
}
Show-Progress "Excel Install Info"
Add-Section "Excel Install Info" {
$exe = $null
$appPath = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\excel.exe'
if (Test-Path $appPath) {
$exe = (Get-ItemProperty $appPath -ErrorAction SilentlyContinue).'(default)'
if ($exe) { $exe = $exe.Trim('"') }
}
if (-not $exe -or -not (Test-Path $exe)) {
$exe = @(
"$env:ProgramFiles\Microsoft Office\root\Office16\EXCEL.EXE",
"${env:ProgramFiles(x86)}\Microsoft Office\root\Office16\EXCEL.EXE",
"$env:ProgramFiles\Microsoft Office\Office16\EXCEL.EXE",
"${env:ProgramFiles(x86)}\Microsoft Office\Office16\EXCEL.EXE"
) | Where-Object { $_ -and (Test-Path $_) } | Select-Object -First 1
}
if ($exe) {
$v = (Get-Item $exe).VersionInfo
[PSCustomObject]@{
Path = $exe
ProductName = $v.ProductName
FileVersion = $v.FileVersion
Bitness = if ($exe -like "*Program Files (x86)*") { "32-bit" } else { "64-bit" }
}
} else {
"Could not locate EXCEL.EXE (App Paths registry key and standard folders checked)"
}
}
Show-Progress "Office Version & Update Channel"
Add-Section "Office Version & Update Channel (Click-to-Run)" {
$c2r = 'HKLM:\SOFTWARE\Microsoft\Office\ClickToRun\Configuration'
if (Test-Path $c2r) {
$c = Get-ItemProperty $c2r
$channels = @{
'492350f6-3a01-4f97-b9c0-c7c6ddf67d60' = 'Current Channel'
'64256afe-f5d9-4f86-8936-8840a6a4f5be' = 'Current Channel (Preview)'
'55336b82-a18d-4dd6-b5f6-9e5095c314a6' = 'Monthly Enterprise Channel'
'7ffbc6bf-bc32-4f92-8982-f9dd17fd3114' = 'Semi-Annual Enterprise Channel'
'b8f9b850-328d-4355-9145-c59439a0c4cf' = 'Semi-Annual Enterprise Channel (Preview)'
'5440fd1f-7ecb-4221-8110-145efaa6372f' = 'Beta Channel'
}
$url = if ($c.UpdateChannel) { $c.UpdateChannel } else { $c.CDNBaseUrl }
$guid = if ($url) { ($url -split '/')[-1] } else { $null }
[PSCustomObject]@{
Version = $c.VersionToReport
Platform = $c.Platform
Products = $c.ProductReleaseIds
UpdateChannel = if ($guid -and $channels.ContainsKey($guid)) { $channels[$guid] } else { $url }
UpdatesEnabled = $c.UpdatesEnabled
}
} else {
"Click-to-Run configuration not found (Office may be an MSI or Store install)"
}
}
Show-Progress "Excel Add-ins"
Add-Section "Excel COM Add-ins (LoadBehavior 3 = loads at startup)" {
$roots = @(
'HKCU:\Software\Microsoft\Office\Excel\Addins',
'HKLM:\SOFTWARE\Microsoft\Office\Excel\Addins',
'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Office\Excel\Addins',
'HKLM:\SOFTWARE\Microsoft\Office\ClickToRun\REGISTRY\MACHINE\Software\Microsoft\Office\Excel\Addins'
)
$list = foreach ($r in $roots) {
if (Test-Path $r) {
Get-ChildItem $r -ErrorAction SilentlyContinue | ForEach-Object {
$p = Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue
[PSCustomObject]@{
AddIn = $_.PSChildName
FriendlyName = $p.FriendlyName
LoadBehavior = $p.LoadBehavior
Scope = if ($r -like 'HKCU:*') { 'User' } else { 'Machine' }
}
}
}
}
if ($list) { $list | Format-Table -AutoSize } else { "No COM add-ins registered" }
$disabled = 'HKCU:\Software\Microsoft\Office\16.0\Excel\Resiliency\DisabledItems'
if (Test-Path $disabled) {
$n = @((Get-Item $disabled).Property).Count
"Add-ins disabled by Office after a crash (Resiliency\DisabledItems): $n"
}
}
Show-Progress "Hardware Acceleration Setting"
Add-Section "Excel Hardware Acceleration Setting" {
$found = $false
foreach ($ver in @("16.0","15.0")) {
$key = "HKCU:\Software\Microsoft\Office\$ver\Common\Graphics"
$val = Get-ItemProperty -Path $key -Name "DisableHardwareAcceleration" -ErrorAction SilentlyContinue
if ($val) {
$found = $true
[PSCustomObject]@{
OfficeVersion = $ver
DisableHardwareAcceleration = $val.DisableHardwareAcceleration
}
}
}
if (-not $found) { "Not set (default - hardware acceleration enabled)" }
}
Show-Progress "Running Excel Processes"
Add-Section "Running Excel Processes" {
$procs = Get-Process -Name EXCEL -ErrorAction SilentlyContinue
if ($procs) {
$procs | Select-Object Id,StartTime,Responding,
@{N='WorkingSetMB';E={[math]::Round($_.WorkingSet64/1MB,1)}},
@{N='PrivateMemMB';E={[math]::Round($_.PrivateMemorySize64/1MB,1)}},
@{N='PeakWorkingSetMB';E={[math]::Round($_.PeakWorkingSet64/1MB,1)}}
} else {
"Excel is not currently running"
}
}
Show-Progress "Excel Crash & Hang Events"
Add-Section "Excel Crash & Hang Events - Application log (last 14 days)" {
Get-WinEvent -FilterHashtable @{
LogName = 'Application'
ProviderName = 'Application Error','Application Hang','Windows Error Reporting'
StartTime = (Get-Date).AddDays(-14)
} -ErrorAction SilentlyContinue |
Where-Object { $_.Message -match 'EXCEL\.EXE' } |
Select-Object -First 50 TimeCreated,ProviderName,Id,
@{N='Message';E={ Get-ShortMessage $_.Message }}
}
Show-Progress "Office Alerts"
Add-Section "Office Alerts - OAlerts log (last 14 days)" {
Get-WinEvent -FilterHashtable @{ LogName='OAlerts'; StartTime=(Get-Date).AddDays(-14) } -ErrorAction SilentlyContinue |
Where-Object { $_.Message -match 'Excel' } |
Select-Object -First 50 TimeCreated,Id,
@{N='Message';E={ Get-ShortMessage $_.Message }}
}
Show-Progress "Display / GPU Events"
Add-Section "Display Driver / GPU Errors & Warnings - System log (last 14 days)" {
Get-WinEvent -FilterHashtable @{ LogName='System'; Level=1,2,3; StartTime=(Get-Date).AddDays(-14) } -ErrorAction SilentlyContinue |
Where-Object {
$_.ProviderName -match 'Display|dwm|nvlddmkm|amdkmdag|amdwddmg|igfx|dxgkrnl' -or
$_.Message -match 'display driver|stopped responding and has successfully recovered'
} |
Select-Object -First 50 TimeCreated,ProviderName,Id,LevelDisplayName,
@{N='Message';E={ Get-ShortMessage $_.Message }}
}
Show-Progress "Unexpected Shutdown / Thermal Events"
Add-Section "Unexpected Shutdown / CPU Throttling Events (last 30 days)" {
# 41 = Kernel-Power unexpected restart, 6008 = previous shutdown was unexpected,
# 37 = CPU speed limited by firmware (often thermal or power related)
Get-WinEvent -FilterHashtable @{ LogName='System'; Id=41,6008,37; StartTime=(Get-Date).AddDays(-30) } -ErrorAction SilentlyContinue |
Select-Object -First 50 TimeCreated,Id,ProviderName,
@{N='Message';E={ Get-ShortMessage $_.Message }}
}
Show-Progress "Windows Error Reports"
$WerRoots = @(
"$env:LOCALAPPDATA\Microsoft\Windows\WER\ReportArchive",
"$env:LOCALAPPDATA\Microsoft\Windows\WER\ReportQueue",
"$env:ProgramData\Microsoft\Windows\WER\ReportArchive",
"$env:ProgramData\Microsoft\Windows\WER\ReportQueue"
)
$ExcelReports = foreach ($root in $WerRoots) {
if (Test-Path $root) {
Get-ChildItem $root -Directory -ErrorAction SilentlyContinue | Where-Object { $_.Name -match 'EXCEL' }
}
}
$ExcelReports = @($ExcelReports | Sort-Object LastWriteTime -Descending)
Add-Section "Windows Error Reporting - recent Excel reports" {
if ($ExcelReports.Count) {
$ExcelReports | Select-Object -First 10 Name,LastWriteTime,@{N='Location';E={$_.Parent.FullName}}
} else {
"No Excel Windows Error Reporting folders found"
}
}
Show-Progress "Crash Dump Files"
$DumpDest = Join-Path $Folder "CrashData"
$Copied = 0
$MaxDumpMB = 300
try {
# 1) The 5 most recent WER report folders (Report.wer + any small dumps)
foreach ($r in ($ExcelReports | Select-Object -First 5)) {
$destSub = Join-Path $DumpDest $r.Name
New-Item -ItemType Directory -Path $destSub -Force | Out-Null
Get-ChildItem $r.FullName -File -Recurse -ErrorAction SilentlyContinue |
Where-Object { ($_.Name -eq 'Report.wer' -or $_.Extension -in '.dmp','.mdmp') -and $_.Length -lt ($MaxDumpMB * 1MB) } |
Copy-Item -Destination $destSub -Force -ErrorAction SilentlyContinue
$Copied++
}
# 2) Local crash dumps (only exist if LocalDumps is configured)
$localDumps = Join-Path $env:LOCALAPPDATA 'CrashDumps'
if (Test-Path $localDumps) {
$dumps = Get-ChildItem $localDumps -Filter 'EXCEL.EXE*.dmp' -ErrorAction SilentlyContinue |
Where-Object { $_.Length -lt ($MaxDumpMB * 1MB) } |
Sort-Object LastWriteTime -Descending | Select-Object -First 3
if ($dumps) {
New-Item -ItemType Directory -Path $DumpDest -Force | Out-Null
$dumps | Copy-Item -Destination $DumpDest -Force -ErrorAction SilentlyContinue
$Copied += @($dumps).Count
}
}
Add-Section "Crash Data Copied" {
if ($Copied) { "Copied $Copied item(s) to: $DumpDest (files over $MaxDumpMB MB skipped)" }
else { "No Excel crash reports or dump files found to copy." }
}
} catch {
Add-Section "Crash Data Copied" { "Could not copy crash data: $($_.Exception.Message)" }
}
Show-Progress "Uptime"
Add-Section "System Uptime" {
$os = Get-CimInstance Win32_OperatingSystem
[PSCustomObject]@{
LastBoot = $os.LastBootUpTime
UptimeDays = [math]::Round(((Get-Date)-$os.LastBootUpTime).TotalDays,1)
}
}
# --- Zip everything up so it is one file to send ---
Write-Host ""
Write-Host "Zipping the report..." -ForegroundColor DarkGray
$ZipPath = "$Folder.zip"
try {
Compress-Archive -Path (Join-Path $Folder '*') -DestinationPath $ZipPath -Force -ErrorAction Stop
} catch {
$ZipPath = $null
}
Write-Host ""
if (Test-Path $ReportPath) {
Write-Host "========================================" -ForegroundColor Green
Write-Host "DONE. The report is in your Downloads folder:" -ForegroundColor Green
Write-Host " $Folder" -ForegroundColor Green
if ($ZipPath) {
Write-Host "Send this one file to your IT support person:" -ForegroundColor Green
Write-Host " $ZipPath" -ForegroundColor Green
}
Write-Host "Check the report before sharing - it includes your computer name and username." -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Green
Start-Process explorer.exe -ArgumentList "/select,`"$(if ($ZipPath) { $ZipPath } else { $ReportPath })`""
} else {
Write-Host "SOMETHING WENT WRONG - the report file was not created." -ForegroundColor Red
Write-Host "Expected location: $ReportPath" -ForegroundColor Red
Wait-BeforeClose
exit
}
# Kept on one line so a pasted run pauses here correctly.
Wait-BeforeClose; exit
When Excel crashes, the error message rarely says why. This script collects the clues (crash logs, add-ins, graphics driver and Office version) and zips them into one file you can send to your IT support.
When to use it
- Excel closes or says "Microsoft Excel has stopped working"
- Excel freezes ("Not Responding")
- Excel is slow to open, scroll or calculate
What it collects
- PC, Windows and Office details
- Excel add-ins
- Graphics driver
- Excel crash events from the last 14 days, plus crash files
It doesn't change anything on your PC, and nothing is sent anywhere.
Reading the report
Open ExcelSupportReport.txt and look for Faulting module under Excel Crash & Hang Events:
- An add-in file: turn that add-in off (File → Options → Add-ins).
- A graphics file (e.g.
nvwgf2umx.dll,igdumdim64.dll): update the graphics driver.
Not sure what it means? Send it to us and we'll take a look.
Privacy
The report includes your computer name and Windows username. Only share it with people you trust.