PowerShell – Did You Patch My Server?

As a patch guy, I get asked this very question at least once a month.  The phrasing may vary, but it’s usually along the lines of:

  • My application broke, did you patch it?
  • My server rebooted, did you patch it?

Et cetera, et cetera..

The easy part, of course, is saying “No”, but we as admins and engineers often require more proof than a good word.  So while it may not exonerate your patch deployment as the issue causing culprit, here’s two commands that make investigation a little bit easier.

“My application broke, did you patch it?”

This usually coincides with something breaking on a specific date.  Usually, I ask when they started noticing the problem and I’ll look into when they last installed updates by checking the Win32_QuickFixEngineering class on the machine:

Get-CimInstance -ComputerName server01 -ClassName win32_quickfixengineering | Sort-Object InstalledOn -Descending

Patching1Now you have a list of patches as well as the install date that you can use to narrow down your list of suspects.  With this, you can investigate what components are affected by the patches in your time-frame and whittle down the suspects with relative ease.

“My server rebooted, did you patch it?”

One of my favorite questions!  I actually get this one more frequently than the other.  The script I use checks the reboot records for a server to find out what initiated the reboot, and if it was expected.  So let’s begin with:

Get-WinEvent -ComputerName server01 -FilterHashTable @{Logname='System';Id='1074','6008'}

Which returns:

Patching2

Well that’s pretty cool!  But it’s kind of dirty and doesn’t give me everything I want.  So let’s see what we have available to us.

Get-WinEvent -ComputerName server01 -FilterHashTable @{Logname='System';Id='1074','6008'} | Get-Member

Gives us:

Patching3

Now what do you suppose is in that Properties collection?

$Events = (Get-WinEvent -ComputerName canatcmdev03 -FilterHashTable @{Logname='System';Id='1074',"6008"}) | Select-Object -First 1
$Events.Properties

Gets us…

Patching4Now that looks like some usable data!  So we’ll just put all of this together in our PSCustomObject:

$Events = (Get-WinEvent -ComputerName server01 -FilterHashTable @{Logname='System';Id='1074',"6008"})
ForEach ($Evt in $Events){
 [PSCustomObject]@{
 ComputerName = $Evt.MachineName
 Date = $Evt.TimeCreated
 Process = $Evt.Properties[0].Value
 User = $Evt.Properties[6].Value
 Action = $Evt.Properties[4].Value
 Reason = $Evt.Properties[2].Value
 Comment = $Evt.Properties[5].Value
 Message = $Evt.Message
 EventID = $Evt.Id
 } #EndPSCustomObject
 }

And we get…

Patching5

That looks like something that we can use.  So now we can wrap this up in a function and put it up on our repository server!

These two commands can help your colleagues quickly get pointed in the right direction when it comes to a reboot that wasn’t necessarily planned, and can get you pointed in the right direction if there’s an issue with a machine getting the proper patch policies.

If you’d like to download the reboot records function, you can catch it at the TechNet Script Repository here.