dist/temp/WindowsUpdateTools/Private/Resolve-WUAppraiserIssues.ps1
|
function Resolve-WUAppraiserIssues { <# .SYNOPSIS Resolves Windows Appraiser compatibility database corruption issues. .DESCRIPTION Fixes SdbpGetMatchingInfoBlocksInternal TAGREF array insufficient errors by resetting the Windows Appraiser compatibility database and clearing corrupted AppCompatFlags registry entries. .PARAMETER LogPath Path to the log file for detailed logging. .EXAMPLE $result = Resolve-WUAppraiserIssues -LogPath "C:\Logs\wu.log" .NOTES This is a private function used internally by the WindowsUpdateTools module. Requires Administrator privileges for registry modification. Returns an object with Success, ActionsPerformed, and RebootRequired properties. #> [CmdletBinding()] param( [string]$LogPath ) # Initialize result object $result = [PSCustomObject]@{ Success = $false RebootRequired = $false ActionsPerformed = @() IssuesResolved = 0 ErrorMessage = $null AppraiserTaskTriggered = $false DatabaseReset = $false } Write-WULog -Message "Starting Windows Appraiser issues remediation" -LogPath $LogPath try { # Step 1: Stop Windows Update Medic Service (if running) Write-WULog -Message "Step 1: Stopping Windows Update Medic Service..." -LogPath $LogPath try { $medicService = Get-Service -Name "WaaSMedicSvc" -ErrorAction SilentlyContinue if ($medicService -and $medicService.Status -eq 'Running') { Stop-Service -Name "WaaSMedicSvc" -Force -ErrorAction Stop Write-WULog -Message "Stopped WaaSMedicSvc service" -LogPath $LogPath $result.ActionsPerformed += "Stopped WaaSMedicSvc" } } catch { Write-WULog -Message "Could not stop WaaSMedicSvc (may not be running): $($_.Exception.Message)" -Level Warning -LogPath $LogPath } # Step 2: Clear corrupted AppCompatFlags registry Write-WULog -Message "Step 2: Clearing corrupted AppCompatFlags registry..." -LogPath $LogPath try { $appCompatPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags" if (Test-Path $appCompatPath) { # Backup the current AppCompatFlags before deletion $backupPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags_Backup_$(Get-Date -Format 'yyyyMMdd_HHmmss')" try { Copy-Item -Path $appCompatPath -Destination $backupPath -Recurse -ErrorAction Stop Write-WULog -Message "Created backup of AppCompatFlags at: $backupPath" -LogPath $LogPath } catch { Write-WULog -Message "Could not create backup of AppCompatFlags: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } # Remove the corrupted AppCompatFlags Remove-Item -Path $appCompatPath -Recurse -Force -ErrorAction Stop Write-WULog -Message "Removed corrupted AppCompatFlags registry tree" -LogPath $LogPath $result.ActionsPerformed += "Reset AppCompatFlags registry" $result.DatabaseReset = $true $result.IssuesResolved++ } else { Write-WULog -Message "AppCompatFlags registry path not found" -LogPath $LogPath } } catch { Write-WULog -Message "Error clearing AppCompatFlags registry: $($_.Exception.Message)" -Level Error -LogPath $LogPath $result.ErrorMessage = "Failed to clear AppCompatFlags: $($_.Exception.Message)" } # Step 3: Clear Appraiser cache files Write-WULog -Message "Step 3: Clearing Appraiser cache files..." -LogPath $LogPath try { $appraiserCachePaths = @( "$env:TEMP\Microsoft\Windows\appraiser", "$env:ProgramData\Microsoft\Windows\appraiser" ) foreach ($cachePath in $appraiserCachePaths) { if (Test-Path $cachePath) { $cacheFiles = Get-ChildItem -Path $cachePath -Force -ErrorAction SilentlyContinue if ($cacheFiles) { Remove-Item -Path "$cachePath\*" -Recurse -Force -ErrorAction SilentlyContinue Write-WULog -Message "Cleared Appraiser cache: $cachePath" -LogPath $LogPath $result.ActionsPerformed += "Cleared Appraiser cache ($cachePath)" } } } } catch { Write-WULog -Message "Error clearing Appraiser cache: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } # Step 4: Trigger manual Appraiser task execution Write-WULog -Message "Step 4: Triggering Windows Appraiser task..." -LogPath $LogPath try { # Check if Appraiser task exists $appraiserTask = Get-ScheduledTask -TaskName "Microsoft Compatibility Appraiser" -TaskPath "\Microsoft\Windows\Application Experience\" -ErrorAction SilentlyContinue if ($appraiserTask) { # Start the Appraiser task Start-ScheduledTask -TaskName "Microsoft Compatibility Appraiser" -TaskPath "\Microsoft\Windows\Application Experience\" -ErrorAction Stop Write-WULog -Message "Triggered Microsoft Compatibility Appraiser task" -LogPath $LogPath $result.ActionsPerformed += "Triggered Appraiser task execution" $result.AppraiserTaskTriggered = $true # Wait a moment for task to start Start-Sleep -Seconds 3 # Check task status $taskStatus = Get-ScheduledTask -TaskName "Microsoft Compatibility Appraiser" -TaskPath "\Microsoft\Windows\Application Experience\" | Get-ScheduledTaskInfo Write-WULog -Message "Appraiser task status: $($taskStatus.LastTaskResult)" -LogPath $LogPath } else { Write-WULog -Message "Microsoft Compatibility Appraiser scheduled task not found" -Level Warning -LogPath $LogPath } } catch { Write-WULog -Message "Error triggering Appraiser task: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } # Step 5: Reset Windows Update Agent configuration Write-WULog -Message "Step 5: Resetting Windows Update Agent configuration..." -LogPath $LogPath try { # Reset Windows Update policies that might affect compatibility scanning $wuPolicyPaths = @( "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate", "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\OSUpgrade" ) foreach ($policyPath in $wuPolicyPaths) { if (Test-Path $policyPath) { # Check for problematic policy values $auOptions = Get-ItemProperty -Path "$policyPath\AU" -Name "AUOptions" -ErrorAction SilentlyContinue if ($auOptions -and $auOptions.AUOptions -eq 1) { Write-WULog -Message "Found disabled AU options - this may interfere with compatibility scanning" -Level Warning -LogPath $LogPath } } } $result.ActionsPerformed += "Checked Windows Update configuration" } catch { Write-WULog -Message "Error checking Windows Update configuration: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } # Step 6: Restart Windows Update Medic Service Write-WULog -Message "Step 6: Restarting Windows Update Medic Service..." -LogPath $LogPath try { $medicService = Get-Service -Name "WaaSMedicSvc" -ErrorAction SilentlyContinue if ($medicService) { Start-Service -Name "WaaSMedicSvc" -ErrorAction Stop Write-WULog -Message "Restarted WaaSMedicSvc service" -LogPath $LogPath $result.ActionsPerformed += "Restarted WaaSMedicSvc" } } catch { Write-WULog -Message "Could not restart WaaSMedicSvc: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } # Determine overall success if ($result.DatabaseReset -and $result.ActionsPerformed.Count -gt 0) { $result.Success = $true Write-WULog -Message "Appraiser issues remediation completed successfully" -LogPath $LogPath } } catch { $result.ErrorMessage = $_.Exception.Message Write-WULog -Message "Critical error during Appraiser remediation: $($_.Exception.Message)" -Level Error -LogPath $LogPath } # Summary Write-WULog -Message "Appraiser remediation summary:" -LogPath $LogPath Write-WULog -Message " Success: $($result.Success)" -LogPath $LogPath Write-WULog -Message " Database reset: $($result.DatabaseReset)" -LogPath $LogPath Write-WULog -Message " Appraiser task triggered: $($result.AppraiserTaskTriggered)" -LogPath $LogPath Write-WULog -Message " Actions performed: $($result.ActionsPerformed.Count)" -LogPath $LogPath if ($result.ActionsPerformed.Count -gt 0) { Write-WULog -Message "Actions completed:" -LogPath $LogPath foreach ($action in $result.ActionsPerformed) { Write-WULog -Message " - $action" -LogPath $LogPath } } if ($result.Success) { Write-WULog -Message "RECOMMENDATION: Run Windows Update compatibility check again to verify TAGREF array issues are resolved" -LogPath $LogPath } return $result } |