WSUS is a great product from Microsoft to keep your servers up to date. In the past years, I have often used it at the companies I worked for. But it has it downsides as well. Sometimes the Windows Update client just won’t work. You’ll get errors like 0x80244022, 0x8024401C and 0x80072EE2 and just haven’t got a clue what is going on.
I have collected a number of solutions to fix these errors and put them in a PowerShell script. This script contains all the tricks I had to pull to get the Windows Update client running again.
So, what does it do?
- it will try to ping your server
- it will test ports 8530 and 8531
- it will check in the registry if a WSUS server has been set (for instance, you think you have set a GPO, but your server didn’t pick up on that)
- it will determine if you are using a proxy server (which may interfere with the Windows Update client) and, if so, will reset that
- it will determine if you have a winsock http proxy set (which may interfere with the Windows Update client) and, if so, will reset that
- it will refresh the group membership of the server (sometimes required if you put servers in groups and restrict a GPO to that group)
- it will refresh the group policy
- it will delete WSUS cached files and the Software Distribution folder (it will stop and start the Background Intelligent Transfer Service, Windows Update, Application Identity and Cryptographic Services services to be able to do so)
- it will run wuauclt /reportnow when it’s finished to have the Windows Update client report to the WSUS server (!!! do not run wuauclt /detectnow before this command, as /reportnow will only run if the Windows Update client is not busy with another task !!!)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | Clear-Host $WSUSServer = "WSUS.$env:USERDNSDOMAIN" # Make sure we run as admin If ((New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Write-Host "You are running this script elevated. This is a good thing. Moving on with the script...." } Else { Write-Warning "You are NOT running this script elevated. This is a BAD thing. Exiting script !!!" Start-Sleep -Seconds 5 Return } # Test connection to the WSUS server If (Test-Connection -ComputerName $WSUSServer -Quiet) { Write-Host "Ping to WSUS server completed SUCCESFULLY. This is a good thing. Moving on with the script...." } Else { Write-Warning "Ping to WSUS server FAILED. This is a BAD thing !!!" Start-Sleep -Seconds 5 } If (Test-NetConnection -ComputerName $WSUSServer -Port 8530) { Write-Host "Connection test to WSUS server on port 8530 completed SUCCESFULLY. This is a good thing. Moving on with the script...." } Else { Write-Warning "Connection test to WSUS server on port 8530 FAILED. This is a BAD thing !!!" Start-Sleep -Seconds 5 } If (Test-NetConnection -ComputerName $WSUSServer -Port 8531) { Write-Host "Connection test to WSUS server on port 8531 completed SUCCESFULLY. This is a good thing. Moving on with the script...." } Else { Write-Warning "Connection test to WSUS server on port 8531 FAILED. This is a BAD thing !!!" Start-Sleep -Seconds 5 } # Test if WSUS server has been set Try { Get-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate' | Select-Object -ExpandProperty 'WUServer' -ErrorAction Stop | Out-Null Write-Host "WSUS server = " (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate' | Select-Object -ExpandProperty 'WUServer') } Catch { Write-Warning "WUServer registry key is empty. This is a BAD thing !!!" } # Test if Internet Explorer proxy server has been set $CurrentProxySettings = (Get-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings') $DNSDomain = (Get-WmiObject -Class Win32_ComputerSystem).Domain $item = "*." + $DNSDomain If ($CurrentProxySettings.ProxyEnable -eq '1') { If ($CurrentProxySettings.ProxyOverride -like "*$item*") { Write-Host "A proxy server has been set in Internet Explorer." Write-Host "A proxy exception for $item has been set. This is a good thing. Moving on with the script...." } # endif Else { Write-Warning "A proxy exception for $item has NOT been set.Adding proxy exception..." $NewOverrideValue = $CurrentProxySettings.ProxyOverride + ";" + $item Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' -Name ProxyOverride $NewOverrideValue $CurrentProxySettings = (Get-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings') Write-Host " Proxy exception has been added. Current proxy exceptions are: " $CurrentProxySettings.ProxyOverride } # endelse } # endif Else { Write-Host 'No proxy server has been set. This is a good thing. Moving on with the script....' } # endelse # Testing if winhttp proxy has been set $NetshWinhttpSetting = [string](Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\Connections' | Select-Object -ExpandProperty 'WinHttpSettings') $NotSet = "40 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0" If ($NetSHWinhttpSetting -match $NotSet) { Write-Host 'A winhttp proxy has not been set. This is a good thing. Moving on with the script....' } Else { Write-Warning 'A winhttp proxy has been set. This is a BAD thing. Resetting winhttp proxy....' # Reset winhttp (wuauclt fails if winhttp is set) netsh winhttp show proxy Start-Sleep -Seconds 3 netsh winhttp reset proxy Start-Sleep -Seconds 3 } # Refresh group membership Write-Host 'Refreshing computer group membership' klist -lh 0 -li 0x3e7 purge klist -lh 0 -li x3e7 purge Start-Sleep 3 # Refrsh group policy Write-Host 'Forcing group policy' gpupdate /force /target:computer Start-Sleep 3 #Stop services $ServiceDisplayNames = @() $ServiceDisplayNames = @('Background Intelligent Transfer Service', 'Windows Update', 'Application Identity', 'Cryptographic Services') ForEach ($ServiceDisplayName in $ServiceDisplayNames) { Try { Get-Service -DisplayName $ServiceDisplayName | Stop-Service -Verbose Get-Service -DisplayName $ServiceDisplayName } Catch { } } # Remove files Remove-Item "$env:AllUsersProfile\Microsoft\Network\Downloader\qmgr*.dat" -Force -Verbose Remove-Item "$env:SystemRoot\SoftwareDistribution" -Force -Recurse -Verbose # Start services $ServiceDisplayNames = @() $ServiceDisplayNames = @('Cryptographic Services', 'Application Identity', 'Windows Update', 'Background Intelligent Transfer Service') ForEach ($ServiceDisplayName in $ServiceDisplayNames) { Try { Get-Service -DisplayName $ServiceDisplayName | Start-Service -Verbose Get-Service -DisplayName $ServiceDisplayName } Catch { } } Start-Sleep -Seconds 5 wuauclt /reportnow |
As always, please keep in mind this script is tailored to my environment, but can be used as a template for your environment. I do not pretend to be a PowerShell guru and as such my script may not be perfect. I am open to suggestions 🙂
If you found this script useful, I’d appreciate it if you leave a comment.