Public/Invoke-ComponentStoreRepairWithISO.ps1
|
function Invoke-ComponentStoreRepairWithISO { <# .SYNOPSIS Enhanced Windows 11 ISO download and comprehensive component store repair. .DESCRIPTION This function performs a comprehensive repair that addresses multiple corruption types: - Component store corruption (Exit Code 193) - InvalidBinary corruption (0xc142011c, 0x8007007b) - WinSxS cache corruption - Download service corruption It includes multiple repair phases with the ISO as a reliable source. .PARAMETER OutputPath Directory where the ISO will be downloaded. Default: C:\Temp .PARAMETER KeepISO Keep the ISO file after repair completes. Default: $false .PARAMETER LogPath Path to the log file for detailed logging. .PARAMETER ComprehensiveRepair Performs additional repair steps beyond basic DISM operations .PARAMETER ProxyServer Proxy server URL for downloads (e.g., "http://proxy.company.com:8080") .PARAMETER ProxyCredential Credentials for proxy authentication .PARAMETER UseSystemProxy Use system proxy settings for downloads .PARAMETER MaxRetries Maximum number of retry attempts for download failures. Default: 3 .EXAMPLE Invoke-ComponentStoreRepairWithISO -ComprehensiveRepair -Verbose .EXAMPLE Invoke-ComponentStoreRepairWithISO -OutputPath "D:\Temp" -KeepISO -ComprehensiveRepair -Verbose .EXAMPLE Invoke-ComponentStoreRepairWithISO -ComprehensiveRepair -ProxyServer "http://proxy:8080" -Verbose .NOTES Enhanced version that addresses InvalidBinary corruption and download failures. Requires 8GB+ free space and internet connectivity. Name: Invoke-ComponentStoreRepairWithISO Author: Anthony Balloi - CSOLVE Version: 2.0.0 #> [CmdletBinding()] param( [Parameter(Mandatory=$false)] [string]$OutputPath = "C:\Temp", [Parameter(Mandatory=$false)] [switch]$KeepISO, [Parameter(Mandatory=$false)] [string]$LogPath, [Parameter(Mandatory=$false)] [switch]$ComprehensiveRepair, [Parameter(Mandatory=$false)] [string]$ProxyServer, [Parameter(Mandatory=$false)] [PSCredential]$ProxyCredential, [Parameter(Mandatory=$false)] [switch]$UseSystemProxy, [Parameter(Mandatory=$false)] [int]$MaxRetries = 3 ) # Admin check $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent()) if (-not $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { throw 'Invoke-ComponentStoreRepairWithISO requires Administrator privileges. Please run PowerShell as Administrator.' } if (-not $LogPath) { $timestamp = Get-Date -Format 'yyyyMMdd-HHmmss' $LogPath = Join-Path $OutputPath "Enhanced-ComponentStoreRepair-$timestamp.log" } $isoPath = $null $mountResult = $null try { Write-Host "=== ENHANCED COMPONENT STORE REPAIR WITH ISO ===" -ForegroundColor Yellow Write-Host "This will perform comprehensive repair for InvalidBinary and download corruption" -ForegroundColor Cyan Write-WULog -Message "=== Enhanced Component Store Repair with ISO Started ===" -LogPath $LogPath # Check for pending reboot first Write-Host "`n[PRE-CHECK] Checking for pending reboot..." -ForegroundColor Magenta $pendingReboot = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired" -ErrorAction SilentlyContinue if ($pendingReboot) { Write-Host "WARNING: Pending reboot detected. Some repairs may be limited until reboot." -ForegroundColor Yellow Write-WULog -Message "WARNING: Pending reboot detected - repairs may be limited" -Level Warning -LogPath $LogPath } # Ensure output directory exists if (-not (Test-Path $OutputPath)) { New-Item -ItemType Directory -Path $OutputPath -Force | Out-Null Write-WULog -Message "Created output directory: $OutputPath" -LogPath $LogPath } # Phase 1: Pre-repair cleanup for InvalidBinary corruption if ($ComprehensiveRepair) { Write-Host "`n[PHASE 1] Pre-repair cleanup for InvalidBinary corruption..." -ForegroundColor Green Write-WULog -Message "Phase 1: Starting pre-repair cleanup for InvalidBinary corruption" -LogPath $LogPath # Stop Windows Update services $services = @('wuauserv', 'cryptsvc', 'bits', 'msiserver', 'trustedinstaller') foreach ($service in $services) { try { Stop-Service -Name $service -Force -ErrorAction SilentlyContinue Write-WULog -Message "Stopped service: $service" -LogPath $LogPath } catch { Write-WULog -Message "Could not stop service $service`: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } } # Clear WinSxS cache and corrupted binaries Write-Host " Clearing WinSxS cache and corrupted binaries..." -ForegroundColor Cyan try { # Clear component store cache $cleanupResult = Start-Process -FilePath "DISM" -ArgumentList "/Online", "/Cleanup-Image", "/StartComponentCleanup", "/ResetBase" -Wait -PassThru -NoNewWindow Write-WULog -Message "Component cleanup exit code: $($cleanupResult.ExitCode)" -LogPath $LogPath # Clear CBS logs and temp files $cbsLogs = @( "$env:SystemRoot\Logs\CBS\*", "$env:SystemRoot\SoftwareDistribution\Download\*", "$env:SystemRoot\System32\catroot2\*" ) foreach ($path in $cbsLogs) { try { Remove-Item -Path $path -Recurse -Force -ErrorAction SilentlyContinue Write-WULog -Message "Cleared: $path" -LogPath $LogPath } catch { Write-WULog -Message "Could not clear $path`: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } } } catch { Write-WULog -Message "Pre-repair cleanup warning: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } } # Phase 2: Download Windows 11 ISO with enhanced resilience Write-Host "`n[PHASE 2] Downloading Windows 11 ISO with enhanced resilience..." -ForegroundColor Green Write-WULog -Message "Phase 2: Starting Windows 11 ISO download to $OutputPath" -LogPath $LogPath # Clean up any partial downloads first Write-Host " Cleaning up any partial downloads..." -ForegroundColor Cyan $partialFiles = Get-ChildItem -Path $OutputPath -Filter "*.tmp" -ErrorAction SilentlyContinue foreach ($partialFile in $partialFiles) { try { Remove-Item -Path $partialFile.FullName -Force Write-WULog -Message "Removed partial download: $($partialFile.Name)" -LogPath $LogPath } catch { Write-WULog -Message "Could not remove partial file $($partialFile.Name): $($_.Exception.Message)" -Level Warning -LogPath $LogPath } } # Build download parameters with proxy support $downloadParams = @{ OutputPath = $OutputPath Force = $true Verbose = $true } if ($ProxyServer) { # Note: This would require enhancing Get-WUWindows11ISO to support proxy Write-Host " Proxy server specified: $ProxyServer" -ForegroundColor Yellow Write-WULog -Message "Proxy server specified: $ProxyServer" -LogPath $LogPath } if ($UseSystemProxy) { Write-Host " Using system proxy settings" -ForegroundColor Yellow Write-WULog -Message "Using system proxy settings" -LogPath $LogPath } # Retry loop for download resilience $downloadAttempt = 0 $isoResult = $null while ($downloadAttempt -lt $MaxRetries -and -not $isoResult) { $downloadAttempt++ if ($downloadAttempt -gt 1) { Write-Host " Download attempt $downloadAttempt of $MaxRetries (previous attempt failed)" -ForegroundColor Yellow Write-WULog -Message "Download retry attempt $downloadAttempt of $MaxRetries" -LogPath $LogPath # Wait before retry Start-Sleep -Seconds (30 * $downloadAttempt) } try { $isoResult = Get-WUWindows11ISO @downloadParams if ($isoResult -and $isoResult.Path -and (Test-Path $isoResult.Path)) { Write-Host " Download successful on attempt $downloadAttempt" -ForegroundColor Green Write-WULog -Message "Download successful on attempt $downloadAttempt" -LogPath $LogPath break } } catch { Write-Host " Download attempt $downloadAttempt failed: $($_.Exception.Message)" -ForegroundColor Red Write-WULog -Message "Download attempt $downloadAttempt failed: $($_.Exception.Message)" -Level Warning -LogPath $LogPath # Clean up any new partial files after failed attempt $newPartialFiles = Get-ChildItem -Path $OutputPath -Filter "*.tmp" -ErrorAction SilentlyContinue foreach ($partialFile in $newPartialFiles) { try { Remove-Item -Path $partialFile.FullName -Force Write-WULog -Message "Cleaned up partial file after failed attempt: $($partialFile.Name)" -LogPath $LogPath } catch { # Ignore cleanup errors } } if ($downloadAttempt -eq $MaxRetries) { throw "All $MaxRetries download attempts failed. Last error: $($_.Exception.Message)" } } } if ($isoResult -and $isoResult.Path -and (Test-Path $isoResult.Path)) { $isoPath = $isoResult.Path $isoSize = [math]::Round((Get-Item $isoPath).Length / 1GB, 2) Write-Host "ISO downloaded successfully: $isoPath ($isoSize GB)" -ForegroundColor Green Write-WULog -Message "ISO download completed: $isoPath ($isoSize GB)" -LogPath $LogPath } else { throw "Failed to download Windows 11 ISO - no valid ISO file returned" } # Phase 3: Mount ISO and validate Write-Host "`n[PHASE 3] Mounting and validating ISO..." -ForegroundColor Green Write-WULog -Message "Phase 3: Mounting ISO image $isoPath" -LogPath $LogPath $mountResult = Mount-DiskImage -ImagePath $isoPath -PassThru $driveLetter = ($mountResult | Get-Volume).DriveLetter $installWim = "${driveLetter}:\sources\install.wim" if (-not (Test-Path $installWim)) { throw "Could not find install.wim at $installWim after mounting ISO" } # Validate install.wim integrity Write-Host " Validating install.wim integrity..." -ForegroundColor Cyan $wimInfo = Start-Process -FilePath "DISM" -ArgumentList "/Get-WimInfo", "/WimFile:$installWim" -Wait -PassThru -NoNewWindow -RedirectStandardOutput "$env:TEMP\wiminfo.txt" if ($wimInfo.ExitCode -eq 0) { Write-Host "install.wim validation successful" -ForegroundColor Green Write-WULog -Message "install.wim validation successful, ready for repair operations" -LogPath $LogPath } else { Write-Warning "install.wim validation failed, proceeding with caution" Write-WULog -Message "install.wim validation failed but proceeding" -Level Warning -LogPath $LogPath } # Phase 4: Enhanced DISM repair operations Write-Host "`n[PHASE 4] Enhanced DISM repair operations..." -ForegroundColor Green Write-WULog -Message "Phase 4: Starting enhanced DISM repair operations" -LogPath $LogPath # Step 4a: ScanHealth (no source parameter needed) Write-Host " Step 4a: Component store scan..." -ForegroundColor Cyan $scanResult = Start-Process -FilePath "DISM" -ArgumentList @( "/Online", "/Cleanup-Image", "/ScanHealth" ) -Wait -PassThru -NoNewWindow Write-WULog -Message "DISM ScanHealth exit code: $($scanResult.ExitCode)" -LogPath $LogPath # Step 4b: CheckHealth Write-Host " Step 4b: Component store health check..." -ForegroundColor Cyan $checkResult = Start-Process -FilePath "DISM" -ArgumentList "/Online", "/Cleanup-Image", "/CheckHealth" -Wait -PassThru -NoNewWindow Write-WULog -Message "DISM CheckHealth exit code: $($checkResult.ExitCode)" -LogPath $LogPath # Step 4c: RestoreHealth with ISO source (main repair) Write-Host " Step 4c: Component store restore with ISO source..." -ForegroundColor Cyan $dismCommand = "DISM /Online /Cleanup-Image /RestoreHealth /Source:${installWim}:1 /LimitAccess" Write-Host " Command: $dismCommand" -ForegroundColor Gray Write-WULog -Message "Executing main repair: $dismCommand" -LogPath $LogPath $restoreResult = Start-Process -FilePath "DISM" -ArgumentList @( "/Online", "/Cleanup-Image", "/RestoreHealth", "/Source:${installWim}:1", "/LimitAccess" ) -Wait -PassThru -NoNewWindow Write-WULog -Message "DISM RestoreHealth with ISO source exit code: $($restoreResult.ExitCode)" -LogPath $LogPath # Phase 5: Post-repair validation and additional fixes if ($ComprehensiveRepair) { Write-Host "`n[PHASE 5] Post-repair validation and additional fixes..." -ForegroundColor Green Write-WULog -Message "Phase 5: Starting post-repair validation and additional fixes" -LogPath $LogPath # Reset Windows Update components Write-Host " Resetting Windows Update components..." -ForegroundColor Cyan try { # Reset Windows Update database Stop-Service -Name 'wuauserv' -Force -ErrorAction SilentlyContinue Remove-Item "$env:SystemRoot\SoftwareDistribution\DataStore\*" -Recurse -Force -ErrorAction SilentlyContinue Remove-Item "$env:SystemRoot\SoftwareDistribution\Download\*" -Recurse -Force -ErrorAction SilentlyContinue # Reset cryptographic services Stop-Service -Name 'cryptsvc' -Force -ErrorAction SilentlyContinue Remove-Item "$env:SystemRoot\System32\catroot2\*" -Recurse -Force -ErrorAction SilentlyContinue Write-WULog -Message "Windows Update components reset completed" -LogPath $LogPath } catch { Write-WULog -Message "Windows Update component reset warning: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } # Register system files Write-Host " Re-registering system files..." -ForegroundColor Cyan try { $regsvr32Files = @( 'wuapi.dll', 'wuaueng.dll', 'wuaueng1.dll', 'wucltui.dll', 'wups.dll', 'wups2.dll', 'wuweb.dll', 'qmgr.dll', 'qmgrprxy.dll', 'wucltux.dll', 'muweb.dll', 'wuwebv.dll' ) foreach ($file in $regsvr32Files) { Start-Process -FilePath 'regsvr32.exe' -ArgumentList "/s", $file -Wait -NoNewWindow -ErrorAction SilentlyContinue } Write-WULog -Message "System files re-registration completed" -LogPath $LogPath } catch { Write-WULog -Message "System file registration warning: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } # Restart services Write-Host " Restarting Windows Update services..." -ForegroundColor Cyan foreach ($service in $services) { try { Start-Service -Name $service -ErrorAction SilentlyContinue Write-WULog -Message "Restarted service: $service" -LogPath $LogPath } catch { Write-WULog -Message "Could not restart service $service`: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } } } # Phase 6: Final validation Write-Host "`n[PHASE 6] Final validation..." -ForegroundColor Green Write-WULog -Message "Phase 6: Final validation of repair results" -LogPath $LogPath $finalScan = Start-Process -FilePath "DISM" -ArgumentList "/Online", "/Cleanup-Image", "/ScanHealth" -Wait -PassThru -NoNewWindow Write-WULog -Message "Final DISM ScanHealth exit code: $($finalScan.ExitCode)" -LogPath $LogPath # Determine overall success $success = ($restoreResult.ExitCode -eq 0) -and ($finalScan.ExitCode -eq 0) if ($success) { Write-Host "Enhanced component store repair completed successfully!" -ForegroundColor Green Write-WULog -Message "Enhanced component store repair completed successfully" -LogPath $LogPath } else { Write-Host "Some repair operations failed. Check logs for details." -ForegroundColor Yellow Write-WULog -Message "Repair completed with some failures - RestoreHealth: $($restoreResult.ExitCode), FinalScan: $($finalScan.ExitCode)" -Level Warning -LogPath $LogPath } # Cleanup ISO Write-Host "`n[CLEANUP] ISO cleanup..." -ForegroundColor Green try { Dismount-DiskImage -ImagePath $isoPath -Confirm:$false Write-Host "ISO unmounted successfully" -ForegroundColor Green Write-WULog -Message "ISO unmounted successfully" -LogPath $LogPath } catch { Write-Warning "Could not unmount ISO: $($_.Exception.Message)" Write-WULog -Message "Warning: Could not unmount ISO: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } if (-not $KeepISO) { try { Remove-Item $isoPath -Force Write-Host "ISO file deleted to save space" -ForegroundColor Green Write-WULog -Message "ISO file deleted to save disk space" -LogPath $LogPath } catch { Write-Warning "Could not delete ISO: $($_.Exception.Message)" Write-WULog -Message "Warning: Could not delete ISO: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } } else { Write-Host "ISO kept at: $isoPath" -ForegroundColor Cyan Write-WULog -Message "ISO file preserved at: $isoPath" -LogPath $LogPath } # Final summary Write-Host "`n=== ENHANCED COMPONENT STORE REPAIR SUMMARY ===" -ForegroundColor Cyan Write-Host "Main Repair Status: $(if ($restoreResult.ExitCode -eq 0) { 'SUCCESS' } else { 'FAILED' })" -ForegroundColor $(if ($restoreResult.ExitCode -eq 0) { 'Green' } else { 'Red' }) Write-Host "Final Validation: $(if ($finalScan.ExitCode -eq 0) { 'HEALTHY' } else { 'ISSUES REMAIN' })" -ForegroundColor $(if ($finalScan.ExitCode -eq 0) { 'Green' } else { 'Yellow' }) Write-Host "Log file: $LogPath" -ForegroundColor Gray if ($pendingReboot) { Write-Host "IMPORTANT: Reboot required to complete repairs" -ForegroundColor Yellow } Write-WULog -Message "=== Enhanced Component Store Repair with ISO Completed ===" -LogPath $LogPath # PowerShell 5.1 compatible object creation $result = New-Object PSObject $result | Add-Member -MemberType NoteProperty -Name Success -Value $success $result | Add-Member -MemberType NoteProperty -Name MainRepairExitCode -Value $restoreResult.ExitCode $result | Add-Member -MemberType NoteProperty -Name FinalScanExitCode -Value $finalScan.ExitCode if ($KeepISO) { $result | Add-Member -MemberType NoteProperty -Name ISOPath -Value $isoPath } else { $result | Add-Member -MemberType NoteProperty -Name ISOPath -Value "Deleted" } $result | Add-Member -MemberType NoteProperty -Name RepairCompleted -Value $success $result | Add-Member -MemberType NoteProperty -Name LogPath -Value $LogPath $result | Add-Member -MemberType NoteProperty -Name PendingReboot -Value ($pendingReboot -ne $null) return $result } catch { $errorMessage = $_.Exception.Message Write-Host "Enhanced repair failed: $errorMessage" -ForegroundColor Red Write-WULog -Message "Enhanced repair failed: $errorMessage" -Level Error -LogPath $LogPath # Cleanup on error try { if ($isoPath -and (Get-DiskImage $isoPath -ErrorAction SilentlyContinue).Attached) { Dismount-DiskImage -ImagePath $isoPath -Confirm:$false Write-WULog -Message "Emergency cleanup: ISO unmounted after error" -LogPath $LogPath } } catch { # Ignore cleanup errors } # PowerShell 5.1 compatible object creation $errorResult = New-Object PSObject $errorResult | Add-Member -MemberType NoteProperty -Name Success -Value $false $errorResult | Add-Member -MemberType NoteProperty -Name Error -Value $errorMessage $errorResult | Add-Member -MemberType NoteProperty -Name RepairCompleted -Value $false $errorResult | Add-Member -MemberType NoteProperty -Name LogPath -Value $LogPath return $errorResult } } |