How Can I Determine When the Last Patch From Windows Update was Applied?

How Can I Determine When the Last Patch From Windows Update was Applied?

  • Comments 9
  • Likes
Hey, Scripting Guy! Question

Hey, Scripting Guy! How can I determine when the last patch from Windows Update was applied?

-- JP

SpacerHey, Scripting Guy! AnswerScript Center

Hey, JP. You know, you picked a good time to ask this question; that’s because we just published a Tales from the Script column that introduces scripters to the Windows Update object model, and provides a number of sample scripts for managing Automatic Updates. And while the article doesn’t have a script that returns information for just the last update applied to a computer, well, it was easy enough to come up with one:

Set objSession = CreateObject("Microsoft.Update.Session")
Set objSearcher = objSession.CreateUpdateSearcher

Set colHistory = objSearcher.QueryHistory(0, 1)

For Each objEntry in colHistory
    Wscript.Echo "Title: " & objEntry.Title
    Wscript.Echo "Update application date: " & objEntry.Date
Next

What’s going on in this little script? Funny you should ask: we were just about to explain that. We begin by creating an instance of the Microsoft.Update.Session object. Once we have that object in hand we can call the CreateUpdateSearcher method. This gives us an instance of the Searcher object, an object that enables us to search through all the updates that have been applied to a computer. Which is exactly the thing we want to do.

Next we use the QueryHistory method to retrieve the desired updates:

Set colHistory = objSearcher.QueryHistory(0, 1)

As you can see, in this script we pass QueryHistory two parameters: 0 and 1. The 0 tells the script to begin its search with record 0 in the update history; the 1 tells the script to stop its search after record 1. (That is, before it gets to record 2.) Why do we do that? Well, updates are stored in reverse chronological order, with the most recent update being record 0 and the very first update ever applied being the last record in the collection. Because we want information about only the most recent update, we can make the script run a tad bit faster by limiting the returned data to just that one record.

Note. We should point out that it’s very easy to retrieve the complete update history for a computer; in fact, the Tales from the Script column includes a script that does just that.

After calling the QueryHistory method we’ll get back a collection (named colHistory) consisting of a single item, an item which just happens to represent the last update that was applied to the computer. All that’s left now is to walk through that collection (and, yes, technically it’s still a collection even though it contains just one item) and echo the title of the update and the date the update was applied:

For Each objEntry in colHistory
    Wscript.Echo "Title: " & objEntry.Title
    Wscript.Echo "Update application date: " & objEntry.Date
Next

In other words, tell us the last time Windows Update did something to this particular computer.

Incidentally, the Windows Update object model is a mixed-bag: some of the objects can be created on - and thus used against - remote computers while others can’t. Fortunately, this happens to be a script that will run against a remote machine. To do that you simply need to add the remote computer name as the second parameter to CreateObject. For example, this line of code causes the script to run against the remote computer atl-dc-01:

Set objSession = CreateObject("Microsoft.Update.Session", "atl-dc-01")

And the complete script for retrieving the last update from atl-dc-01 would thus look like this:

Set objSession = CreateObject("Microsoft.Update.Session", "atl-dc-01")
Set objSearcher = objSession.CreateUpdateSearcher

Set colHistory = objSearcher.QueryHistory(1, 1)

For Each objEntry in colHistory
    Wscript.Echo "Title: " & objEntry.Title
    Wscript.Echo "Update application date: " & objEntry.Date
Next

And people think that patch management is hard. Not anymore!

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Hi im sorry im just new to this WSUS scripting ..whn i put the remote server name it just gives me an error "permission denied" I have username and password to logon now how to make this script to actively ask for username and password, get connect to the server and pull the last update?

    Please guide me through the steps...

  • Is this possible to run this script against a set of computers ? Plz help

  • I am getting below error while connecting to remote system

    WARNING: Exception calling "CreateInstance" with "1" argument(s): "Retrieving the COM class factory for remote component with CLSID {4CB43D7F-7EEE-4906-8698-60DA1C38F2FE} from machine 01hw283458 failed due to the following error: 80070005."

    Any workaround?

  • Doesn't seem to work, though specifying a local check does. Here's the error.

    Set-Variable : A positional parameter cannot be found that accepts argument 'CreateObject'.

    At line:1 char:4

    + Set <<<<  objSession = CreateObject("Microsoft.Update.Session", "myservername")

       + CategoryInfo          : InvalidArgument: (:) [Set-Variable], ParameterBindingException

       + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.SetVariableCommand

  • Is it possible to pass a variable to this script to run against a list of computers?

  • I need this -- will it work in 2013?  On Windows 7 and 8?

  • @Hank on Windows 7 or 8 use PowerShell to do this -- it is much easier and much more reliable. Take a look at this grouping of articles to see some great examples social.technet.microsoft.com/.../en-US

  • I change this script to run against a list of computers but did not work what need to change in this..

    Const ForReading = 1

    Set objSession = CreateObject("Microsoft.Update.Session")
    Set objFile = objSession.OpenTextFile ("c:\servers.txt", ForReading)


    Do While Not objFile.AtEndOfStream
    strComputer = objFile.ReadLine
    Set objSearcher = objSession.CreateUpdateSearcher
    Set colHistory = objSearcher.QueryHistory(1, 1)
    For Each objEntry in colHistory
    Wscript.Echo "Title: " & objEntry.Title
    Wscript.Echo strComputer & "Update application date: " & objEntry.Date
    Next
    Loop

  • Const ForReading = 1

    Set objSession = CreateObject("Microsoft.Update.Session")
    Set objFile = objSession.OpenTextFile ("c:\servers.txt", ForReading)

    Do While Not objFile.AtEndOfStream
    strComputer = objFile.ReadLine
    Set objSearcher = objSession.CreateUpdateSearcher
    Set colHistory = objSearcher.QueryHistory(1, 1)
    For Each objEntry in colHistory
    Wscript.Echo "Title: " & objEntry.Title
    Wscript.Echo strComputer & "Update application date: " & objEntry.Date
    Next
    Loop