"=== Excel ===" $FormatEnumerationLimit = -1 "Time: " + (Get-Date -Format 'yyyy-MM-dd HH:mm:ss zzz') + "; PowerShell language mode: " + $ExecutionContext.SessionState.LanguageMode + "; PowerShell process: " + $env:PROCESSOR_ARCHITECTURE Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Office\ClickToRun\Configuration -ErrorAction SilentlyContinue | Select-Object VersionToReport, Platform, UpdateChannel | Format-List $excelExe = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\excel.exe' -ErrorAction SilentlyContinue).'(default)' "Excel: $excelExe" "=== Add-ins that load with Excel ===" $options = Get-ItemProperty HKCU:\Software\Microsoft\Office\16.0\Excel\Options -ErrorAction SilentlyContinue $options | Select-Object OPEN* | Format-List $addin = "$env:APPDATA\Microsoft\AddIns\Blitz Report.xlam" foreach ($p in $options.PSObject.Properties) { if ($p.Name -like 'OPEN*' -and $p.Value -like '*\*Blitz Report.xlam*') { $addin = ($p.Value -replace '^/R ', '').Trim('"') } } Get-Item $addin | Select-Object FullName, Length, LastWriteTime | Format-List if (Get-Item $addin -Stream Zone.Identifier -ErrorAction SilentlyContinue) { Get-Content $addin -Stream Zone.Identifier | Where-Object { $_ -match 'ZoneId' } } else { "The add-in file has no Mark of the Web" } Get-ChildItem HKCU:\Software\Microsoft\Office\Excel\Addins, HKLM:\SOFTWARE\Microsoft\Office\Excel\Addins, HKLM:\SOFTWARE\WOW6432Node\Microsoft\Office\Excel\Addins -ErrorAction SilentlyContinue | ForEach-Object { Get-ItemProperty $_.PSPath } | Select-Object PSChildName, FriendlyName, LoadBehavior | Format-Table -AutoSize -Wrap Get-ChildItem "$env:APPDATA\Microsoft\Excel\XLSTART", "$env:APPDATA\Microsoft\AddIns" -ErrorAction SilentlyContinue | Select-Object FullName, Length | Format-Table -AutoSize -Wrap "Add-in settings:" Select-String -Path "$env:APPDATA\Blitz Report\settings.ini" -Pattern '^(EnvironmentFormat|DebugEnabled)=' -ErrorAction SilentlyContinue | ForEach-Object { $_.Line } "Environments in the settings file: " + @(Select-String -Path "$env:APPDATA\Blitz Report\settings.ini" -Pattern '^Name\d+=.' -ErrorAction SilentlyContinue).Count "Environments set by policy: " + (Test-Path 'HKLM:\SOFTWARE\Policies\Enginatics\Blitz Report\Environments') + ' ' + (Test-Path 'HKCU:\Software\Policies\Enginatics\Blitz Report\Environments') "=== Machine ===" Get-CimInstance Win32_ComputerSystem | Select-Object Manufacturer, Model, TotalPhysicalMemory | Format-List Get-CimInstance Win32_Processor | Select-Object Name, NumberOfLogicalProcessors | Format-List Get-CimInstance Win32_OperatingSystem | Select-Object Caption, Version | Format-List "=== Security products ===" Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntiVirusProduct -ErrorAction SilentlyContinue | Select-Object displayName, productState | Format-Table -AutoSize "Running security services:" Get-CimInstance Win32_Service -Filter "State='Running'" | Where-Object { ($_.Name + ' ' + $_.DisplayName + ' ' + $_.PathName) -match 'Defender|CrowdStrike|CSFalcon|Sentinel|Cylance|Zscaler|ZSA|Netskope|stAgent|Tanium|Carbon ?Black|RepMgr|ESET|McAfee|Trellix|Sophos|Symantec|Forcepoint|Websense|Cortex|Palo Alto|cyserver|Qualys|Digital Guardian|dgagent|AppSense|Ivanti|Kaspersky|Trend Micro|Bitdefender|WithSecure|F-Secure|BeyondTrust|Avecto|CyberArk|FireEye|xagt|Proofpoint|Antivirus|Anti-Malware|Data Loss|Threat' } | Select-Object Name, DisplayName | Format-Table -AutoSize -Wrap "File system filter drivers that are not Microsoft's:" Get-CimInstance Win32_SystemDriver -Filter "State='Running' AND ServiceType='File System Driver'" | Select-Object Name, DisplayName, @{n='Company';e={ (Get-Item ($_.PathName -replace '^\\\?\?\\', '') -ErrorAction SilentlyContinue).VersionInfo.CompanyName }} | Where-Object { $_.Company -notmatch 'Microsoft' } | Format-Table -AutoSize -Wrap "Antimalware scan interface providers:" Get-ChildItem HKLM:\SOFTWARE\Microsoft\AMSI\Providers, HKLM:\SOFTWARE\WOW6432Node\Microsoft\AMSI\Providers -ErrorAction SilentlyContinue | ForEach-Object { $id = $_.PSChildName; (Get-ItemProperty "Registry::HKEY_CLASSES_ROOT\CLSID\$id\InprocServer32", "Registry::HKEY_CLASSES_ROOT\WOW6432Node\CLSID\$id\InprocServer32" -ErrorAction SilentlyContinue).'(default)' } | Select-Object -Unique try { Get-MpComputerStatus -ErrorAction Stop | Select-Object AMRunningMode, AntivirusEnabled, RealTimeProtectionEnabled, OnAccessProtectionEnabled, BehaviorMonitorEnabled, IoavProtectionEnabled, AMProductVersion | Format-List } catch { "Defender status not available" } try { Get-MpPreference -ErrorAction Stop | Select-Object @{n='AsrRuleIds';e={ $_.AttackSurfaceReductionRules_Ids -join ' ' }}, @{n='AsrRuleActions';e={ $_.AttackSurfaceReductionRules_Actions -join ' ' }}, MAPSReporting, CloudBlockLevel, CloudExtendedTimeout | Format-List } catch { "Defender settings not available" } "=== Office security policies and trust ===" Get-ItemProperty HKCU:\Software\Policies\Microsoft\Office\16.0\Excel\Security, HKLM:\SOFTWARE\Policies\Microsoft\Office\16.0\Excel\Security, HKCU:\Software\Policies\Microsoft\Cloud\Office\16.0\Excel\Security, HKCU:\Software\Policies\Microsoft\Office\16.0\Common\Security, HKLM:\SOFTWARE\Policies\Microsoft\Office\16.0\Common\Security, HKCU:\Software\Policies\Microsoft\Cloud\Office\16.0\Common\Security, HKCU:\Software\Microsoft\Office\16.0\Excel\Security, HKCU:\Software\Microsoft\Office\16.0\Common\Security -ErrorAction SilentlyContinue | Select-Object * -ExcludeProperty PSParentPath, PSChildName, PSDrive, PSProvider | Format-List "Trusted publishers named Enginatics:" Get-ChildItem Cert:\CurrentUser\TrustedPublisher, Cert:\LocalMachine\TrustedPublisher -ErrorAction SilentlyContinue | Where-Object { $_.Subject -match 'Enginatics' } | Select-Object Subject, NotAfter, PSParentPath | Format-List "Trusted locations:" $tl = 'HKCU:\Software\Microsoft\Office\16.0\Excel\Security\Trusted Locations', 'HKCU:\Software\Policies\Microsoft\Office\16.0\Excel\Security\Trusted Locations', 'HKLM:\SOFTWARE\Policies\Microsoft\Office\16.0\Excel\Security\Trusted Locations', 'HKCU:\Software\Policies\Microsoft\Cloud\Office\16.0\Excel\Security\Trusted Locations' Get-ItemProperty $tl -ErrorAction SilentlyContinue | Select-Object AllLocationsDisabled, AllowNetworkLocations, PSPath | Format-List Get-ChildItem $tl -ErrorAction SilentlyContinue | ForEach-Object { Get-ItemProperty $_.PSPath } | Select-Object Path, AllowSubFolders | Format-Table -AutoSize -Wrap "Check for publisher's certificate revocation, State (146432 = on, 146944 = off): " + (Get-ItemProperty 'HKCU:\Software\Microsoft\Windows\CurrentVersion\WinTrust\Trust Providers\Software Publishing' -ErrorAction SilentlyContinue).State "=== Excel start timings ===" $sid = (Get-Process -Id $PID).SessionId $snap = { $k = @{}; $u = @{}; Get-CimInstance Win32_Process | ForEach-Object { $id = "$($_.ProcessId)|$($_.CreationDate)"; $k[$id] = $_.KernelModeTime; $u[$id] = $_.UserModeTime }; @($k, $u) } $cpu = { "Processor time used from this start until Excel was closed, in seconds (Kernel = inside Windows and drivers, User = the program's own code):"; $rows = @(Get-CimInstance Win32_Process | Select-Object Name, @{n='Kernel';e={ [int](($_.KernelModeTime - $c[0]["$($_.ProcessId)|$($_.CreationDate)"]) / 1000000) / 10 }}, @{n='User';e={ [int](($_.UserModeTime - $c[1]["$($_.ProcessId)|$($_.CreationDate)"]) / 1000000) / 10 }}); $rows += '' | Select-Object @{n='Name';e={ 'EXCEL.EXE' }}, @{n='Kernel';e={ [int]($xk * 10) / 10 }}, @{n='User';e={ [int]($xu * 10) / 10 }}; $rows | Where-Object { ($_.Kernel + $_.User) -ge 0.2 -and $_.Name -ne 'System Idle Process' } | Sort-Object { $_.Kernel + $_.User } -Descending | Select-Object -First 12 | Format-Table -AutoSize | Out-Host } $log = { param($since) $files = @(Get-ChildItem "$env:TEMP\Diagnostics\EXCEL\Primary*.log" -ErrorAction SilentlyContinue | Where-Object { $_.Length -gt 0 -and $_.CreationTime -ge $since } | Sort-Object LastWriteTime); if ($files.Count -eq 0) { " Excel wrote no log for this start." }; foreach ($f in $files) { $prev = $null; $boot = $false; foreach ($x in (Get-Content $f.FullName)) { if ($x -match '^\S+ (\d\d):(\d\d):(\d\d)\.(\d\d\d)\t') { $t = [int]$Matches[1] * 3600 + [int]$Matches[2] * 60 + [int]$Matches[3] + [int]$Matches[4] / 1000; $e = ''; if ($x -match '"EventName":"([^"]+)"') { $e = $Matches[1] }; if (-not $boot -and $prev -ne $null -and ($t - $prev) -ge 1) { " {0:n1} s without a log entry before {1}" -f ($t - $prev), $e }; if ($e -match 'Performance\.Boot$|Coauth\.OpenFile$|Security\.Macro\.') { $o = ' ' + $x.Substring(11, 12) + ' ' + $e; foreach ($key in 'Activity\.Duration', 'Data\.ActivationKind', 'Data\.IsBootOpen', 'Data\.PathLength', 'Data\.ScanRequiredResult', 'Data\.Measurements', 'Data\.InclusiveMeasurements', 'Data\.State', 'Data\.IsRegistry', 'Data\.DocSizeInBytes') { if ($x -match ('"' + $key + '":("[^"]*"|[^,}]*)')) { $o = $o + ' ' + ($key -replace '\\', '') + '=' + $Matches[1] } }; $o; if ($e -match 'Performance\.Boot$') { $boot = $true } }; $prev = $t } } } } $mods = { " Software loaded inside Excel that is not Microsoft's, and the antimalware and VBA modules:"; try { $m = @(Get-Process -Id @($all | ForEach-Object { $_.Id }) -Module -ErrorAction Stop | Where-Object { $_.ModuleName -match '^(amsi|mpoav|mpclient|vbe7)\.' -or ($_.FileName -notmatch '\\Microsoft Office\\|\\Common Files\\Microsoft Shared\\|\\DriverStore\\' -and $_.FileVersionInfo.CompanyName -and $_.FileVersionInfo.CompanyName -notmatch 'Microsoft|Intel|NVIDIA|Advanced Micro|ICU Project') } | Select-Object FileName, @{n='Company';e={ $_.FileVersionInfo.CompanyName }} -Unique); if ($m.Count -eq 0) { " None listed. A 64-bit PowerShell window cannot list the modules of 32-bit Excel (Platform x86 above)." } else { $m | Format-Table -AutoSize -Wrap | Out-Host } } catch { " Module list not available" } } $run = { param($label, $arg, $modules) $c = & $snap; $t0 = Get-Date; $ok = $true; $hint = 'Close Excel as soon as it has finished starting.'; if ($modules) { $hint = 'Leave Excel open for ten seconds after it has finished starting, then close it.' }; "{0}, started {1:HH:mm:ss}. {2} The next step follows by itself." -f $label, $t0, $hint; try { if ($arg) { Start-Process excel.exe -ArgumentList $arg -ErrorAction Stop } else { Start-Process excel.exe -ErrorAction Stop } } catch { $ok = $false; "Excel could not be started: " + $_.Exception.Message }; $last = ''; $seen = $false; $same = 0; $n = 0; $xt = @{}; while ($ok) { $all = @(Get-Process excel -ErrorAction SilentlyContinue | Where-Object { $_.SessionId -eq $sid }); $s = ((Get-Date) - $t0).TotalSeconds; if ($all.Count -eq 0) { if ($seen -or $s -gt 120) { break } } else { $seen = $true; try { foreach ($q in $all) { $pk = $q.PrivilegedProcessorTime; $pu = $q.UserProcessorTime; if ($pk -ne $null -and $pu -ne $null) { $xt[$q.Id] = @($pk.TotalSeconds, $pu.TotalSeconds) } }; $w = ''; foreach ($q in $all) { if ($w -eq '' -and $q.MainWindowTitle -ne '') { $w = "$($q.MainWindowHandle) $($q.MainWindowTitle)"; $title = $q.MainWindowTitle } }; if ($w -ne '') { if ($w -ne $last) { $last = $w; $same = 0; " after {0:n1} seconds: window '{1}'" -f $s, $title } else { $same++ }; if ($modules -and $same -eq 15) { & $mods } } } catch { } }; $n++; if ($seen -and $n % 300 -eq 0) { " Excel is still running. Close it once it has finished starting; if no window is open, end Microsoft Excel in Task Manager." }; Start-Sleep -Milliseconds 200 }; if ($ok -and $seen) { " after {0:n1} seconds: Excel was closed" -f ((Get-Date) - $t0).TotalSeconds; Start-Sleep -Seconds 1; "Excel's own log of this start:"; & $log $t0; $xk = 0; $xu = 0; foreach ($v in $xt.Values) { $xk += $v[0]; $xu += $v[1] }; & $cpu } elseif ($ok) { " Excel did not appear within 120 seconds." } } $closed = { $n = 0; while (Get-Process excel -ErrorAction SilentlyContinue | Where-Object { $_.SessionId -eq $sid }) { Start-Sleep -Seconds 1; $n++; if ($n % 30 -eq 0) { "Excel is still running. Close every Excel window; if none is open, end Microsoft Excel in Task Manager." } } } "Close every Excel window now. The first timing starts by itself once Excel is closed." & $closed & $run 'Start 1, normal' $null $false & $run 'Start 2, normal' $null $true & $run 'Start 3, safe mode without add-ins' '/safe' $false "=== Certificate servers of the add-in's signature ===" "Testing whether this PC reaches the servers that Windows asks whether the add-in's certificate is still valid. The three tests can take up to two minutes." $t1 = Get-Date; try { $r = Test-NetConnection ccsca2021.ocsp-certum.com -Port 80 -WarningAction SilentlyContinue -ErrorAction Stop; "Direct connection to ccsca2021.ocsp-certum.com port 80: reachable = {0}, answer after {1:n1} seconds" -f $r.TcpTestSucceeded, ((Get-Date) - $t1).TotalSeconds } catch { "Direct connection test not available: " + $_.Exception.Message } $t2 = Get-Date; try { $w = Invoke-WebRequest -Uri 'http://ccsca2021.crl.certum.pl/ccsca2021.crl' -Method Head -UseBasicParsing -TimeoutSec 30 -ErrorAction Stop; "Revocation list through this user's proxy settings: HTTP {0} after {1:n1} seconds" -f $w.StatusCode, ((Get-Date) - $t2).TotalSeconds } catch { "Revocation list through this user's proxy settings: failed after {0:n1} seconds: {1}" -f ((Get-Date) - $t2).TotalSeconds, $_.Exception.Message } $t3 = Get-Date; try { $w = Invoke-WebRequest -Uri 'http://ccsca2021.ocsp-certum.com/' -Method Head -UseBasicParsing -TimeoutSec 30 -ErrorAction Stop; "Certificate status server through this user's proxy settings: HTTP {0} after {1:n1} seconds" -f $w.StatusCode, ((Get-Date) - $t3).TotalSeconds } catch { "Certificate status server through this user's proxy settings: no HTTP 200 after {0:n1} seconds: {1}" -f ((Get-Date) - $t3).TotalSeconds, $_.Exception.Message } $ie = Get-ItemProperty 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' -ErrorAction SilentlyContinue "Proxy of this user: enabled = {0}, proxy server set = {1}, configuration script set = {2}" -f $ie.ProxyEnable, [bool]$ie.ProxyServer, [bool]$ie.AutoConfigURL "=== The add-in file ===" $r1 = (Measure-Command { Get-Content $addin -Encoding Byte -ReadCount 0 | Out-Null }).TotalSeconds; $r2 = (Measure-Command { Get-Content $addin -Encoding Byte -ReadCount 0 | Out-Null }).TotalSeconds "Reading the add-in file, twice: {0:n2} and {1:n2} seconds" -f $r1, $r2 $mp = "$env:ProgramFiles\Windows Defender\MpCmdRun.exe" if (Test-Path $mp) { $s1 = (Measure-Command { & $mp -Scan -ScanType 3 -File $addin -DisableRemediation | Out-Host }).TotalSeconds; $s2 = (Measure-Command { & $mp -Scan -ScanType 3 -File $addin -DisableRemediation | Out-Host }).TotalSeconds; "Microsoft Defender scan of the add-in file, twice: {0:n2} and {1:n2} seconds" -f $s1, $s2 } else { "MpCmdRun.exe not found" } "=== Done. Copy everything in this window into your reply. ==="