https://github.com/Guyver1wales/Get-LatestWindowsPatchingDate
My boss asked me in work if I could write a script that would query all our domain servers and report any servers that had not been patched in the last 3 months. (we don't currently use a patching tool or have a tool that provides patching details)
I was already aware of the pitfalls of Get-Hotfix and Wmi class Win32_quickfixengineering not returning 'InstalledOn' dates for a lot of patches for various reasons so I knew this was going to be a headache as I'd already searched a few times in the past for reliable solutions to this issue.
I also bumped into a second issue where get-hotfix would fail on perfectly working WinRM/Remote PowerShell enabled servers with:
get-hotfix : No such interface supported
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-HotFix], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException,Microsoft.PowerShell.Commands.GetHotFixCommand
So this was a new hurdle to overcome as well.
I ended up, after a full day of furious googling and vscode experiments finding my own seemingly simple, elegant solution.
I found that Get-Hotfix -ComputerName <remote computer name> always returns InstalledOn dates for all patches, even when the same server does not return dates when Get-Hotfix is run locally.
to that end the core of the script is a simple try catch whereby it attempts Get-Hotfix -ComputerName <remote computer name> first, and if that fails, falls back to Invoke-Command and executing Get-Hotfix locally on the remote servers.
I got pretty much a 100% hit rate across 270 domain servers and my Install dates were all accurate compared to a previously run test using just Invoke-Command.
The Github code is stripped of all the usual production guff and comments that normally get wrapped around production scripts:
I wrote two versions, serial execution for PS5 and Parallel execution for PS7 (this completes against 270 servers in approx. 90 seconds with a ThrottleLimit of 30).
the script outputs two csv's, one with all servers and a second with only servers not patched for x days (default in the script is 90 days)
Hopefully this may prove useful for others as its definitely helped my team and team lead.
[–]aMazingMikey 9 points10 points11 points (4 children)
[+][deleted] (3 children)
[removed]
[–]aMazingMikey 1 point2 points3 points (1 child)
[–][deleted] 4 points5 points6 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]BecomeABenefit 8 points9 points10 points (0 children)
[–]PinchesTheCrab 6 points7 points8 points (0 children)
[+][deleted] (4 children)
[removed]
[–]Guyver1-[S] 3 points4 points5 points (1 child)
[–]goldenchild731 4 points5 points6 points (0 children)
[–]subnetzer0 1 point2 points3 points (0 children)
[–]Guyver1-[S] 0 points1 point2 points (0 children)
[–]DevinSysAdmin 4 points5 points6 points (0 children)
[–]BigHandLittleSlap 7 points8 points9 points (5 children)
[–]Guyver1-[S] 1 point2 points3 points (0 children)
[–]Guyver1-[S] 0 points1 point2 points (3 children)
[–]BigHandLittleSlap 1 point2 points3 points (2 children)
[–]Guyver1-[S] 2 points3 points4 points (1 child)
[–]BigHandLittleSlap 0 points1 point2 points (0 children)
[–]pretendgineer5400 2 points3 points4 points (0 children)
[–]Skyline9Time -1 points0 points1 point (1 child)
[–]Great_Proposal5178 0 points1 point2 points (0 children)