Private/Remove-WUProblematicDrivers.ps1
|
function Remove-WUProblematicDrivers { <# .SYNOPSIS Identifies and remediates problematic drivers that may interfere with Windows Updates and upgrades. .DESCRIPTION Scans for both configuration errors and Windows Setup blocking drivers. Provides specific remediation for drivers identified in Windows 11 upgrade compatibility scans, including handling false positives where signed drivers are incorrectly flagged as unsigned by Windows Setup. .PARAMETER LogPath Path to the log file for detailed logging. .PARAMETER RemoveAction Specifies the action to take for blocking drivers. Valid values: - 'Identify' (default): Only identify and log drivers - 'DisableDevice': Disable devices associated with blocking drivers - 'UninstallDriver': Uninstall the driver package (use with caution) .EXAMPLE $result = Remove-WUProblematicDrivers -LogPath "C:\Logs\wu.log" .EXAMPLE $result = Remove-WUProblematicDrivers -LogPath "C:\Logs\wu.log" -RemoveAction "DisableDevice" .NOTES This is a private function used internally by the WindowsUpdateTools module. Returns an object with Success, DriversRemoved, and ActionsPerformed properties. Uses Get-WUSetupLogsDirect internally to analyze Windows Setup logs. #> [CmdletBinding()] param( [string]$LogPath, [ValidateSet('Identify', 'DisableDevice', 'UninstallDriver')] [string]$RemoveAction = 'Identify' ) $result = [PSCustomObject]@{ Success = $false DriversRemoved = 0 DriversDisabled = 0 BlockingDriversFound = 0 SignatureDiscrepancies = 0 ActionsPerformed = @() BlockingDriverDetails = @() DeviceConfigErrors = 0 PrinterDriversRemoved = 0 PrinterDriversReinstalled = 0 } # Helper function to clean Microsoft virtual printer drivers function Clean-MicrosoftPrinterDrivers { param( [string]$LogPath, [string]$RemoveAction ) $removedDrivers = @() $targets = @( "Microsoft XPS Document Writer", "Microsoft Print To PDF" ) foreach ($targetDriver in $targets) { # Remove any printers using this driver $printersUsingDriver = Get-Printer -ErrorAction SilentlyContinue | Where-Object { $_.DriverName -like "$targetDriver*" } foreach ($printer in $printersUsingDriver) { Write-WULog -Message " -> Removing printer: $($printer.Name) (Driver: $($printer.DriverName))" -LogPath $LogPath try { Remove-Printer -Name $printer.Name -ErrorAction Stop Write-WULog -Message " Successfully removed printer: $($printer.Name)" -LogPath $LogPath } catch { Write-WULog -Message " Failed to remove printer: $($printer.Name) - $($_.Exception.Message)" -Level Warning -LogPath $LogPath } } # Remove the printer driver $driver = Get-PrinterDriver -ErrorAction SilentlyContinue | Where-Object { $_.Name -like "$targetDriver*" } if ($driver) { Write-WULog -Message " Removing driver: $($driver.Name)" -LogPath $LogPath try { Remove-PrinterDriver -Name $driver.Name -ErrorAction Stop Write-WULog -Message " Successfully removed driver: $($driver.Name)" -LogPath $LogPath $removedDrivers += $driver.Name } catch { Write-WULog -Message " Failed to remove driver: $($driver.Name) - $($_.Exception.Message)" -Level Warning -LogPath $LogPath } } else { Write-WULog -Message " Driver not found: $targetDriver" -LogPath $LogPath } } # Reinstall if any were removed and RemoveAction allows it if ($RemoveAction -ne 'Identify') { if ($removedDrivers -match "Microsoft Print to PDF") { Write-WULog -Message " Reinstalling Microsoft Print to PDF..." -LogPath $LogPath try { Add-WindowsCapability -Online -Name "Printing.PrintToPDF~~~~0.0.1.0" -ErrorAction Stop | Out-Null Write-WULog -Message " Successfully reinstalled Microsoft Print to PDF" -LogPath $LogPath $result.PrinterDriversReinstalled++ } catch { Write-WULog -Message " Failed to reinstall Microsoft Print to PDF - $($_.Exception.Message)" -Level Warning -LogPath $LogPath } } if ($removedDrivers -match "Microsoft XPS Document Writer") { Write-WULog -Message " Reinstalling Microsoft XPS Document Writer..." -LogPath $LogPath try { Add-WindowsCapability -Online -Name "Printing.XPSServices~~~~0.0.1.0" -ErrorAction Stop | Out-Null Write-WULog -Message " Successfully reinstalled Microsoft XPS Document Writer" -LogPath $LogPath $result.PrinterDriversReinstalled++ } catch { Write-WULog -Message " Failed to reinstall Microsoft XPS Document Writer - $($_.Exception.Message)" -Level Warning -LogPath $LogPath } } } if (-not $removedDrivers) { Write-WULog -Message " No matching Microsoft printer drivers found for removal" -LogPath $LogPath } else { $result.PrinterDriversRemoved += $removedDrivers.Count } return $removedDrivers.Count } try { Write-WULog -Message "Checking for problematic drivers and Windows Setup blocking drivers..." -LogPath $LogPath # Phase 1: Get blocking drivers using existing module function Write-WULog -Message "Analyzing Windows Setup logs for blocking drivers..." -LogPath $LogPath $setupAnalysis = Get-WUSetupLogsDirect -LogPath $LogPath $microsoftPrinterDriverDetected = $false if ($setupAnalysis.AnalysisSuccessful -and $setupAnalysis.BlockingDriverDetails.Count -gt 0) { Write-WULog -Message "Found $($setupAnalysis.BlockingDriverDetails.Count) blocking drivers from setup analysis" -LogPath $LogPath $result.BlockingDriversFound = $setupAnalysis.BlockingDriverDetails.Count $result.ActionsPerformed += "Analyzed Windows Setup blocking drivers" foreach ($driverDetails in $setupAnalysis.BlockingDriverDetails) { Write-WULog -Message "Processing blocking driver: $($driverDetails.OemInf)" -LogPath $LogPath $result.BlockingDriverDetails += $driverDetails # Check if this is a Microsoft virtual printer driver issue if ($driverDetails.ProviderName -eq "Microsoft" -and ($driverDetails.ClassName -like "*Print*" -or $driverDetails.OemInf -like "*print*" -or $driverDetails.OemInf -like "*xps*")) { $microsoftPrinterDriverDetected = $true Write-WULog -Message " DETECTED: Microsoft virtual printer driver blocking upgrade" -Level Warning -LogPath $LogPath } # Check for signature status discrepancy (already identified in Get-WUSetupLogsDirect) $isSignatureDiscrepancy = $false if ($driverDetails.ResolvedSuccessfully -and $driverDetails.IsSigned) { # Look for indicators that this was flagged as unsigned by setup but is actually signed if ($driverDetails.ProviderName -eq "Microsoft" -or $driverDetails.SignerName -like "*Microsoft*") { $isSignatureDiscrepancy = $true $result.SignatureDiscrepancies++ Write-WULog -Message "SIGNATURE DISCREPANCY: $($driverDetails.OemInf) is Microsoft-signed but was flagged by Windows Setup" -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 } } if ($driverDetails.ResolvedSuccessfully) { $signatureStatus = if ($isSignatureDiscrepancy) { "SIGNED (Setup log false positive)" } elseif ($driverDetails.IsSigned) { "SIGNED" } else { "UNSIGNED" } Write-WULog -Message " Driver details: $($driverDetails.ClassName) from $($driverDetails.ProviderName)" -LogPath $LogPath Write-WULog -Message " Signature status: $signatureStatus" -LogPath $LogPath Write-WULog -Message " Associated devices: $($driverDetails.AssociatedDevices.Count)" -LogPath $LogPath } # Perform remediation based on RemoveAction parameter if ($RemoveAction -ne 'Identify') { if ($isSignatureDiscrepancy -and $driverDetails.IsSigned) { Write-WULog -Message " RECOMMENDATION: Driver is properly signed - investigate Windows Update compatibility settings instead of removing" -Level Warning -LogPath $LogPath } else { # Only proceed with removal/disabling for actually problematic drivers if ($driverDetails.AssociatedDevices.Count -gt 0) { foreach ($device in $driverDetails.AssociatedDevices) { if ($device.Present) { try { if ($RemoveAction -eq 'DisableDevice') { # Disable the device Disable-PnpDevice -InstanceId $device.InstanceId -Confirm:$false -ErrorAction Stop | Out-Null Write-WULog -Message " Disabled device: $($device.Name)" -LogPath $LogPath $result.DriversDisabled++ } elseif ($RemoveAction -eq 'UninstallDriver') { # Remove the driver package (more aggressive) $null = pnputil.exe /delete-driver $driverDetails.OemInf /uninstall /force Write-WULog -Message " Uninstalled driver: $($driverDetails.OemInf)" -LogPath $LogPath $result.DriversRemoved++ } } catch { Write-WULog -Message " Failed to $RemoveAction device $($device.Name): $($_.Exception.Message)" -Level Warning -LogPath $LogPath } } } } else { Write-WULog -Message " No active devices found for driver $($driverDetails.OemInf) - driver may be unused" -LogPath $LogPath if ($RemoveAction -eq 'UninstallDriver') { try { $null = pnputil.exe /delete-driver $driverDetails.OemInf /force Write-WULog -Message " Removed unused driver: $($driverDetails.OemInf)" -LogPath $LogPath $result.DriversRemoved++ } catch { Write-WULog -Message " Failed to remove driver $($driverDetails.OemInf): $($_.Exception.Message)" -Level Warning -LogPath $LogPath } } } } } } } else { Write-WULog -Message "No blocking drivers found or setup analysis failed" -LogPath $LogPath } # Phase 1.5: Handle Microsoft virtual printer drivers if detected if ($microsoftPrinterDriverDetected) { Write-WULog -Message "Microsoft virtual printer drivers detected as problematic - applying specialized cleanup..." -LogPath $LogPath $printerDriversProcessed = Clean-MicrosoftPrinterDrivers -LogPath $LogPath -RemoveAction $RemoveAction if ($printerDriversProcessed -gt 0) { $result.ActionsPerformed += "Microsoft printer driver cleanup applied" } } # Phase 2: Check for general device configuration issues Write-WULog -Message "Checking for devices with configuration errors..." -LogPath $LogPath $problematicDevices = Get-CimInstance -ClassName Win32_PnPEntity | Where-Object { $_.ConfigManagerErrorCode -ne 0 -and $null -ne $_.ConfigManagerErrorCode } $result.DeviceConfigErrors = $problematicDevices.Count if ($problematicDevices) { Write-WULog -Message "Found $($problematicDevices.Count) devices with configuration errors" -LogPath $LogPath foreach ($device in $problematicDevices) { Write-WULog -Message "Device with config error: $($device.Name) (Error: $($device.ConfigManagerErrorCode))" -LogPath $LogPath } $result.ActionsPerformed += "Identified devices with configuration errors" } else { Write-WULog -Message "No devices with configuration errors detected" -LogPath $LogPath } # Determine overall success if ($result.BlockingDriversFound -gt 0 -or $result.DeviceConfigErrors -gt 0) { $result.ActionsPerformed += "Driver Analysis Completed" if ($RemoveAction -ne 'Identify' -and ($result.DriversRemoved -gt 0 -or $result.DriversDisabled -gt 0 -or $result.PrinterDriversRemoved -gt 0)) { $result.ActionsPerformed += "Driver Remediation Applied" } } $result.Success = $true # Summary logging Write-WULog -Message "Driver analysis summary:" -LogPath $LogPath Write-WULog -Message " Windows Setup blocking drivers: $($result.BlockingDriversFound)" -LogPath $LogPath Write-WULog -Message " Signature discrepancies (false positives): $($result.SignatureDiscrepancies)" -LogPath $LogPath Write-WULog -Message " Device configuration errors: $($result.DeviceConfigErrors)" -LogPath $LogPath Write-WULog -Message " Microsoft printer drivers removed: $($result.PrinterDriversRemoved)" -LogPath $LogPath Write-WULog -Message " Microsoft printer drivers reinstalled: $($result.PrinterDriversReinstalled)" -LogPath $LogPath if ($RemoveAction -ne 'Identify') { Write-WULog -Message " Drivers removed: $($result.DriversRemoved)" -LogPath $LogPath Write-WULog -Message " Devices disabled: $($result.DriversDisabled)" -LogPath $LogPath } } catch { Write-WULog -Message "Error during driver cleanup: $($_.Exception.Message)" -Level Warning -LogPath $LogPath $result.Success = $false } return $result } |