Refresh Windows Updates Components: Patching Failure Super Script
Don’t you hate when monthly patches just won’t take? I ran into patch compliance issues in my past life as a MECM engineer. The script we’re about to review has helped me knock thousands of endpoints into patching compliance. We’re going to tackle 4 things in one go:
- Restart Windows Updates related services
- Backup and recreate Catroot2 and SoftwareDistribution folders
- Reregister related .dll files
- Kick off a reevaluation of MECM’s Software Update Deployment Evaluation task
I like to call this script a super punch; One, because I think that’s funny. Two, because we’re going to throw the kitchen sink at the problem. Let’s dive in.
TL;DR >>> GitHub
From the Top
Let’s start off by making some much needed variables. These will be the WMI objects for our Windows services, and the needed folder paths for Catroot2 and SoftwareDistribution.
$WUservice = Get-WmiObject -Class Win32_Service -Filter "Name='wuauserv'"
$BITSservice = Get-WmiObject -Class Win32_Service -Filter "Name='BITS'"
$Cryptsvc = Get-WmiObject -Class Win32_service -Filter "Name='cryptsvc'"
$Msiserver = Get-WmiObject -Class Win32_service -Filter "Name='msiserver'"
$SFTDistBK = "c:\windows\SoftwareDistribution.bak"
$SFTDist = "c:\windows\SoftwareDistribution"
$CatrootDir= "c:\windows\system32\catroot2"
$CatrootDirBK = "C:\windows\system32\catroot2.old"
Catroot. Meow.
Next up! Let’s work on recreating the Catroot2 and SoftwareDistribution folders. We need to ensure that our Windows Updates related services are stopped. If they won’t stop, we’ll try to force them. If they don’t stop, we’ll relay back an error code to MECM so we know what to troubleshoot further.
For your weary eyes, I’ll only post a snippet here. Essentially, copy/paste this block of code for each Windows Update service variable (see above code) and change out the variables to the designated values. We also need to keep this in one big Try/Catch block, so please reference the GitHub link to see how I did this.
Try{
#write-host "Stopping Services: $WUservice.Name"
if($WUservice.State = "Running"){
Stop-Service wuauserv
}
Else {
Start-Service wuauserv
Start-Sleep -Seconds 10
Stop-Service wuauserv
}
} Catch {
write-error "$WUservice.Name Service failed to stop" -ErrorId "3"
}
Now, we’re going to attempt to recreate the discussed folders. Again, using more Try/Catch blocks and reporting back any error codes to MECM for further troubleshooting.
$FolderFlagSF = Test-Path $SFTDistBK
if($WUservice.State = "Stopped" -and ($BITSservice.State = "Stopped")){
#write-host "Renaming SoftwareDistribution folder"
Try {
if(!($FolderFlagSF)){
Rename-Item -path $SFTDist -NewName $SFTDistBK -Force
}
Else {
Remove-Item $SFTDistBK -Force -Recurse
Rename-Item -Path $SFTDist -NewName $SFTDistBK -Force
}
} Catch [RenameItemIOError]{
Write-error "Could not handle Software Distribution folder" -ErrorID "6"
}
}
$FolderFlagCat = Test-Path $CatrootDirBK
#write-host "Copying Catroot2 folder"
Try{
if(!($FolderFlagCat)) {
New-Item -Path $CatrootDirBK -ItemType Directory
Copy-Item -Path $CatrootDir -Destination $CatrootDirBK -Recurse
Remove-Item $CatrootDir -Force -Recurse
}
Else {
Remove-Item $CatrootDirBK -Force -Recurse
New-Item -Path $CatrootDirBK -ItemType Directory
Copy-Item -Path $CatrootDir -Destination $CatrootDirBK -Recurse
Remove-Item $CatrootDir -Force -Recurse
}
} Catch {
write-error "Could not handle Catroot2 folder" -ErrorId "7"
}
D-LL Cool J
Next step, registering .DLL files. I kept this relatively straight forward.
regsvr32.exe /s atl.dll
regsvr32.exe /s urlmon.dll
regsvr32.exe /s mshtml.dll
regsvr32.exe /s shdocvw.dll
regsvr32.exe /s browseui.dll
regsvr32.exe /s jscript.dll
regsvr32.exe /s vbscript.dll
regsvr32.exe /s scrrun.dll
regsvr32.exe /s msxml.dll
regsvr32.exe /s msxml3.dll
regsvr32.exe /s msxml6.dll
regsvr32.exe /s actxprxy.dll
regsvr32.exe /s softpub.dll
regsvr32.exe /s wintrust.dll
regsvr32.exe /s dssenh.dll
regsvr32.exe /s rsaenh.dll
regsvr32.exe /s gpkcsp.dll
regsvr32.exe /s sccbase.dll
regsvr32.exe /s slbcsp.dll
regsvr32.exe /s cryptdlg.dll
regsvr32.exe /s oleaut32.dll
regsvr32.exe /s ole32.dll
regsvr32.exe /s shell32.dll
regsvr32.exe /s initpki.dll
regsvr32.exe /s wuapi.dll
regsvr32.exe /s wuaueng.dll
regsvr32.exe /s wuaueng1.dll
regsvr32.exe /s wucltui.dll
regsvr32.exe /s wups.dll
regsvr32.exe /s wups2.dll
regsvr32.exe /s wuweb.dll
regsvr32.exe /s qmgr.dll
regsvr32.exe /s qmgrprxy.dll
regsvr32.exe /s wucltux.dll
regsvr32.exe /s muweb.dll
regsvr32.exe /s wuwebv.dll
Closing Time
Let’s wrap it up with ensuring that our services are started again.
Start-Service wuauserv
Start-Service BITS
Start-Service cryptsvc
Start-service msiserver
And most importantly, sometimes the most complex problems require the simplest solutions; let’s kick off another Software Update Deployment Evaluation with the following command:
Invoke-WmiMethod -Namespace root\ccm -Class sms_client -Name TriggerSchedule "{00000000-0000-0000-0000-000000000108}"
Final Words
This is a big one. It may be privy of you to just copy/paste the script from GitHub instead of following along, but at least you have a big explanation of what’s going on. As previously stated, I used to be a MECM engineer, and this script has helped me tackle those fickle machines that just don’t want to patch. I’m not saying this is a cure-all, but it definitely comes in handy!
And remember, kids:
This project is provided “as is” without any warranty of any kind, express or implied. Use it at your own risk. The authors and contributors are not responsible for any damage, data loss, or other issues that may arise from using this software. You are solely responsible for any actions taken based on this code.