Jump to content
Teeevv

Monitoring Windows Updates Health

Recommended Posts

As we all know managing windows updates can be a pain sometimes, and thanks to the report created by Gavsto (https://www.gavsto.com/free-report-get-a-second-opinion-on-your-patching/) we've discovered the patch compliance reporting within Automate can be very misleading. Using this report I started to dig into the anomalies and discovered two problems

  1. The report showed the last Cumulative Update and when the installation was attempted, whether it was successful or not
  2. I didn't want to rely on a manual task to review a report, I wanted automate to raise a ticket when a machine fell behind by 35 days so we can go fix the issue

Based on these issues, I decided the best way to proceed was to expand upon Gavsto's idea. Since we're trying to verify the actual current patch level of every computer, I didn't want to rely on the information already existing in Automate in case it was incorrect. I figured the most accurate source of the current patch level would be the computer itself. I created two new extra data fields and populated them with a small powershell script. The logic for the powershell script followed the same principal as the report, list out the latest cumulative update's that were installed but with the added condition of making sure the update was successful. The EDF's I created and the powershell scripts to populate them were

  • Last Successful Patch - The Title of the patch that was last installed
$Result = @();
$Session = New-Object -ComObject Microsoft.Update.Session;
$Searcher = $Session.CreateUpdateSearcher();
$HistoryCount = $Searcher.GetTotalHistoryCount();
$Result = (
	$Searcher.QueryHistory(0,$HistoryCount) | Where-Object {
		(
			$_.ResultCode -eq 2 -or 
			$_.ResultCode -eq 3
		) -and (
			$_.Title -like '*Security Monthly Quality*' -or 
			$_.Title -like '*Servicing Stack Update*' -or 
			$_.Title -like '*Cumulative Security Update*' -or 
			$_.Title -like '*Cumulative Update For*' -or 
			$_.Title -like '*Feature update to*'
		) -and (
			$_.Title -notlike '*Cumulative Security Update For Internet Explorer*' -and 
			$_.Title -notlike '*Cumulative Security Update for ActiveX*' -and 
			$_.Title -notlike '*Cumulative Update for .NET Framework*'
		)
	} | Sort-Object Date);
If ($Result.count -gt 0) {
	return ($Result[-1]).Title 
} Else { 
	Return "No CU Patching Information Available" 
};
  • Last Successful Patch Timestamp - The date and time this patch was installed, in a YYYYMMDD-HHMMSS format
$Result = @(); 
$Session = New-Object -ComObject Microsoft.Update.Session; 
$Searcher = $Session.CreateUpdateSearcher(); 
$HistoryCount = $Searcher.GetTotalHistoryCount(); 
$Result = (
	$Searcher.QueryHistory(0,$HistoryCount) | Where-Object {
		(
			$_.ResultCode -eq 2 -or 
			$_.ResultCode -eq 3
		) -and (
			$_.Title -like '*Security Monthly Quality*' -or 
			$_.Title -like '*Servicing Stack Update*' -or 
			$_.Title -like '*Cumulative Security Update*' -or 
			$_.Title -like '*Cumulative Update For*' -or 
			$_.Title -like '*Feature update to*'
		) -and (
			$_.Title -notlike '*Cumulative Security Update For Internet Explorer*' -and 
			$_.Title -notlike '*Cumulative Security Update for ActiveX*' -and 
			$_.Title -notlike '*Cumulative Update for .NET Framework*'
		)
	} | Sort-Object Date); 
If ($Result.count -gt 0) { 
	return ($Result[-1]).Date.ToString('yyyyMMdd-HHmmss') 
} Else {
	Return "No CU Patching Information Available" 
};

 

The added benefit from this approach was it didn't matter how the patch was installed, whether through automate, manually or by a third party, it should always appear which is great to get an accurate sense of patch level when on boarding a new client.

Now we had the latest patch information from the computer in Automate I simply created an internal monitor to compare the timestamp and log a ticket for anything that hasn't successfully patched in over 35 days.

image.png.f474594453c4f895442024ce8f75338c.png

 

So far this has been working for me, it's also highlighted a few machines that haven't been patched since last year that didn't show up in the report. A few ideas we've had so far to improve upon this

  • Add some verification to only log a ticket if the machine has been online during the past 35 days
  • Run some autofix actions prior to logging a ticket such as
    • Force the EDF's to update and revalidate
    • Attempt to run a patch job

I'd love to hear peoples feedback on this approach, any gotcha's you might see catching us out in future, or ideas to improve on the solution. If nothing else hopefully this posts helps some others detect systems that aren't patching properly.

 

 

  • Like 2

Share this post


Link to post
Share on other sites

Thank you for the great info! I started implementing this today and am excited about the results so far.

Share this post


Link to post
Share on other sites
Posted (edited)

@Teeevv

@Gavsto

Thanks for sharing this great way to monitor Updates.

Would you please share the steps of how you created two new extra data fields and populated them with a small powershell script?

Cheers.

Edited by Dayrak

Share this post


Link to post
Share on other sites

Great idea...I added the following to the first line of each script to squelch extra error messages from the script polluting the result EDF.  I am also working on a report to pull the data from the EDF in spreadsheet format for easy viewing.

$ErrorActionPreference= 'silentlycontinue';

 

Share this post


Link to post
Share on other sites
Posted (edited)

One issue I have now is that a PC isnt reporting the Patching to Automate correctly.

Seems it cant send Patch Inventory.
I can see it has later updates in the History but not from Automate.
Any ideas?

Thanks

 

 

 

 

Edited by Dave C

Share this post


Link to post
Share on other sites
Posted (edited)
On 6/23/2019 at 9:06 PM, Teeevv said:

As we all know managing windows updates can be a pain sometimes, and thanks to the report created by Gavsto (https://www.gavsto.com/free-report-get-a-second-opinion-on-your-patching/) we've discovered the patch compliance reporting within Automate can be very misleading. Using this report I started to dig into the anomalies and discovered two problems

  1. The report showed the last Cumulative Update and when the installation was attempted, whether it was successful or not
  2. I didn't want to rely on a manual task to review a report, I wanted automate to raise a ticket when a machine fell behind by 35 days so we can go fix the issue

Based on these issues, I decided the best way to proceed was to expand upon Gavsto's idea. Since we're trying to verify the actual current patch level of every computer, I didn't want to rely on the information already existing in Automate in case it was incorrect. I figured the most accurate source of the current patch level would be the computer itself. I created two new extra data fields and populated them with a small powershell script. The logic for the powershell script followed the same principal as the report, list out the latest cumulative update's that were installed but with the added condition of making sure the update was successful. The EDF's I created and the powershell scripts to populate them were

  • Last Successful Patch - The Title of the patch that was last installed

$Result = @();
$Session = New-Object -ComObject Microsoft.Update.Session;
$Searcher = $Session.CreateUpdateSearcher();
$HistoryCount = $Searcher.GetTotalHistoryCount();
$Result = (
	$Searcher.QueryHistory(0,$HistoryCount) | Where-Object {
		(
			$_.ResultCode -eq 2 -or 
			$_.ResultCode -eq 3
		) -and (
			$_.Title -like '*Security Monthly Quality*' -or 
			$_.Title -like '*Servicing Stack Update*' -or 
			$_.Title -like '*Cumulative Security Update*' -or 
			$_.Title -like '*Cumulative Update For*' -or 
			$_.Title -like '*Feature update to*'
		) -and (
			$_.Title -notlike '*Cumulative Security Update For Internet Explorer*' -and 
			$_.Title -notlike '*Cumulative Security Update for ActiveX*' -and 
			$_.Title -notlike '*Cumulative Update for .NET Framework*'
		)
	} | Sort-Object Date);
If ($Result.count -gt 0) {
	return ($Result[-1]).Title 
} Else { 
	Return "No CU Patching Information Available" 
};
  • Last Successful Patch Timestamp - The date and time this patch was installed, in a YYYYMMDD-HHMMSS format

$Result = @(); 
$Session = New-Object -ComObject Microsoft.Update.Session; 
$Searcher = $Session.CreateUpdateSearcher(); 
$HistoryCount = $Searcher.GetTotalHistoryCount(); 
$Result = (
	$Searcher.QueryHistory(0,$HistoryCount) | Where-Object {
		(
			$_.ResultCode -eq 2 -or 
			$_.ResultCode -eq 3
		) -and (
			$_.Title -like '*Security Monthly Quality*' -or 
			$_.Title -like '*Servicing Stack Update*' -or 
			$_.Title -like '*Cumulative Security Update*' -or 
			$_.Title -like '*Cumulative Update For*' -or 
			$_.Title -like '*Feature update to*'
		) -and (
			$_.Title -notlike '*Cumulative Security Update For Internet Explorer*' -and 
			$_.Title -notlike '*Cumulative Security Update for ActiveX*' -and 
			$_.Title -notlike '*Cumulative Update for .NET Framework*'
		)
	} | Sort-Object Date); 
If ($Result.count -gt 0) { 
	return ($Result[-1]).Date.ToString('yyyyMMdd-HHmmss') 
} Else {
	Return "No CU Patching Information Available" 
};

 

The added benefit from this approach was it didn't matter how the patch was installed, whether through automate, manually or by a third party, it should always appear which is great to get an accurate sense of patch level when on boarding a new client.

Now we had the latest patch information from the computer in Automate I simply created an internal monitor to compare the timestamp and log a ticket for anything that hasn't successfully patched in over 35 days.

image.png.f474594453c4f895442024ce8f75338c.png

 

So far this has been working for me, it's also highlighted a few machines that haven't been patched since last year that didn't show up in the report. A few ideas we've had so far to improve upon this

  • Add some verification to only log a ticket if the machine has been online during the past 35 days
  • Run some autofix actions prior to logging a ticket such as
    • Force the EDF's to update and revalidate
    • Attempt to run a patch job

I'd love to hear peoples feedback on this approach, any gotcha's you might see catching us out in future, or ideas to improve on the solution. If nothing else hopefully this posts helps some others detect systems that aren't patching properly.

 

 

If it helps anyone else I found that some servers had installed the Preview Update instead so had to add this line to both Scripts.
            $_.Title -like '*Preview of Monthly Quality*' -or 
 

To make anyones lives Easier ive attached a copy of the Script I used to populate the EDFs I created.

 

Last Successful Patch Date.xml

Edited by Dave C

Share this post


Link to post
Share on other sites

Anyone Created a decent DataView or Report template they want to share that pulls from their EDF's?

Share this post


Link to post
Share on other sites
1 hour ago, HickBoy said:

Wow... that's a great report.  It does work and is a great canvas to add some features.  Thx for pointing me in that direction...

Indeed. You'r welcome.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...