Public/Repair-WindowsUpdate.ps1
function Repair-WindowsUpdate { <# .SYNOPSIS Performs automated Windows Update remediation and repair operations. .DESCRIPTION Repair-WindowsUpdate executes a comprehensive set of Windows Update repair operations to resolve common issues and failures. This function combines multiple remediation strategies based on detected issues or can run comprehensive repairs. .PARAMETER OutputPath Specifies the directory path where log files will be created. Default: C:\Windows\Temp .PARAMETER Comprehensive Run comprehensive remediation that includes all available repair strategies. Use this when the specific issue is unclear or multiple problems are suspected. .PARAMETER ComponentStore Specifically repair Windows Component Store corruption using DISM and SFC. .PARAMETER Services Reset and repair Windows Update services, cache folders, and DLL registration. .PARAMETER SystemPartition Clean up System Reserved Partition to resolve disk space issues. .PARAMETER PassThru Return detailed results as PowerShell objects for further analysis. When not specified, only writes to host and log file. .PARAMETER LogPath Specifies a custom path for the log file. If not provided, automatically generates a timestamped log file in OutputPath. .EXAMPLE Repair-WindowsUpdate Performs comprehensive Windows Update repair with all available strategies. .EXAMPLE Repair-WindowsUpdate -Services -ComponentStore Performs targeted Windows Update service and component store repair. .EXAMPLE $results = Repair-WindowsUpdate -Comprehensive -PassThru if ($results.RebootRequired) { Write-Warning "System restart required to complete repairs" } Performs comprehensive repair and checks if reboot is needed. .EXAMPLE Repair-WindowsUpdate -SystemPartition -OutputPath "C:\Logs" -Verbose Performs System Reserved Partition cleanup with verbose logging. .OUTPUTS When -PassThru is specified, returns a PSCustomObject with: - Success: Boolean indicating if repairs were successful - RebootRequired: Boolean indicating if system restart is needed - ActionsPerformed: Array of repair actions that were executed - IssuesResolved: Count of issues that were resolved - Errors: Array of any errors encountered during repair - LogPath: Path to the detailed log file .NOTES Name: Repair-WindowsUpdate Author: Anthony Balloi - CSOLVE Version: 1.0.0 Requires Administrator privileges for repair operations. Some repairs may require system restart to complete. Always review log files for detailed repair information. #> [CmdletBinding(DefaultParameterSetName = 'Comprehensive')] param( [Parameter(Position = 0)] [ValidateScript({ Test-Path $_ -PathType Container })] [string]$OutputPath = $script:DefaultOutputPath, [Parameter(ParameterSetName = 'Comprehensive')] [switch]$Comprehensive, [Parameter(ParameterSetName = 'Targeted')] [switch]$ComponentStore, [Parameter(ParameterSetName = 'Targeted')] [switch]$Services, [Parameter(ParameterSetName = 'Targeted')] [switch]$SystemPartition, [switch]$PassThru, [string]$LogPath ) begin { # Check for administrator privileges $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent()) if (-not $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { throw "Repair-WindowsUpdate requires Administrator privileges. Please run PowerShell as Administrator." } # Initialize logging if (-not $LogPath) { $timestamp = Get-Date -Format 'yyyyMMdd-HHmmss' $LogPath = Join-Path $OutputPath "WU-Repair-$timestamp.log" } # Initialize the repair results object $results = [PSCustomObject]@{ Success = $false RebootRequired = $false ActionsPerformed = @() IssuesResolved = 0 Errors = @() ComponentResults = @{} RepairDate = Get-Date LogPath = $LogPath } # Start logging Write-WULog -Message "=== Windows Update Repair Started ===" -LogPath $LogPath Write-WULog -Message "Version: $script:ModuleVersion" -LogPath $LogPath Write-WULog -Message "Parameters: OutputPath=$OutputPath, Comprehensive=$Comprehensive, ComponentStore=$ComponentStore, Services=$Services, SystemPartition=$SystemPartition" -LogPath $LogPath $totalErrors = 0 } process { try { Write-Progress -Activity "Windows Update Repair" -Status "Initializing repair operations..." -PercentComplete 5 # Determine repair strategy if ($PSCmdlet.ParameterSetName -eq 'Comprehensive' -or $Comprehensive) { Write-WULog -Message "Starting comprehensive Windows Update repair" -LogPath $LogPath Write-Verbose "Executing comprehensive repair strategy" try { $comprehensiveResult = Invoke-WUComprehensiveRemediation -LogPath $LogPath $results.ComponentResults["Comprehensive"] = $comprehensiveResult if ($comprehensiveResult.Success) { $results.ActionsPerformed += $comprehensiveResult.ActionsPerformed $results.IssuesResolved += $comprehensiveResult.IssuesResolved if ($comprehensiveResult.RebootRequired) { $results.RebootRequired = $true } } } catch { $errorMsg = "Comprehensive repair failed: $($_.Exception.Message)" Write-WULog -Message $errorMsg -Level Error -LogPath $LogPath $results.Errors += $errorMsg $totalErrors++ } } else { # Targeted repairs Write-WULog -Message "Starting targeted Windows Update repairs" -LogPath $LogPath $repairCount = 0 if ($ComponentStore) { Write-Progress -Activity "Windows Update Repair" -Status "Repairing Component Store..." -PercentComplete 25 Write-Verbose "Executing Component Store repair" try { $componentResult = Resolve-WUComponentStore -LogPath $LogPath $results.ComponentResults["ComponentStore"] = $componentResult if ($componentResult.Success) { $results.ActionsPerformed += "Component Store Repair" $results.IssuesResolved++ if ($componentResult.RebootRequired) { $results.RebootRequired = $true } } $repairCount++ } catch { $errorMsg = "Component Store repair failed: $($_.Exception.Message)" Write-WULog -Message $errorMsg -Level Error -LogPath $LogPath $results.Errors += $errorMsg $totalErrors++ } } if ($Services) { Write-Progress -Activity "Windows Update Repair" -Status "Repairing Windows Update Services..." -PercentComplete 50 Write-Verbose "Executing Windows Update Services repair" try { $serviceResult = Resolve-WUGenericErrors -LogPath $LogPath $results.ComponentResults["Services"] = $serviceResult if ($serviceResult.Success) { $results.ActionsPerformed += "Windows Update Services Repair" $results.IssuesResolved++ if ($serviceResult.RebootRequired) { $results.RebootRequired = $true } } $repairCount++ } catch { $errorMsg = "Windows Update Services repair failed: $($_.Exception.Message)" Write-WULog -Message $errorMsg -Level Error -LogPath $LogPath $results.Errors += $errorMsg $totalErrors++ } } if ($SystemPartition) { Write-Progress -Activity "Windows Update Repair" -Status "Cleaning System Reserved Partition..." -PercentComplete 75 Write-Verbose "Executing System Reserved Partition cleanup" try { $partitionResult = Resolve-WUSystemPartition -LogPath $LogPath $results.ComponentResults["SystemPartition"] = $partitionResult if ($partitionResult.Success) { $results.ActionsPerformed += "System Reserved Partition Cleanup" $results.IssuesResolved++ } $repairCount++ } catch { $errorMsg = "System Reserved Partition cleanup failed: $($_.Exception.Message)" Write-WULog -Message $errorMsg -Level Error -LogPath $LogPath $results.Errors += $errorMsg $totalErrors++ } } # If no specific repairs were requested, default to comprehensive if ($repairCount -eq 0) { Write-WULog -Message "No specific repair requested, defaulting to comprehensive repair" -LogPath $LogPath Write-Verbose "No targeted repairs specified, executing comprehensive repair" try { $comprehensiveResult = Invoke-WUComprehensiveRemediation -LogPath $LogPath $results.ComponentResults["Comprehensive"] = $comprehensiveResult if ($comprehensiveResult.Success) { $results.ActionsPerformed += $comprehensiveResult.ActionsPerformed $results.IssuesResolved += $comprehensiveResult.IssuesResolved if ($comprehensiveResult.RebootRequired) { $results.RebootRequired = $true } } } catch { $errorMsg = "Comprehensive repair failed: $($_.Exception.Message)" Write-WULog -Message $errorMsg -Level Error -LogPath $LogPath $results.Errors += $errorMsg $totalErrors++ } } } Write-Progress -Activity "Windows Update Repair" -Status "Finalizing repair operations..." -PercentComplete 95 # Determine overall success if ($results.ActionsPerformed.Count -gt 0 -and $totalErrors -eq 0) { $results.Success = $true } elseif ($results.ActionsPerformed.Count -gt 0 -and $totalErrors -lt $results.ActionsPerformed.Count) { $results.Success = $true # Partial success } } catch { Write-WULog -Message "Critical error during Windows Update repair: $($_.Exception.Message)" -Level Error -LogPath $LogPath $results.Errors += "Critical error during repair: $($_.Exception.Message)" $totalErrors++ } finally { Write-Progress -Activity "Windows Update Repair" -Completed } } end { # Generate summary Write-WULog -Message "=== REPAIR SUMMARY ===" -LogPath $LogPath Write-WULog -Message "Repair Success: $($results.Success)" -LogPath $LogPath Write-WULog -Message "Actions Performed: $($results.ActionsPerformed.Count)" -LogPath $LogPath Write-WULog -Message "Issues Resolved: $($results.IssuesResolved)" -LogPath $LogPath Write-WULog -Message "Errors Encountered: $($results.Errors.Count)" -LogPath $LogPath Write-WULog -Message "Reboot Required: $($results.RebootRequired)" -LogPath $LogPath if ($results.ActionsPerformed.Count -gt 0) { Write-WULog -Message "ACTIONS PERFORMED:" -LogPath $LogPath foreach ($action in $results.ActionsPerformed) { Write-WULog -Message " - $action" -LogPath $LogPath } } if ($results.Errors.Count -gt 0) { Write-WULog -Message "ERRORS ENCOUNTERED:" -LogPath $LogPath foreach ($error in $results.Errors) { Write-WULog -Message " - $error" -Level Error -LogPath $LogPath } } Write-WULog -Message "Log file saved to: $LogPath" -LogPath $LogPath Write-WULog -Message "=== Windows Update Repair Completed ===" -LogPath $LogPath # Display summary to host Write-Host "`n=== Windows Update Repair Results ===" -ForegroundColor Cyan if ($results.Success) { Write-Host "Repair Status: SUCCESS" -ForegroundColor Green Write-Host "Actions Performed: $($results.ActionsPerformed.Count)" -ForegroundColor Green Write-Host "Issues Resolved: $($results.IssuesResolved)" -ForegroundColor Green } else { Write-Host "Repair Status: PARTIAL/FAILED" -ForegroundColor Red Write-Host "Errors: $($results.Errors.Count)" -ForegroundColor Red } if ($results.RebootRequired) { Write-Host "REBOOT REQUIRED: Some repairs require system restart to complete" -ForegroundColor Yellow } Write-Host "Log file: $LogPath" -ForegroundColor Gray # Return results if PassThru requested if ($PassThru) { return $results } # Set exit code based on results if ($results.Success -and $results.Errors.Count -eq 0) { if ($results.RebootRequired) { $global:LASTEXITCODE = $script:ExitCodes.RebootRequired } else { $global:LASTEXITCODE = $script:ExitCodes.Success } } elseif ($results.Success) { $global:LASTEXITCODE = $script:ExitCodes.PartialSuccess } else { $global:LASTEXITCODE = $script:ExitCodes.Failure } } } |