dist/temp/WindowsUpdateTools/Public/Debug-WindowsUpdateAgent.ps1
|
function Debug-WindowsUpdateAgent { <# .SYNOPSIS Advanced debugging tool for Windows Update Agent COM object operations. .DESCRIPTION This function provides detailed, real-time debugging of Windows Update Agent COM operations to diagnose issues like 0x80131501 errors. It includes step-by-step COM object validation, method invocation testing, and comprehensive error analysis. .PARAMETER TestLevel Controls the depth of testing: - Basic: COM object creation and basic properties - Intermediate: Method invocation testing - Advanced: Full update search and download simulation .PARAMETER LogPath Path to write detailed debug logs. If not specified, logs to console only. .EXAMPLE Debug-WindowsUpdateAgent -TestLevel Basic -Verbose .EXAMPLE Debug-WindowsUpdateAgent -TestLevel Advanced -LogPath "C:\Temp\WUA-Debug.log" .NOTES Requires administrative privileges. Designed specifically to diagnose 0x80131501 and similar COM-related errors. Author: CSOLVE Scripts - Advanced Diagnostics Version: 1.0.0 #> [CmdletBinding()] param( [Parameter()] [ValidateSet('Basic', 'Intermediate', 'Advanced')] [string]$TestLevel = 'Intermediate', [Parameter()] [string]$LogPath ) # Enhanced logging function with real-time output function Write-DebugLog { param( [string]$Message, [ValidateSet('Info', 'Warning', 'Error', 'Debug', 'Verbose')] [string]$Level = 'Info', [string]$LogPath ) $timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss.fff' $logEntry = "[$timestamp] [$Level] $Message" # Always write to console with color coding switch ($Level) { 'Error' { Write-Host $logEntry -ForegroundColor Red } 'Warning' { Write-Host $logEntry -ForegroundColor Yellow } 'Debug' { Write-Host $logEntry -ForegroundColor Cyan } 'Verbose' { Write-Host $logEntry -ForegroundColor Gray } default { Write-Host $logEntry -ForegroundColor White } } # Write to log file if specified if ($LogPath) { try { Add-Content -Path $LogPath -Value $logEntry -ErrorAction SilentlyContinue } catch { # Ignore log file errors to prevent cascading issues } } } # Test COM object creation with detailed error reporting function Test-ComObjectCreation { param( [string]$ProgId, [string]$Description ) Write-DebugLog "Testing COM object creation: $Description ($ProgId)" -Level Info try { $comObject = New-Object -ComObject $ProgId Write-DebugLog "SUCCESS: Created $Description" -Level Info Write-DebugLog "Object Type: $($comObject.GetType().FullName)" -Level Debug # Get available methods and properties $methods = $comObject | Get-Member -MemberType Method | Select-Object -ExpandProperty Name $properties = $comObject | Get-Member -MemberType Property | Select-Object -ExpandProperty Name Write-DebugLog "Available Methods: $($methods.Count) - $($methods -join ', ')" -Level Verbose Write-DebugLog "Available Properties: $($properties.Count) - $($properties -join ', ')" -Level Verbose return $comObject } catch [System.Runtime.InteropServices.COMException] { $hresult = [System.String]::Format("0x{0:X8}", $_.Exception.HResult) Write-DebugLog "COM Exception creating $Description" -Level Error Write-DebugLog "HResult: $hresult" -Level Error Write-DebugLog "Message: $($_.Exception.Message)" -Level Error return $null } catch { Write-DebugLog "Unexpected error creating $Description" -Level Error Write-DebugLog "Exception Type: $($_.Exception.GetType().FullName)" -Level Error Write-DebugLog "Message: $($_.Exception.Message)" -Level Error return $null } } # Test method invocation with detailed error capture function Test-MethodInvocation { param( [object]$ComObject, [string]$MethodName, [array]$Parameters = @(), [string]$Description ) Write-DebugLog "Testing method: $MethodName on $Description" -Level Info try { if ($Parameters.Count -eq 0) { $result = $ComObject.$MethodName() } else { $result = $ComObject.$MethodName($Parameters) } Write-DebugLog "SUCCESS: Method $MethodName executed" -Level Info Write-DebugLog "Result Type: $($result.GetType().FullName)" -Level Debug return $result } catch [System.Management.Automation.MethodInvocationException] { $hresult = [System.String]::Format("0x{0:X8}", $_.Exception.InnerException.HResult) Write-DebugLog "Method Invocation Exception for $MethodName" -Level Error Write-DebugLog "HResult: $hresult" -Level Error Write-DebugLog "Message: $($_.Exception.Message)" -Level Error Write-DebugLog "Inner Exception: $($_.Exception.InnerException.Message)" -Level Error return $null } catch [System.Runtime.InteropServices.COMException] { $hresult = [System.String]::Format("0x{0:X8}", $_.Exception.HResult) Write-DebugLog "COM Exception for $MethodName" -Level Error Write-DebugLog "HResult: $hresult" -Level Error Write-DebugLog "Message: $($_.Exception.Message)" -Level Error return $null } catch { Write-DebugLog "Unexpected error for $MethodName" -Level Error Write-DebugLog "Exception Type: $($_.Exception.GetType().FullName)" -Level Error Write-DebugLog "Message: $($_.Exception.Message)" -Level Error return $null } } # Main debugging logic try { Write-DebugLog "=== Windows Update Agent COM Debug Session Started ===" -Level Info Write-DebugLog "Test Level: $TestLevel" -Level Info Write-DebugLog "PowerShell Version: $($PSVersionTable.PSVersion)" -Level Info Write-DebugLog "OS Version: $([System.Environment]::OSVersion)" -Level Info if ($LogPath) { Write-DebugLog "Debug log file: $LogPath" -Level Info } # Step 1: Test basic COM object creation Write-DebugLog "`n--- PHASE 1: COM Object Creation Testing ---" -Level Info $updateSession = Test-ComObjectCreation -ProgId "Microsoft.Update.Session" -Description "Update Session" if (-not $updateSession) { Write-DebugLog "CRITICAL: Cannot create Microsoft.Update.Session - aborting" -Level Error return } # Test UpdateSearcher creation $updateSearcher = Test-MethodInvocation -ComObject $updateSession -MethodName "CreateUpdateSearcher" -Description "UpdateSearcher" if (-not $updateSearcher) { Write-DebugLog "CRITICAL: Cannot create UpdateSearcher - aborting" -Level Error return } # Test UpdateDownloader creation $updateDownloader = Test-MethodInvocation -ComObject $updateSession -MethodName "CreateUpdateDownloader" -Description "UpdateDownloader" if (-not $updateDownloader) { Write-DebugLog "CRITICAL: Cannot create UpdateDownloader - this may be the 0x80131501 issue!" -Level Error return } if ($TestLevel -eq 'Basic') { Write-DebugLog "Basic testing completed successfully" -Level Info return } # Step 2: Test intermediate operations Write-DebugLog "`n--- PHASE 2: Intermediate Operations Testing ---" -Level Info # Test UpdateDownloader properties try { Write-DebugLog "Testing UpdateDownloader properties..." -Level Info $priority = $updateDownloader.Priority Write-DebugLog "Current Priority: $priority" -Level Debug $updateDownloader.Priority = 4 # ExtraHigh Write-DebugLog "Set Priority to ExtraHigh (4)" -Level Debug $isForced = $updateDownloader.IsForced Write-DebugLog "Current IsForced: $isForced" -Level Debug $updateDownloader.IsForced = $true Write-DebugLog "Set IsForced to True" -Level Debug } catch { $hresult = [System.String]::Format("0x{0:X8}", $_.Exception.HResult) Write-DebugLog "Error setting UpdateDownloader properties" -Level Error Write-DebugLog "HResult: $hresult" -Level Error Write-DebugLog "Message: $($_.Exception.Message)" -Level Error } if ($TestLevel -eq 'Intermediate') { Write-DebugLog "Intermediate testing completed" -Level Info return } # Step 3: Advanced testing - actual update operations Write-DebugLog "`n--- PHASE 3: Advanced Update Operations Testing ---" -Level Info # Test update search Write-DebugLog "Testing update search..." -Level Info $searchCriteria = "IsHidden=0 and IsInstalled=0 and Type='Software' and BrowseOnly=0" Write-DebugLog "Search criteria: $searchCriteria" -Level Debug $searchResult = Test-MethodInvocation -ComObject $updateSearcher -MethodName "Search" -Parameters @($searchCriteria) -Description "UpdateSearcher.Search" if ($searchResult) { Write-DebugLog "Search found $($searchResult.Updates.Count) updates" -Level Info if ($searchResult.Updates.Count -gt 0) { # Test setting up downloads Write-DebugLog "Testing download setup..." -Level Info try { $updateCollection = New-Object -ComObject "Microsoft.Update.UpdateColl" $updateCollection.Add($searchResult.Updates.Item(0)) # Add first update $updateDownloader.Updates = $updateCollection Write-DebugLog "Successfully assigned update collection to downloader" -Level Info Write-DebugLog "Updates in downloader collection: $($updateDownloader.Updates.Count)" -Level Debug # This is where 0x80131501 typically occurs - test the Download method Write-DebugLog "CRITICAL TEST: Attempting Download() method..." -Level Warning Write-DebugLog "This is where 0x80131501 errors typically occur" -Level Warning $downloadResult = Test-MethodInvocation -ComObject $updateDownloader -MethodName "Download" -Description "UpdateDownloader.Download" if ($downloadResult) { Write-DebugLog "Download method succeeded!" -Level Info Write-DebugLog "Download ResultCode: $($downloadResult.ResultCode)" -Level Info } else { Write-DebugLog "Download method failed - this confirms the 0x80131501 issue" -Level Error } } catch { $hresult = [System.String]::Format("0x{0:X8}", $_.Exception.HResult) Write-DebugLog "Error during download setup or execution" -Level Error Write-DebugLog "HResult: $hresult" -Level Error Write-DebugLog "Message: $($_.Exception.Message)" -Level Error } } else { Write-DebugLog "No updates found - cannot test download operations" -Level Warning } } Write-DebugLog "`n--- PHASE 4: Environmental Analysis ---" -Level Info # Check Windows Update service status try { $wuService = Get-Service -Name "wuauserv" -ErrorAction SilentlyContinue if ($wuService) { Write-DebugLog "Windows Update Service Status: $($wuService.Status)" -Level Info Write-DebugLog "Windows Update Service StartType: $($wuService.StartType)" -Level Info } else { Write-DebugLog "Windows Update Service not found" -Level Error } } catch { Write-DebugLog "Error checking Windows Update service: $($_.Exception.Message)" -Level Error } # Check for Group Policy interference try { $auOptions = Get-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "NoAutoUpdate" -ErrorAction SilentlyContinue if ($auOptions) { Write-DebugLog "Group Policy NoAutoUpdate detected: $($auOptions.NoAutoUpdate)" -Level Warning } else { Write-DebugLog "No Group Policy interference detected for automatic updates" -Level Info } } catch { Write-DebugLog "Error checking Group Policy settings: $($_.Exception.Message)" -Level Warning } # Check Windows Update Agent version try { $wuaVersion = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate" -Name "Services" -ErrorAction SilentlyContinue if ($wuaVersion) { Write-DebugLog "Windows Update Agent registry path accessible" -Level Info } } catch { Write-DebugLog "Error accessing Windows Update Agent registry: $($_.Exception.Message)" -Level Warning } Write-DebugLog "`n=== Windows Update Agent COM Debug Session Completed ===" -Level Info } catch { Write-DebugLog "Critical error in debug session: $($_.Exception.Message)" -Level Error Write-DebugLog "Exception Type: $($_.Exception.GetType().FullName)" -Level Error if ($_.Exception.HResult -ne 0) { $hresult = [System.String]::Format("0x{0:X8}", $_.Exception.HResult) Write-DebugLog "HResult: $hresult" -Level Error } } finally { # Cleanup COM objects if ($updateDownloader) { try { [System.Runtime.InteropServices.Marshal]::ReleaseComObject($updateDownloader) | Out-Null } catch { } } if ($updateSearcher) { try { [System.Runtime.InteropServices.Marshal]::ReleaseComObject($updateSearcher) | Out-Null } catch { } } if ($updateSession) { try { [System.Runtime.InteropServices.Marshal]::ReleaseComObject($updateSession) | Out-Null } catch { } } Write-DebugLog "COM objects released and session cleaned up" -Level Info } } |