Private/Resolve-WUComponentStore.ps1
function Resolve-WUComponentStore { <# .SYNOPSIS Repairs Windows Component Store corruption issues. .DESCRIPTION Performs comprehensive Component Store health assessment and repair using DISM and System File Checker (SFC) tools. Follows Microsoft recommended sequence for maximum effectiveness. .PARAMETER LogPath Path to the log file for detailed logging. .EXAMPLE $result = Resolve-WUComponentStore -LogPath "C:\Logs\wu.log" .NOTES This function requires Administrator privileges. Returns an object with Success, ActionsPerformed, and RebootRequired properties. Repair sequence follows Microsoft best practices: 1. DISM CheckHealth 2. DISM ScanHealth 3. DISM RestoreHealth 4. SFC ScanNow (after DISM RestoreHealth) 5. DISM StartComponentCleanup with ResetBase #> [CmdletBinding()] param( [string]$LogPath ) # Initialize result object $result = [PSCustomObject]@{ Success = $false RebootRequired = $true # Component store repair typically requires reboot ActionsPerformed = @() ErrorMessage = $null CorruptionDetected = $false CorruptionRepaired = $false } Write-WULog -Message "Starting Component Store repair with enhanced sequence" -LogPath $LogPath try { # Step 1: Check component store health Write-WULog -Message "Step 1: Checking component store health..." -LogPath $LogPath try { $checkHealthOutput = & dism.exe /online /cleanup-image /checkhealth 2>&1 $checkHealthExitCode = $LASTEXITCODE Write-WULog -Message "DISM CheckHealth exit code: $checkHealthExitCode" -LogPath $LogPath if ($checkHealthOutput -like "*Component Store is repairable*") { $result.CorruptionDetected = $true Write-WULog -Message "Component store corruption detected - proceeding with repair" -Level Warning -LogPath $LogPath } elseif ($checkHealthExitCode -eq 0) { Write-WULog -Message "Component store appears healthy, but continuing with repair sequence" -LogPath $LogPath } else { Write-WULog -Message "DISM CheckHealth failed with exit code: $checkHealthExitCode" -Level Warning -LogPath $LogPath } $result.ActionsPerformed += "DISM CheckHealth" } catch { Write-WULog -Message "Error during DISM CheckHealth: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } # Step 2: Scan for component store corruption (more thorough) Write-WULog -Message "Step 2: Scanning for component store corruption..." -LogPath $LogPath try { $scanHealthOutput = & dism.exe /online /cleanup-image /scanhealth 2>&1 $scanHealthExitCode = $LASTEXITCODE Write-WULog -Message "DISM ScanHealth exit code: $scanHealthExitCode" -LogPath $LogPath if ($scanHealthOutput -like "*Component Store corruption was detected*") { $result.CorruptionDetected = $true Write-WULog -Message "DISM ScanHealth confirmed component store corruption" -Level Warning -LogPath $LogPath } elseif ($scanHealthExitCode -eq 0) { Write-WULog -Message "DISM ScanHealth completed - no corruption detected" -LogPath $LogPath } else { Write-WULog -Message "DISM ScanHealth failed with exit code: $scanHealthExitCode" -Level Warning -LogPath $LogPath } $result.ActionsPerformed += "DISM ScanHealth" } catch { Write-WULog -Message "Error during DISM ScanHealth: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } # Step 3: Repair component store Write-WULog -Message "Step 3: Repairing component store..." -LogPath $LogPath try { # This can take a very long time, so log start time $restoreStartTime = Get-Date Write-WULog -Message "Starting DISM RestoreHealth at $($restoreStartTime.ToString('HH:mm:ss')) - this may take 15-30 minutes" -LogPath $LogPath $restoreHealthOutput = & dism.exe /online /cleanup-image /restorehealth 2>&1 $restoreHealthExitCode = $LASTEXITCODE $restoreEndTime = Get-Date $restoreDuration = $restoreEndTime - $restoreStartTime Write-WULog -Message "DISM RestoreHealth completed in $($restoreDuration.ToString('mm\:ss')) with exit code: $restoreHealthExitCode" -LogPath $LogPath if ($restoreHealthExitCode -eq 0) { Write-WULog -Message "DISM RestoreHealth completed successfully" -LogPath $LogPath $result.CorruptionRepaired = $true } else { Write-WULog -Message "DISM RestoreHealth failed with exit code: $restoreHealthExitCode" -Level Warning -LogPath $LogPath Write-WULog -Message "This may indicate network connectivity issues or corrupted Windows Update cache" -Level Warning -LogPath $LogPath # Log output for debugging if there were issues if ($restoreHealthOutput) { Write-WULog -Message "DISM RestoreHealth output: $($restoreHealthOutput -join ' ')" -Level Warning -LogPath $LogPath } } $result.ActionsPerformed += "DISM RestoreHealth" } catch { Write-WULog -Message "Error during DISM RestoreHealth: $($_.Exception.Message)" -Level Error -LogPath $LogPath } # Step 4: Run System File Checker (CRITICAL: After DISM RestoreHealth) Write-WULog -Message "Step 4: Running System File Checker..." -LogPath $LogPath try { $sfcStartTime = Get-Date Write-WULog -Message "Starting SFC ScanNow at $($sfcStartTime.ToString('HH:mm:ss')) - this may take 10-20 minutes" -LogPath $LogPath $sfcOutput = & sfc /scannow 2>&1 $sfcExitCode = $LASTEXITCODE $sfcEndTime = Get-Date $sfcDuration = $sfcEndTime - $sfcStartTime Write-WULog -Message "SFC ScanNow completed in $($sfcDuration.ToString('mm\:ss')) with exit code: $sfcExitCode" -LogPath $LogPath # Parse SFC output for meaningful results if ($sfcOutput -like "*Windows Resource Protection found corrupt files and successfully repaired them*") { Write-WULog -Message "SFC found and repaired corrupt files" -LogPath $LogPath $result.CorruptionRepaired = $true } elseif ($sfcOutput -like "*Windows Resource Protection found corrupt files but was unable to fix some of them*") { Write-WULog -Message "SFC found corrupt files but could not repair all of them" -Level Warning -LogPath $LogPath Write-WULog -Message "Check CBS.log for details: $env:WINDIR\Logs\CBS\CBS.log" -LogPath $LogPath } elseif ($sfcOutput -like "*Windows Resource Protection did not find any integrity violations*") { Write-WULog -Message "SFC found no integrity violations" -LogPath $LogPath } else { Write-WULog -Message "SFC completed with unexpected output - check system for issues" -Level Warning -LogPath $LogPath } $result.ActionsPerformed += "SFC ScanNow" } catch { Write-WULog -Message "Error during SFC ScanNow: $($_.Exception.Message)" -Level Error -LogPath $LogPath } # Step 5: Clean up component store and reset base Write-WULog -Message "Step 5: Cleaning up component store..." -LogPath $LogPath try { $cleanupStartTime = Get-Date Write-WULog -Message "Starting component cleanup with reset base - this may take 10-15 minutes" -LogPath $LogPath $cleanupOutput = & dism.exe /online /cleanup-image /startcomponentcleanup /resetbase 2>&1 $cleanupExitCode = $LASTEXITCODE $cleanupEndTime = Get-Date $cleanupDuration = $cleanupEndTime - $cleanupStartTime Write-WULog -Message "Component cleanup completed in $($cleanupDuration.ToString('mm\:ss')) with exit code: $cleanupExitCode" -LogPath $LogPath # Log cleanup output for debugging if there were issues if ($cleanupExitCode -ne 0 -and $cleanupOutput) { Write-WULog -Message "DISM cleanup output: $($cleanupOutput -join ' ')" -Level Warning -LogPath $LogPath } if ($cleanupExitCode -eq 0) { Write-WULog -Message "Component store cleanup completed successfully" -LogPath $LogPath } else { Write-WULog -Message "Component store cleanup failed with exit code: $cleanupExitCode" -Level Warning -LogPath $LogPath } $result.ActionsPerformed += "DISM StartComponentCleanup with ResetBase" } catch { Write-WULog -Message "Error during component store cleanup: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } # Additional step: Check CBS.log for any remaining issues try { $cbsLogPath = "$env:WINDIR\Logs\CBS\CBS.log" if (Test-Path $cbsLogPath) { Write-WULog -Message "Checking CBS.log for recent corruption indicators..." -LogPath $LogPath # Get recent entries (last 50 lines should be sufficient) $recentCbsEntries = Get-Content $cbsLogPath -Tail 50 -ErrorAction SilentlyContinue $corruptionKeywords = @('corrupt', 'failed to repair', 'cannot repair', 'error', 'failed') $recentCorruption = $recentCbsEntries | Where-Object { $line = $_.ToLower() $corruptionKeywords | Where-Object { $line -like "*$_*" } } if ($recentCorruption) { Write-WULog -Message "Found $($recentCorruption.Count) potential issues in recent CBS.log entries" -Level Warning -LogPath $LogPath Write-WULog -Message "Review full CBS.log at: $cbsLogPath" -LogPath $LogPath } else { Write-WULog -Message "No recent corruption indicators found in CBS.log" -LogPath $LogPath } } } catch { Write-WULog -Message "Could not analyze CBS.log: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } # Determine overall success if ($result.ActionsPerformed.Count -gt 0) { $result.Success = $true Write-WULog -Message "Component store repair sequence completed successfully" -LogPath $LogPath } } catch { $result.ErrorMessage = $_.Exception.Message Write-WULog -Message "Critical error during component store repair: $($_.Exception.Message)" -Level Error -LogPath $LogPath } # Summary if ($result.Success) { Write-WULog -Message "Component Store remediation completed" -LogPath $LogPath Write-WULog -Message "Actions performed:" -LogPath $LogPath foreach ($action in $result.ActionsPerformed) { Write-WULog -Message " - $action" -LogPath $LogPath } if ($result.CorruptionDetected) { if ($result.CorruptionRepaired) { Write-WULog -Message "Component store corruption was detected and repaired" -LogPath $LogPath } else { Write-WULog -Message "Component store corruption was detected but repair status uncertain" -Level Warning -LogPath $LogPath } } Write-WULog -Message "RECOMMENDATION: Restart the system to complete component store repair" -Level Warning -LogPath $LogPath } else { Write-WULog -Message "Component Store remediation failed: $($result.ErrorMessage)" -Level Error -LogPath $LogPath } return $result } |