#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