Windows Update Report with Win32_QuickFixEngineering

08 Oct

There are still a lot of servers I manage that are not a part of WSUS yet. This means going in and manually installing patches.  I knew that I had a lot of these servers and just going down the list one by one isn’t very efficient.  One thing that would really help is if I could get a list that is ordered by the last time it was patched. Then I could target the worst offenders first, and if I had time I could move on to the servers with fewer patches needed.

This simple command will get a list of all the patches that have been installed with a few other pieces of information.

wmic qfe get > c:wu.txt

For my computer this report is formatted with fixed width columns and could be parsed.  I could add a node parameter to the above command and run it for each server. Then I would have all the data I need to get my report. However, that is just too much data and a lot of parsing. I stepped back over an older project that I still use and pulled out some of the WMI code.  To dump everything in one heap and then sort through it would be inefficient.  To make this more efficient I looked at the WMI class Win32_QuickFixEngineering or qfe.

The qfe has this nice column “InstallDate” which really sounded like a winner to me.  Its actually a date type and could be very useful.  However, its always NULL for every server I checked. I went back to the text report scratching my head and saw that there was another column “InstalledOn”.  That is the column I need.

select InstalledOn from Win32_QuickFixEngineering where InstalledOn <> ''

I noticed that on some servers this value was blank for a lot of patches.  I am assuming a bit here but it appears they are patches that were installed during sysprep or in some other fashion early in the servers life. The next thing I realized is that all I really need is the top 1 in descending order.  This is when I found out there is no sorting in WMI. I would have to sort the results after the fact.

The MangementObject that gets returned is a bit tricky to work with so the first thing I do is read the results into an array. ArraysLists are easy to add to “.add” and also easy to sort. A .Sort() and then a .Reverse() is all I needed to pick out the last patch date. It was sitting in my array(0).

I ran into a snag rather quickly. Turns out vista era Microsoft decided it would be a great idea to start returning this as a 16 character hex value. Part of my code had to handle 4 different date types if you count NULLs.

'oReturn is one record in the managementobject.  You get one for each patch
Dim oDate As Object
If oReturn("InstalledOn").Length = 16 Then
    oDate = DateTime.FromFileTimeUtc(Int64.Parse(oReturn("InstalledOn"), System.Globalization.NumberStyles.AllowHexSpecifier))
ElseIf oReturn("InstalledOn").Length &gt; 7 And oReturn("InstalledOn").Length &lt; 11 Then
    oDate = CDate(oReturn(&quot;InstalledOn&quot;))
    'I don't know what date type you are... you must not be a recent patch.
    oDate = DateTime.Now.AddYears(-100)
End If

When searching for answers to my questions I did read some complaints about all patches not showing up in the results. To solve my problem it wasn’t really necessary to be totally accurate. I just needed a date the last time the server had some tlc. So far it has been very accurate.

Here are some links that I used to get to my end game.


Leave a comment

Posted by on October 8, 2011 in .NET, Network Admin


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: