# WINDOWS 11 START MENU & UI REPAIR # Repairs StartMenuExperienceHost, its AppX registration, CloudStore state when # evidence points to it, and the per-user AppContainer profile used by Start. # # Important: on Windows 11 build 26100 we observed a real failure where Start # crashed in Windows.UI.Xaml.dll only because CreateAppContainerProfile failed # with 0x80070005 for: # %LOCALAPPDATA%\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\AC # The working repair was to recreate AC, restore the current user's access and # set Low Mandatory Integrity on AC. Keep that repair AFTER Reset-AppxPackage, # because resetting the package can delete the AppContainer profile again. [CmdletBinding()] param( # Reset CloudStore even when no recent CloudStore errors were found. [switch]$ResetCloudStore, # Do not print a reboot recommendation if live verification still fails. [switch]$NoRebootPrompt ) $ErrorActionPreference = 'Stop' $StartMenuPackageName = 'Microsoft.Windows.StartMenuExperienceHost' $StartMenuPackageFamily = 'Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy' $ShellPackageName = 'Microsoft.Windows.ShellExperienceHost' $RemoteScriptUrl = 'https://fix-startmenu.pages.dev' function Write-Status { param([string]$Message, [string]$Kind = 'proc') if (Get-Command 'UI.Status' -ErrorAction SilentlyContinue) { UI.Status $Message $Kind } else { Write-Host "[Fix-StartMenu] $Message" } } function Write-Result { param([string]$Message, [string]$Color = 'Green') if (Get-Command 'UI.Box' -ErrorAction SilentlyContinue) { UI.Box $Message $Color } else { Write-Host "`n$Message" -ForegroundColor $Color } } function Invoke-Icacls { param( [Parameter(Mandatory)][string[]]$Arguments, [Parameter(Mandatory)][string]$Description ) & "$env:SystemRoot\System32\icacls.exe" @Arguments | Out-Null if ($LASTEXITCODE -ne 0) { throw "$Description failed (icacls.exe exit code $LASTEXITCODE)." } } function Get-SystemAppManifest { param([Parameter(Mandatory)][string]$PackageName) $package = Get-AppxPackage -AllUsers -Name $PackageName | Where-Object { $_.InstallLocation } | Select-Object -First 1 if ($package) { $manifest = Join-Path $package.InstallLocation 'AppxManifest.xml' if (Test-Path -LiteralPath $manifest) { return $manifest } } throw "The system AppX package '$PackageName' was not found." } function Get-StartMenuAppContainerErrors { param([datetime]$Since = (Get-Date).AddDays(-7)) @( Get-WinEvent -FilterHashtable @{ LogName = 'Microsoft-Windows-AppModel-Runtime/Admin' StartTime = $Since } -MaxEvents 300 -ErrorAction SilentlyContinue | Where-Object { $_.Id -in 21, 28 -and $_.Message -match 'StartMenuExperienceHost' -and $_.Message -match '0x80070005|\\AC' } ) } function Get-StartMenuCrashes { param([datetime]$Since = (Get-Date).AddDays(-7)) @( Get-WinEvent -FilterHashtable @{ LogName = 'Application' StartTime = $Since } -MaxEvents 500 -ErrorAction SilentlyContinue | Where-Object { $_.ProviderName -in 'Application Error', 'Windows Error Reporting' -and $_.Message -match 'StartMenuExperienceHost' } ) } function Repair-StartMenuAppContainerProfile { $packageRoot = Join-Path $env:LOCALAPPDATA "Packages\$StartMenuPackageFamily" $acPath = Join-Path $packageRoot 'AC' $identity = [Security.Principal.WindowsIdentity]::GetCurrent().Name Write-Status 'Repairing the Start menu AppContainer profile...' New-Item -ItemType Directory -Path $acPath -Force | Out-Null # Do not reset/take ownership of the whole Packages tree. Only ensure the # current user can maintain this package profile, matching the repair that # fixed CreateAppContainerProfile 0x80070005 on the affected machine. Invoke-Icacls -Arguments @( $packageRoot, '/grant', "${identity}:(OI)(CI)(F)" ) -Description 'Granting access to the Start menu package profile' Invoke-Icacls -Arguments @( $acPath, '/grant', "${identity}:(OI)(CI)(F)" ) -Description 'Granting access to the Start menu AC directory' # AppContainer AC directories require Low Mandatory Integrity. Without this # label Windows can fail while setting attributes and Start then crashes. Invoke-Icacls -Arguments @( $acPath, '/setintegritylevel', '(OI)(CI)L' ) -Description 'Setting Low Mandatory Integrity on the Start menu AC directory' if (-not (Test-Path -LiteralPath $acPath -PathType Container)) { throw "The Start menu AppContainer AC directory was not created: $acPath" } Write-Status 'Start menu AppContainer profile repaired.' 'ok' return $acPath } function Backup-AndResetCloudStore { $stamp = Get-Date -Format 'yyyyMMdd-HHmmss' $cloudStoreFolder = Join-Path $env:LOCALAPPDATA 'Microsoft\Windows\CloudStore' $cloudStoreKey = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\CloudStore' $backupRoot = Join-Path $env:LOCALAPPDATA 'Microsoft\Windows\Fix-StartMenu-Backup' New-Item -ItemType Directory -Path $backupRoot -Force | Out-Null if (Test-Path -LiteralPath $cloudStoreFolder) { $folderBackup = Join-Path $backupRoot "CloudStore-$stamp" Move-Item -LiteralPath $cloudStoreFolder -Destination $folderBackup Write-Status "CloudStore files backed up to $folderBackup" 'ok' } if (Test-Path -LiteralPath $cloudStoreKey) { $registryBackup = Join-Path $backupRoot "CloudStore-$stamp.reg" & reg.exe export 'HKCU\Software\Microsoft\Windows\CurrentVersion\CloudStore' $registryBackup /y | Out-Null if ($LASTEXITCODE -ne 0) { throw "CloudStore registry backup failed (reg.exe exit code $LASTEXITCODE)." } Remove-Item -LiteralPath $cloudStoreKey -Recurse -Force Write-Status "CloudStore registry backed up to $registryBackup" 'ok' } } function Start-ElevatedSelf { $switches = @() if ($ResetCloudStore) { $switches += '-ResetCloudStore' } if ($NoRebootPrompt) { $switches += '-NoRebootPrompt' } if ($PSCommandPath) { $arguments = @( '-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', "`"$PSCommandPath`"" ) + $switches Start-Process -FilePath 'powershell.exe' -Verb RunAs -ArgumentList $arguments return } # Supports the normal one-liner: # iex (irm -useb fix-startmenu.pages.dev) # $PSCommandPath is empty in that mode, so relaunch the remote script itself. $switchText = $switches -join ' ' $command = "& ([ScriptBlock]::Create((irm -useb '$RemoteScriptUrl'))) $switchText" Start-Process -FilePath 'powershell.exe' -Verb RunAs -ArgumentList ( "-NoProfile -ExecutionPolicy Bypass -Command `"$command`"" ) } function Test-StartMenuLive { $startedAt = Get-Date try { $shell = New-Object -ComObject WScript.Shell $shell.SendKeys('^{ESC}') } catch { Write-Status "Could not send Ctrl+Esc for live verification: $($_.Exception.Message)" 'warn' } Start-Sleep -Seconds 3 $process = Get-Process -Name StartMenuExperienceHost -ErrorAction SilentlyContinue | Where-Object { $_.Responding } | Select-Object -First 1 $newContainerErrors = @(Get-StartMenuAppContainerErrors -Since $startedAt) $newCrashes = @(Get-StartMenuCrashes -Since $startedAt) if ($process -and $newContainerErrors.Count -eq 0 -and $newCrashes.Count -eq 0) { try { if ($shell) { $shell.SendKeys('{ESC}') } } catch {} return $true } return $false } $isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole( [Security.Principal.WindowsBuiltInRole]::Administrator ) if (-not $isAdmin) { Start-ElevatedSelf return } # Keep the existing optional UI, but do not make the repair depend on it. try { Invoke-Expression (Invoke-RestMethod -Uri 'https://psui.pages.dev' -ErrorAction Stop) } catch { Write-Host '[Fix-StartMenu] UI module unavailable; using console output.' } Write-Result 'Fix-StartMenu: UI & Shell Repair' 'Cyan' $startMenuManifest = Get-SystemAppManifest $StartMenuPackageName $shellManifest = Get-SystemAppManifest $ShellPackageName $appContainerErrorsBeforeRepair = @(Get-StartMenuAppContainerErrors) $startMenuCrashesBeforeRepair = @(Get-StartMenuCrashes) if ($appContainerErrorsBeforeRepair.Count -gt 0) { Write-Status ( "Detected $($appContainerErrorsBeforeRepair.Count) recent Start menu AppContainer " + 'error(s), including CreateAppContainerProfile/0x80070005.' ) 'warn' } Write-Status 'Stopping Start menu and shell processes...' Get-Process -Name explorer, StartMenuExperienceHost, ShellExperienceHost, SearchHost, RuntimeBroker -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue $cloudStoreErrors = @( Get-WinEvent -FilterHashtable @{ LogName = 'Microsoft-Windows-CloudStore/Operational' StartTime = (Get-Date).AddDays(-7) } -MaxEvents 200 -ErrorAction SilentlyContinue | Where-Object { $_.LevelDisplayName -eq 'Error' } ) if ($ResetCloudStore -or ($cloudStoreErrors.Count -gt 0 -and $startMenuCrashesBeforeRepair.Count -gt 0)) { Write-Status 'CloudStore errors detected; backing up and resetting shell state...' Backup-AndResetCloudStore $cloudStoreWasReset = $true } else { Write-Status 'No CloudStore failure detected; retaining existing shell personalization...' 'ok' $cloudStoreWasReset = $false } Write-Status 'Restarting the AppX state service...' Get-Service -Name StateRepository -ErrorAction SilentlyContinue | Stop-Service -Force -ErrorAction SilentlyContinue Start-Service -Name StateRepository -ErrorAction SilentlyContinue Write-Status 'Re-registering Start menu and Shell Experience packages...' foreach ($manifest in @($startMenuManifest, $shellManifest)) { Add-AppxPackage -DisableDevelopmentMode -Register $manifest -ForceApplicationShutdown } Write-Status 'Resetting the Start menu package state...' try { Get-AppxPackage -Name $StartMenuPackageName -ErrorAction Stop | Reset-AppxPackage -ErrorAction Stop } catch { # Reset-AppxPackage is useful but not required for the targeted AC repair. Write-Status "Reset-AppxPackage could not complete: $($_.Exception.Message)" 'warn' } # IMPORTANT: Reset-AppxPackage may remove the AppContainer profile. The targeted # AC repair must therefore happen after it. $repairedAcPath = Repair-StartMenuAppContainerProfile Write-Status 'Restarting Explorer...' Start-Process explorer.exe Start-Sleep -Seconds 1 Write-Status 'Verifying Start menu live with Ctrl+Esc...' $startMenuHealthy = Test-StartMenuLive if ($startMenuHealthy) { $summary = 'FULL REPAIR COMPLETED. StartMenuExperienceHost is running, responding, and no new AppContainer/crash event was detected.' if ($cloudStoreWasReset) { $summary += ' CloudStore was reset; its backup is under %LOCALAPPDATA%\Microsoft\Windows\Fix-StartMenu-Backup.' } Write-Result $summary 'Green' Write-Status "Verified AppContainer directory: $repairedAcPath" 'ok' } else { Write-Result ( 'Repair steps completed, but live verification still detected a Start menu failure. ' + 'Check the newest AppModel-Runtime/Admin and Application events before applying broader Windows repair.' ) 'Yellow' if (-not $NoRebootPrompt) { Write-Host 'Restart Windows once, then test Start again. If it still fails, inspect fresh events rather than repeating destructive ACL resets.' -ForegroundColor Yellow } } if (Get-Command 'UI.Pause' -ErrorAction SilentlyContinue) { UI.Pause }