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.

✓ Safe for work PCs No admin rights needed Windows 10/11, PowerShell 5.1+
ExcelSupportReport.ps1
⬇ Download
How to run it
  1. 1Download
  2. 2Right-click › Run with PowerShell
  3. 3Results open in Downloads
Didn't work? Do this instead
  1. 1Copy script
  2. 2Open PowerShell from Start
  3. 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.

Tip: if you can, make Excel crash again first, then run the script straight away. Don't restart the PC in between.

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.

Was this helpful?
🚩 Report a problem with this script
0 / 2000

Still stuck? We can fix it for you remotely, usually the same day. See our Microsoft 365 & Office support service.

Get help