Private/Test-WUComponentStore.ps1
function Test-WUComponentStore { <# .SYNOPSIS Tests Windows Component Store health for corruption issues. .DESCRIPTION Performs component store health assessment using DISM CheckHealth and ScanHealth operations. Also analyzes CBS.log for corruption indicators. .PARAMETER LogPath Path to the log file for detailed logging. .EXAMPLE $componentHealth = Test-WUComponentStore -LogPath "C:\Logs\wu.log" .NOTES This is a private function used internally by the WindowsUpdateTools module. Returns component store health status and corruption indicators. #> [CmdletBinding()] param( [string]$LogPath ) Write-WULog -Message "Testing Component Store health" -LogPath $LogPath # Initialize results object $results = [PSCustomObject]@{ CorruptionDetected = $false HealthCheckPassed = $false ScanHealthPassed = $false CBSLogIssues = 0 Issues = @() CheckHealthExitCode = $null ScanHealthExitCode = $null ErrorMessage = $null } try { # Step 1: DISM CheckHealth (quick check) Write-WULog -Message "Running DISM CheckHealth..." -LogPath $LogPath try { $checkHealthOutput = & dism.exe /online /cleanup-image /checkhealth 2>&1 $results.CheckHealthExitCode = $LASTEXITCODE Write-WULog -Message "DISM CheckHealth exit code: $($results.CheckHealthExitCode)" -LogPath $LogPath if ($results.CheckHealthExitCode -eq 0) { if ($checkHealthOutput -like "*Component Store is repairable*") { $results.CorruptionDetected = $true $results.Issues += "DISM CheckHealth detected repairable component store corruption" Write-WULog -Message "Component store corruption detected by CheckHealth" -Level Warning -LogPath $LogPath } else { $results.HealthCheckPassed = $true Write-WULog -Message "DISM CheckHealth passed - no corruption detected" -LogPath $LogPath } } else { $results.Issues += "DISM CheckHealth failed with exit code: $($results.CheckHealthExitCode)" Write-WULog -Message "DISM CheckHealth failed with exit code: $($results.CheckHealthExitCode)" -Level Warning -LogPath $LogPath } } catch { $results.Issues += "Error running DISM CheckHealth: $($_.Exception.Message)" Write-WULog -Message "Error running DISM CheckHealth: $($_.Exception.Message)" -Level Error -LogPath $LogPath } # Step 2: DISM ScanHealth (more thorough check) - only if CheckHealth passed or we want to be thorough if ($results.HealthCheckPassed -or $results.CorruptionDetected) { Write-WULog -Message "Running DISM ScanHealth for thorough analysis..." -LogPath $LogPath try { $scanHealthOutput = & dism.exe /online /cleanup-image /scanhealth 2>&1 $results.ScanHealthExitCode = $LASTEXITCODE Write-WULog -Message "DISM ScanHealth exit code: $($results.ScanHealthExitCode)" -LogPath $LogPath if ($results.ScanHealthExitCode -eq 0) { if ($scanHealthOutput -like "*Component Store corruption was detected*") { $results.CorruptionDetected = $true $results.Issues += "DISM ScanHealth confirmed component store corruption" Write-WULog -Message "Component store corruption confirmed by ScanHealth" -Level Warning -LogPath $LogPath } else { $results.ScanHealthPassed = $true Write-WULog -Message "DISM ScanHealth passed - no corruption detected" -LogPath $LogPath } } else { $results.Issues += "DISM ScanHealth failed with exit code: $($results.ScanHealthExitCode)" Write-WULog -Message "DISM ScanHealth failed with exit code: $($results.ScanHealthExitCode)" -Level Warning -LogPath $LogPath } } catch { $results.Issues += "Error running DISM ScanHealth: $($_.Exception.Message)" Write-WULog -Message "Error running DISM ScanHealth: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } } # Step 3: Analyze CBS.log for corruption indicators Write-WULog -Message "Analyzing CBS.log for corruption indicators..." -LogPath $LogPath try { $cbsLogPath = "$env:WINDIR\Logs\CBS\CBS.log" if (Test-Path $cbsLogPath) { # Get recent entries (last 200 lines for better coverage) $recentCbsEntries = Get-Content $cbsLogPath -Tail 200 -ErrorAction SilentlyContinue if ($recentCbsEntries) { $corruptionKeywords = @('corrupt', 'corruption', 'failed to repair', 'cannot repair', 'error 0x', 'failed', 'missing') $corruptionIndicators = @() foreach ($line in $recentCbsEntries) { $lineLower = $line.ToLower() foreach ($keyword in $corruptionKeywords) { if ($lineLower -like "*$keyword*" -and $lineLower -notlike "*successfully*") { $corruptionIndicators += $line.Trim() break } } } $results.CBSLogIssues = $corruptionIndicators.Count if ($corruptionIndicators.Count -gt 0) { $results.Issues += "Found $($corruptionIndicators.Count) potential corruption indicators in CBS.log" Write-WULog -Message "Found $($corruptionIndicators.Count) potential corruption indicators in CBS.log" -Level Warning -LogPath $LogPath # Log a few examples (not all to avoid log spam) $sampleIndicators = $corruptionIndicators | Select-Object -First 3 foreach ($indicator in $sampleIndicators) { Write-WULog -Message " CBS Log indicator: $indicator" -LogPath $LogPath } # If we have many indicators, this suggests corruption if ($corruptionIndicators.Count -gt 5) { $results.CorruptionDetected = $true Write-WULog -Message "High number of corruption indicators suggests component store issues" -Level Warning -LogPath $LogPath } } else { Write-WULog -Message "No corruption indicators found in recent CBS.log entries" -LogPath $LogPath } } else { $results.Issues += "Could not read CBS.log entries" Write-WULog -Message "Could not read CBS.log entries" -Level Warning -LogPath $LogPath } } else { $results.Issues += "CBS.log not found at expected location" Write-WULog -Message "CBS.log not found at $cbsLogPath" -Level Warning -LogPath $LogPath } } catch { $results.Issues += "Error analyzing CBS.log: $($_.Exception.Message)" Write-WULog -Message "Error analyzing CBS.log: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } # Step 4: Check for pending component store operations try { $pendingOperations = Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending" if ($pendingOperations) { $results.Issues += "Pending component store operations detected - reboot may be required" Write-WULog -Message "Pending component store operations detected" -Level Warning -LogPath $LogPath } } catch { Write-WULog -Message "Could not check for pending component store operations" -Level Warning -LogPath $LogPath } } catch { $results.ErrorMessage = $_.Exception.Message Write-WULog -Message "Critical error during component store health test: $($_.Exception.Message)" -Level Error -LogPath $LogPath } # Summary Write-WULog -Message "Component Store health test completed:" -LogPath $LogPath Write-WULog -Message " Corruption detected: $($results.CorruptionDetected)" -LogPath $LogPath Write-WULog -Message " Health check passed: $($results.HealthCheckPassed)" -LogPath $LogPath Write-WULog -Message " Scan health passed: $($results.ScanHealthPassed)" -LogPath $LogPath Write-WULog -Message " CBS log issues: $($results.CBSLogIssues)" -LogPath $LogPath Write-WULog -Message " Total issues found: $($results.Issues.Count)" -LogPath $LogPath if ($results.CorruptionDetected) { Write-WULog -Message "RECOMMENDATION: Run component store repair (DISM RestoreHealth)" -Level Warning -LogPath $LogPath } return $results } |