Private/Get-WUSetupLogsDirect.ps1
|
function Get-WUSetupLogsDirect { <# .SYNOPSIS Direct Windows Setup log parsing for immediate error detection. .DESCRIPTION Lightweight parser that directly analyzes Windows Setup logs to identify specific Windows 11 24H2 failure patterns without external dependencies. Used as fallback when SetupDiag is inconclusive or for faster results. .PARAMETER SetupLogPath Path to Windows Setup logs directory (auto-detected if not provided). .PARAMETER LogPath Path to the WindowsUpdateTools log file. .EXAMPLE $analysis = Get-WUSetupLogsDirect -LogPath "C:\Logs\wu.log" .EXAMPLE $analysis = Get-WUSetupLogsDirect -SetupLogPath "C:\$Windows.~BT\Sources\Panther" -LogPath "C:\Logs\wu.log" .NOTES This is a private function used internally by the WindowsUpdateTools module. Returns detailed analysis of Windows Setup failures with targeted remediation. #> [CmdletBinding()] param( [string]$SetupLogPath, [string]$LogPath ) Write-WULog -Message "Starting direct Windows Setup log analysis" -LogPath $LogPath $analysis = [PSCustomObject]@{ AnalysisSuccessful = $false SetupLogPath = $null FailuresDetected = 0 FailureReasons = @() CriticalErrors = @() TargetedRemediation = @() BlockingItems = @() BlockingDriverDetails = @() SoftwareConflicts = @() ErrorCodes = @() } try { # Auto-detect setup log path if not provided if (-not $SetupLogPath) { $setupPaths = @( "C:\`$Windows.~BT\Sources\Panther", "C:\Windows\Panther", "C:\Windows\Logs\MoSetup" ) foreach ($path in $setupPaths) { if (Test-Path "$path\setuperr.log") { $SetupLogPath = $path Write-WULog -Message "Auto-detected setup logs at: $path" -LogPath $LogPath break } } } if (-not $SetupLogPath -or -not (Test-Path "$SetupLogPath\setuperr.log")) { Write-WULog -Message "No Windows Setup logs found - no recent upgrade attempts detected" -LogPath $LogPath return $analysis } $analysis.SetupLogPath = $SetupLogPath $analysis.AnalysisSuccessful = $true # Phase 1: Parse setuperr.log for critical 24H2 error patterns Write-WULog -Message "Analyzing setuperr.log for critical error patterns..." -LogPath $LogPath $setupErrPath = Join-Path $SetupLogPath "setuperr.log" $setupErrors = Get-Content $setupErrPath # Define error patterns with remediation mapping $errorPatterns = @{ "SdbpGetMatchingInfoBlocksInternal.*TAGREF array insufficient" = @{ Name = "AppraiserTAGREF" Description = "Appraiser compatibility database corruption (TAGREF array insufficient)" Remediation = "Reset Windows Appraiser compatibility database" Function = "Resolve-WUAppraiserIssues" ErrorCode = "TAGREF_CORRUPTION" } "0x80070057.*WU.*configuration.*targeted scans|Failed to set WU internal configuration property.*0x80070057" = @{ Name = "DynamicUpdatesConfig" Description = "Dynamic Updates configuration failure (0x80070057)" Remediation = "Fix Dynamic Updates configuration and add registry fixes" Function = "Resolve-WUDynamicUpdatesIssues" ErrorCode = "0x80070057" } "0x80004005.*download.*updates|Failed to download updates.*0x80004005|CDownloadDUUpdates.*0x80004005" = @{ Name = "DynamicUpdatesDownload" Description = "Dynamic Updates download failure (0x80004005)" Remediation = "Reset Windows Update components and fix download issues" Function = "Resolve-WUDynamicUpdatesIssues" ErrorCode = "0x80004005" } "DriverPackageReader.*0x3|Failed to Open Driver Package 0x3|InitDriverPackageHardwareIds.*0x3" = @{ Name = "DriverStoreCorruption" Description = "Driver Store corruption - missing driver packages (0x3)" Remediation = "Repair Driver Store integrity and remove problematic drivers" Function = "Resolve-WUDriverStoreIssues" ErrorCode = "0x00000003" } 'XML.*format.*"script".*mandatory|Invalid xml format.*script.*attribute is mandatory' = @{ Name = "ComponentStoreXML" Description = "Component Store XML format corruption (missing script attributes)" Remediation = "Repair Component Store and fix XML manifest corruption" Function = "Resolve-WUComponentStore" ErrorCode = "XML_FORMAT" } "0x00000005.*registry|failed to delete reg tree.*0x00000005|pSPRemoveUpgradeRegTree.*0x00000005" = @{ Name = "RegistryPermissions" Description = "Registry permission/access denied errors (0x00000005)" Remediation = "Fix registry permissions and TrustedInstaller ownership" Function = "Resolve-WURegistryPermissions" ErrorCode = "0x00000005" } "0x80070490.*driver|Failed to find.*driver.*0x80070490" = @{ Name = "DriverStoreNotFound" Description = "Driver Store corruption - elements not found (0x80070490)" Remediation = "Rebuild Driver Store integrity" Function = "Resolve-WUDriverStoreIssues" ErrorCode = "0x80070490" } } # Check for each error pattern foreach ($pattern in $errorPatterns.GetEnumerator()) { $patternMatches = $setupErrors | Select-String $pattern.Key if ($patternMatches) { $analysis.FailuresDetected++ $analysis.FailureReasons += $pattern.Value.Description $analysis.CriticalErrors += $pattern.Value.Name $analysis.TargetedRemediation += $pattern.Value.Function $analysis.ErrorCodes += $pattern.Value.ErrorCode Write-WULog -Message "Detected: $($pattern.Value.Description)" -Level Warning -LogPath $LogPath Write-WULog -Message " Matches found: $($patternMatches.Count)" -LogPath $LogPath Write-WULog -Message " Remediation: $($pattern.Value.Remediation)" -LogPath $LogPath } } # Phase 2: Parse ScanResult.xml for blocking items $scanResultPath = Join-Path $SetupLogPath "ScanResult.xml" if (Test-Path $scanResultPath) { Write-WULog -Message "Analyzing ScanResult.xml for compatibility blocks..." -LogPath $LogPath try { $scanContent = Get-Content $scanResultPath -Raw # Find blocking drivers - check both unsigned and potentially misidentified drivers # Pattern 1: Explicitly marked as having unsigned binaries $blockingDriverPattern1 = 'Inf="([^"]+)"[^>]*BlockMigration="True"[^>]*HasSignedBinaries="False"' $blockingDrivers1 = [regex]::Matches($scanContent, $blockingDriverPattern1) # Pattern 2: General blocking drivers (might be misidentified as unsigned) $blockingDriverPattern2 = 'Inf="([^"]+)"[^>]*BlockMigration="True"' $blockingDrivers2 = [regex]::Matches($scanContent, $blockingDriverPattern2) # Combine and deduplicate driver INF names $allBlockingDrivers = @() $allBlockingDrivers += $blockingDrivers1 | ForEach-Object { $_.Groups[1].Value } $allBlockingDrivers += $blockingDrivers2 | ForEach-Object { $_.Groups[1].Value } $uniqueBlockingDrivers = $allBlockingDrivers | Sort-Object -Unique foreach ($driverInf in $uniqueBlockingDrivers) { # Determine if setup logs claim this is unsigned $claimedUnsigned = $blockingDrivers1 | Where-Object { $_.Groups[1].Value -eq $driverInf } $logMessage = if ($claimedUnsigned) { "Found blocking driver flagged as unsigned: $driverInf - Verifying actual signature status..." } else { "Found blocking driver: $driverInf - Resolving details..." } Write-WULog -Message $logMessage -Level Warning -LogPath $LogPath # Resolve detailed driver information with actual signature verification $driverDetails = Resolve-WUDriverDetails -OemInfName $driverInf -LogPath $LogPath $analysis.BlockingDriverDetails += $driverDetails # Check for signature status discrepancy if ($claimedUnsigned -and $driverDetails.IsSigned) { Write-WULog -Message "SIGNATURE DISCREPANCY: Setup logs incorrectly flagged $driverInf as unsigned" -Level Warning -LogPath $LogPath Write-WULog -Message " Actual signature status: SIGNED by $($driverDetails.SignerName)" -LogPath $LogPath Write-WULog -Message " This appears to be a Windows Setup compatibility scanner false positive" -LogPath $LogPath } # Create enhanced blocking item description with signature verification $enhancedDescription = "BLOCKING DRIVER: $driverInf" if ($driverDetails.ResolvedSuccessfully) { $enhancedDescription += "`n Original Name: $($driverDetails.OriginalName)" $enhancedDescription += "`n Provider: $($driverDetails.ProviderName)" $enhancedDescription += "`n Device Class: $($driverDetails.ClassName)" $enhancedDescription += "`n Driver Version: $($driverDetails.DriverVersion) ($($driverDetails.DriverDate))" # Enhanced signature reporting if ($claimedUnsigned -and $driverDetails.IsSigned) { $enhancedDescription += "`n SETUP LOG CLAIM: Unsigned (INCORRECT)" $enhancedDescription += "`n ACTUAL STATUS: SIGNED by $($driverDetails.SignerName)" $enhancedDescription += "`n ANALYSIS: False positive - driver is properly signed" } else { $enhancedDescription += "`n Digital Signature: $($driverDetails.IsSigned) ($($driverDetails.SignerName))" } if ($driverDetails.DeviceDescriptions.Count -gt 0) { $enhancedDescription += "`n Device Types: $($driverDetails.DeviceDescriptions -join ', ')" } if ($driverDetails.AssociatedDevices.Count -gt 0) { $enhancedDescription += "`n Associated Hardware:" foreach ($device in $driverDetails.AssociatedDevices) { $status = if ($device.Present) { "Present" } else { "Not Present" } $enhancedDescription += "`n - $($device.Name) ($status)" } } else { $enhancedDescription += "`n Associated Hardware: None detected (driver may be unused)" } # Enhanced recommendation based on actual signature status $enhancedDescription += "`n RECOMMENDATION: " if ($claimedUnsigned -and $driverDetails.IsSigned) { if ($driverDetails.ProviderName -eq "Microsoft" -or $driverDetails.SignerName -like "*Microsoft*") { $enhancedDescription += "This is a Microsoft-signed driver incorrectly flagged by Windows Setup. Safe to keep - investigate Windows Update compatibility settings." } else { $enhancedDescription += "Driver is properly signed but flagged by Setup. Verify Windows 11 24H2 compatibility with manufacturer." } } elseif (-not $driverDetails.IsSigned) { $enhancedDescription += "Remove this unsigned driver before attempting Windows 11 upgrade" } else { $enhancedDescription += "Verify driver compatibility with Windows 11 24H2" } # Enhanced targeted remediation with signature context if ($claimedUnsigned -and $driverDetails.IsSigned) { $analysis.TargetedRemediation += "Investigate-SignedDriverBlock:$driverInf ($($driverDetails.ClassName) - $($driverDetails.ProviderName)) - False positive detected" } else { $analysis.TargetedRemediation += "Remove-BlockingDriver:$driverInf ($($driverDetails.ClassName) - $($driverDetails.ProviderName))" } } else { $enhancedDescription += "`n Could not resolve driver details - manual investigation required" $analysis.TargetedRemediation += "Remove-BlockingDriver:$driverInf" } $analysis.BlockingItems += $enhancedDescription # Log summary of findings with signature verification if ($driverDetails.ResolvedSuccessfully) { $signatureStatus = if ($claimedUnsigned -and $driverDetails.IsSigned) { "SIGNED (Setup log false positive)" } elseif ($driverDetails.IsSigned) { "SIGNED" } else { "UNSIGNED" } Write-WULog -Message " Resolved as: $($driverDetails.ClassName) driver from $($driverDetails.ProviderName)" -LogPath $LogPath Write-WULog -Message " Signature status: $signatureStatus, Associated devices: $($driverDetails.AssociatedDevices.Count)" -LogPath $LogPath } else { Write-WULog -Message " Could not resolve driver details for $driverInf" -Level Warning -LogPath $LogPath } } # Check for general compatibility blocks if ($scanContent -match 'BlockingType="[^N][^o][^n][^e]"') { $blockingItems = [regex]::Matches($scanContent, 'HardwareType="([^"]+)"[^>]*BlockingType="([^"]+)"') foreach ($block in $blockingItems) { if ($block.Groups[2].Value -ne "None") { $analysis.BlockingItems += "Hardware compatibility block: $($block.Groups[1].Value) ($($block.Groups[2].Value))" Write-WULog -Message "Hardware block: $($block.Groups[1].Value) - $($block.Groups[2].Value)" -Level Warning -LogPath $LogPath } } } } catch { Write-WULog -Message "Error parsing ScanResult.xml: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } } # Phase 3: Parse diagwrn.xml for software conflicts $diagWrnPath = Join-Path $SetupLogPath "diagwrn.xml" if (Test-Path $diagWrnPath) { Write-WULog -Message "Analyzing diagwrn.xml for software conflicts..." -LogPath $LogPath try { $warnContent = Get-Content $diagWrnPath # Known problematic software patterns $conflictPatterns = @{ "FolderLock" = "FolderLock file encryption software" "Intel.*Driver.*Support.*Assistant" = "Intel Driver Support Assistant" "Acronis" = "Acronis backup software" "McAfee" = "McAfee antivirus" "Norton" = "Norton antivirus" "Kaspersky" = "Kaspersky antivirus" "VirtualBox" = "Oracle VirtualBox" "VMware" = "VMware virtualization" } $phantomLogged = @{} foreach ($pattern in $conflictPatterns.GetEnumerator()) { $conflictMatches = $warnContent | Select-String $pattern.Key foreach ($match in $conflictMatches) { $software = $pattern.Value if ($match.Line -match "will remove it") { if (-not $phantomLogged.ContainsKey($software)) { Write-WULog -Message "Cleaning up phantom reference: $software" -LogPath $LogPath $phantomLogged[$software] = $true } } else { $analysis.SoftwareConflicts += $software Write-WULog -Message "Software conflict detected: $software" -Level Warning -LogPath $LogPath } } } } catch { Write-WULog -Message "Error parsing diagwrn.xml: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } } # Phase 4: Parse diagerr.xml for additional structured errors $diagErrPath = Join-Path $SetupLogPath "diagerr.xml" if (Test-Path $diagErrPath) { Write-WULog -Message "Checking diagerr.xml for additional error details..." -LogPath $LogPath try { $errMatches = Select-String -Path $diagErrPath -Pattern 'Msg="([^"]+)"' | Select-Object -First 10 foreach ($match in $errMatches) { $errorMsg = $match.Matches[0].Groups[1].Value # Only log if not already detected in setuperr.log and the message is not empty if (-not [string]::IsNullOrWhiteSpace($errorMsg) -and ($analysis.FailureReasons -notcontains $errorMsg)) { Write-WULog -Message "Additional error from diagerr.xml: $errorMsg" -LogPath $LogPath } } } catch { Write-WULog -Message "Error parsing diagerr.xml: $($_.Exception.Message)" -Level Warning -LogPath $LogPath } } # Summary Write-WULog -Message "Direct log analysis completed:" -LogPath $LogPath Write-WULog -Message " Critical errors found: $($analysis.FailuresDetected)" -LogPath $LogPath Write-WULog -Message " Blocking items: $($analysis.BlockingItems.Count)" -LogPath $LogPath Write-WULog -Message " Blocking drivers resolved: $($analysis.BlockingDriverDetails.Count)" -LogPath $LogPath Write-WULog -Message " Software conflicts: $($analysis.SoftwareConflicts.Count)" -LogPath $LogPath Write-WULog -Message " Targeted remediation functions: $($analysis.TargetedRemediation.Count)" -LogPath $LogPath # Log summary of resolved drivers if ($analysis.BlockingDriverDetails.Count -gt 0) { Write-WULog -Message "Blocking drivers summary:" -LogPath $LogPath foreach ($driver in $analysis.BlockingDriverDetails) { if ($driver.ResolvedSuccessfully) { Write-WULog -Message " $($driver.OemInf): $($driver.ClassName) by $($driver.ProviderName) (Signed: $($driver.IsSigned))" -LogPath $LogPath } else { Write-WULog -Message " $($driver.OemInf): Resolution failed - $($driver.ErrorMessage)" -Level Warning -LogPath $LogPath } } } } catch { Write-WULog -Message "Error during direct setup log analysis: $($_.Exception.Message)" -Level Error -LogPath $LogPath $analysis.AnalysisSuccessful = $false } return $analysis } |