July 2005

SG090301

By The Scripting Guys

For a list and additional information on all Tales from the Script columns, click here.

On This Page

I’ll Get You, My Pretty…And We’ll Manage Windows Update, Too!
Are You a Good Scripting Interface or a Bad Scripting Interface?
Determining Whether the Automatic Updates Service is Installed
Determining Whether Automatic Updates is Enabled
Enabling Automatic Updates
Determining the Automatic Updates Schedule
Modifying the Automatic Updates Schedule
Determining whether a Computer Needs to be Rebooted
Reviewing Updates on a Computer
Searching for Updates
Determining if a Particular Update has Been Installed
Toto, I've a Feeling We Can’t Complain About Windows Update Any More

I’ll Get You, My Pretty…And We’ll Manage Windows Update, Too!

In the movie The Wizard of Oz Dorothy faced numerous perils on her journey to the Emerald City: stalked by lions and tigers and bears (oh, my!); spirited away by flying monkeys; threatened by the Wicked Witch of the West. (All in all, though, she had a much quicker and easier trip than the trip faced each morning by Seattle-area commuters.) To make matters worse, after all that hardship, it appeared that she wouldn’t even be able to get back to Kansas, not after the Wizard’s balloon took off without her.

It was only then that Glinda, the Good Witch of the North, spoke up: “You know, Dorothy, you’ve always had the power to get back to Kansas. Did I forget to mention that?” Yes, Glinda, you did. Thanks for all your help.

Note. The scary thing is that Glinda was the good witch. With friends like that….

Eventually, of course, Dorothy clicked her heels three times, repeated the phrase, “There’s no place like home,” and was magically transported back to Kansas. Today she’s a 35-year-old single mother of 2 working as an accountant in Little Rick, Arkansas, and wondering how much those ruby slippers would fetch on EBay.

Note. Let’s put it this way: more than most of us can afford. There are five known pairs of ruby slippers that were used in the movie, and in the year 2000 one of those pairs was auctioned off for $600,000. That’s nearly a year’s salary for a Scripting Guy!

System administrators can be forgiven if they sometimes feel like Dorothy. (No jokes about Scripting Guys being like the Scarecrow, the one who needed a brain.) System administrators often lament the fact that Microsoft failed to give them the proper management tools, only to find out later that we did provide those tools; like Glinda, the Good Witch of the North, we just forgot to mention them. (“Oh, my!” indeed.)

Take the Windows Update service, for example. Windows Update (and Automatic Updates, the feature that works with Windows Update to automatically deliver critical updates) goes a long way towards addressing the problem of dealing with patches, hot fixes, service packs, and other software updates. For the most part system administrators seem satisfied with this approach. Still, they can’t help wondering why Microsoft didn’t provide better tools for managing Windows Update across the enterprise. For example, how can a system administrator know whether a given user has disabled Automatic Updates? How can you know when Automatic Updates is scheduled on all your computers? How can you verify that a particular patch has been installed on a particular machine? In other words:

I could while away the hours, conferrin' with the flowers
Consultin' like a fool.
And my head I'd be scratchin' while my thoughts were busy hatchin'
If I only had a tool.

And people think Peter Costantini is the only musical Scripting Guy!

As it turns out, you actually do have some tools for managing Windows Update across the enterprise: scripts. Any time you install Automatic Updates on a computer you get – for free – a library of COM objects that can enable and disable the update service, modify the update schedule, review the list of installed updates, and even install new updates for you. Pretty sweet, huh?

So how do you write scripts that can manage the Automatic Updates service on your client computers? Well, to quote our old friend Glinda: “It's always best to start at the beginning - and all you do is follow the Yellow Brick Road.”

And once you’re done doing that, read the rest of this month’s column.

Are You a Good Scripting Interface or a Bad Scripting Interface?

Before we begin, we need to issue a few caveats. First, the object model for Windows Update client services is surprisingly big; there’s no way we can cover it all in this one column. The best we can do is to give you an overview and show you a few sample scripts that cover some of the more useful tasks; if you’d like to go beyond what we do today, then take a look at the Windows Update Agent API on MSDN.

In addition, the story around remoting – that is, the ability to use your Windows Update scripts against remote computers – is a bit confusing, to say the least. As you’ll see throughout this article, some of the scripts will work against remote computers and some of them won’t; the latter set of scripts have to run locally (perhaps as a logon or computer startup script). There’s not a lot we can do about that, but as we go along we’ll try to make it obvious which scripts will work against remote computers and which ones won’t.

And yes, we wish all the scripts would work against remote computers, too; unfortunately, they don’t. Now be gone before somebody drops a house on you!

Note. Relax; no one’s going to drop a house on you.

Well, probably not.

We should add that all the sample scripts shown in this column work against the local computer. To run a script against a remote machine (or at least those scripts capable of working against remote machines) you need to add the remote computer name as a second parameter to the CreateObject call. For example, to run a script against the remote computer atl-ws-01, your first line of code should look something like this:

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

This, by the way, has nothing to do with Windows Update; it’s standard VBScript. VBScript always allows you to specify the name of a remote computer as a second parameter to CreateObject; of course, this works only if the COM object in question can be run remotely.

The only exception to this is the very first script we show, which happens to be a typical WMI script. To run that script against a remote computer simply assign the name of that computer to the variable strComputer:

strComputer = "atl-ws-01"

Determining Whether the Automatic Updates Service is Installed

This script can be run against remote computers.

Before you start worrying about whether or not Automatic Updates has been properly configured, you should probably verify that Automatic Updates has been installed in the first place. Because Automatic Updates runs as a service, you can verify the installation (and determine the current service state) by using a script like this:

strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colServices = objWMIService.ExecQuery _
    ("Select * from Win32_Service Where DisplayName = 'Automatic Updates'")

If colServices.Count = 0 Then
    Wscript.Echo "Automatic Updates is not installed."
Else
    For Each objService in colServices 
        Wscript.Echo "Automatic Updates: " & objService.State
    Next
End If

Because the focus of this month’s column is on Windows Update and not WMI, we won’t say much about this script other than the fact that it queries the computer for all services with a DisplayName of Automatic Updates. The script then checks the Count property of the returned collection, which happens to represent the number of items in that collection. If Count is equal to 0, then no instances of the service were found, and we assume that Automatic Updates is not installed. If Count is anything other than 0, we assume that Automatic Updates is installed, and we echo both that fact and the current state of the service.

Determining Whether Automatic Updates is Enabled

This script cannot be run against remote computers.

For better or worse, it’s possible to have the Automatic Updates service running yet still turn off Automatic Updates. Needless to say, knowing whether or not Automatic Updates is enabled is very important. Here’s a script that will not only tell you whether or not Automatic Updates is enabled, but will also tell you the “notification level” that has been configured (that is, whether updates will be automatically downloaded and installed, whether they will automatically be downloaded but not installed, etc.).

The code looks like this:

Set objAutoUpdate = CreateObject("Microsoft.Update.AutoUpdate")
Set objSettings = objAutoUpdate.Settings

Select Case objSettings.NotificationLevel
    Case 0
        Wscript.Echo "Notification level: Automatic Updates is not configured by the user " & _
            "or by a Group Policy administrator."
    Case 1
        Wscript.Echo "Notification level: Automatic Updates is disabled."
    Case 2
        Wscript.Echo "Notification level: Automatic Updates prompts users to approve updates " & _
            "before downloading or installing."
    Case 3
        Wscript.Echo "Notification level: Automatic Updates automatically downloads " & _
             "updates, but prompts users to approve them before installation."
    Case 4
        Wscript.Echo "Notification level: Automatic Updates automatically installs " & _
            "updates per the schedule specified by the user."
    Case Else
        Wscript.Echo "Notification level could not be determined."
End Select

The script begins by creating an instance of the Microsoft.Update.AutoUpdate object, then creating an instance of the Settings object. (The Settings object is a child object of Microsoft.Update.AutoUpdate.)

Note. We should point out that – alas – the Settings object cannot be created remotely; it can be created only on the local computer. What does that mean? Well, it means that you can’t run this script against a remote computer, the script must run locally. Admittedly, that probably isn’t the news you wanted to hear, but it is what it is. If you want to call us a clinging, clanking, clattering collection of congineous junk, we’ll understand.

After creating the Settings object all we have to do is echo the value of the NotificationLevel property. Because NotificationLevel is returned as an integer (for example, a 1 means that Automatic Updates have been disabled), we set up a Select Case block and then echo a more meaningful string value based on NotificationLevel. That’s it, that’s all we have to do to find out how Automatic Updates have been configured on a computer.

Enabling Automatic Updates

This script cannot be run against remote computers.

If you’re familiar with the movie The Wizard of Oz, then you know that reaching the Emerald City was only half the battle: once there, Dorothy discovered that, in order to earn passage home, she’d have to steal the broomstick of the Wicked Witch. As a system administrator you might find yourself in a somewhat analogous situation when dealing with Windows Update: now that you know how Automatic Updates have been configured on a computer you might need to change those updates. But could a young farm girl from Kansas – or a system administrator – configure Automatic Updates settings using a script?

Of course:

Const SCHEDULED_INSTALLATION = 4

Set objAutoUpdate = CreateObject("Microsoft.Update.AutoUpdate")
Set objSettings = objAutoUpdate.Settings

objSettings.NotificationLevel = SCHEDULED_INSTALLATION
objSettings.Save

As it turns out, NotificationLevel is a read/write property: to change the Automatic Updates settings all you need to do is set the NotificationLevel to the desired value, and then call the Save method. In the preceding script, we’ve defined a constant named SCHEDULED_INSTALLATION and assigned it the value 4; if you refer back to the script for determining whether Automatic Updates is enabled, you’ll see that 4 means updates will automatically be downloaded and installed according to a schedule specified by the user. After creating the Microsoft.Update.AutoUpdate object and the Settings child object, we use these two lines of code to change the value of NotificationLevel and then save those changes:

objSettings.NotificationLevel = SCHEDULED_INSTALLATION
objSettings.Save

Determining the Automatic Updates Schedule

This script cannot be run against remote computers.

As useful as it is to know that Automatic Updates has been enabled, it’s equally important to know when Automatic Updates is scheduled to run. This information can also be retrieved from the Settings object: you simply need to examine the values of the ScheduledInstallationDay and ScheduledInstallationTime properties:

Set objAutoUpdate = CreateObject("Microsoft.Update.AutoUpdate")
Set objSettings = objAutoUpdate.Settings

Select Case objSettings.ScheduledInstallationDay
    Case 0
        Wscript.Echo "Scheduled installation day: Every day"
    Case 1
        Wscript.Echo "Scheduled installation day: Sunday"
    Case 2
        Wscript.Echo "Scheduled installation day: Monday"
    Case 3
        Wscript.Echo "Scheduled installation day: Tuesday"
    Case 4
        Wscript.Echo "Scheduled installation day: Wednesday"
    Case 5
        Wscript.Echo "Scheduled installation day: Thursday"
    Case 6
        Wscript.Echo "Scheduled installation day: Friday"
    Case 7
        Wscript.Echo "Scheduled installation day: Saturday"
    Case Else
        Wscript.Echo "The scheduled installation day is could not be determined."
End Select

If objSettings.ScheduledInstallationTime = 0 Then
    Wscript.Echo "Scheduled installation time: 12:00 AM"
ElseIf objSettings.ScheduledInstallationTime = 12 Then
    Wscript.Echo "Scheduled installation time: 12:00 PM"
Else
    If objSettings.ScheduledInstallationTime > 12 Then
        intScheduledTime = objSettings.ScheduledInstallationTime - 12
        strScheduledTime = intScheduledTime & ":00 PM"
    Else
        strScheduledTime = objSettings.ScheduledInstallationTime & ":00 AM"
    End If
    Wscript.Echo "Scheduled installation time: " & strScheduledTime
End If

The script looks complicated, but that’s only because both ScheduledInstallationDay and ScheduledInstallationTime return values as integers; most of the preceding script does nothing more than convert those integer values into something a bit more meaningful. For example, the scheduled installation day is returned as one of the following values:

  • 0 – Every day

  • 1 – Sunday

  • 2 – Monday

  • 3 – Tuesday

  • 4 – Wednesday

  • 5 – Thursday

  • 6 – Friday

  • 7 – Saturday

In the script, we simply set up a Select Case block to check the value of ScheduledInstallationDay and then echo the day of the week (as opposed to a 5 or a 2). Likewise, ScheduledInstallationTime is returned as a number between 0 and 23, with 0 representing 12:00 AM, 1 representing 1:00 AM, and so on. Again, we simply convert that value to something a bit more readable.

Modifying the Automatic Updates Schedule

This script cannot be run against remote computers.

Oh, you spoiled our big surprise: yes, you can modify the scheduled date and time for Automatic Updates. And, again, this involves nothing more strenuous than configuring new values for the ScheduledInstallationDay and ScheduledInstallationTime properties and then calling the Save method to save those changes:

Const EVERY_THURSDAY = 5
Const FOUR_AM = 4

Set objAutoUpdate = CreateObject("Microsoft.Update.AutoUpdate")
Set objSettings = objAutoUpdate.Settings

objSettings.ScheduledInstallationDay = EVERY_THURSDAY
objSettings.ScheduledInstallationTime = FOUR_AM
objSettings.Save

We begin this script be defining two constants. EVERY_THURSDAY, with a value of 5, indicates that we want to check for new updates every Thursday; FOUR_AM, with a value of 4, means that we want this check to take place at 4:00 AM. We create an instance of the Microsoft.Update.AutoUpdate object (and its child object, Settings), and then use these three lines of code to modify the property values and save the changes:

objSettings.ScheduledInstallationDay = EVERY_THURSDAY
objSettings.ScheduledInstallationTime = FOUR_AM
objSettings.Save

Determining whether a Computer Needs to be Rebooted

This script cannot be run against remote computers.

Consider this a bonus script, a little gift from the Scripting Guys. As you know, some patches require the computer to be restarted before installation is complete; if this is a security patch, the computer could be vulnerable to an attack of some kind until the reboot has taken place. As you also probably know, when patches are installed users are presented with a dialog box that asks if they want to reboot now or later. A persistent and determined user can continually click the Later button (the dialog box reappears at periodic intervals) and thus never reboot the computer.

That’s where this script comes in: it can tell you whether a computer needs to be rebooted in order to complete installation of an update. Here’s what the script looks like:

Set objSysInfo = CreateObject("Microsoft.Update.SystemInfo")

If objSysInfo.RebootRequired Then
    Wscript.Echo "This computer needs to be rebooted."
Else
    Wscript.Echo "This computer does not need to be rebooted."
End If

No tricks here, and no men behind the curtain. All we do is create an instance of the Microsoft.Update.SystemInfo object and then check the value of the RebootRequired property. If RebootRequired is True, that means the computer must be rebooted to complete the installation of a patch. If RebootRequired is False, then no reboot is required.

Reviewing Updates on a Computer

This script can be run against remote computers.

One of the cool things that Windows Update does for you is keep track of your update history: that includes not just a record of updates that you installed on a computer, but also updates that you tried to install but couldn’t and updates that you uninstalled. Best of all, you can use a script to retrieve that history:

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

Set colHistory = objSearcher.QueryHistory(0, intHistoryCount)

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

    Select Case objEntry.Operation
        Case 1
            Wscript.Echo "Operation type: Installation"
        Case 2
            Wscript.Echo "Operation type: Uninstallation"
        Case Else
            Wscript.Echo "The operation type could not be determined."
    End Select

    Select Case objEntry.ResultCode
        Case 0
            Wscript.Echo "Operation result: The operation has not started."
        Case 1
            Wscript.Echo "Operation result: The operation is in progress."
        Case 2
            Wscript.Echo "Operation result: The operation completed successfully."
        Case 3
            Wscript.Echo "Operation result: The operation completed, but one or more errors occurred " & _
            "during the operation and the results are potentially incomplete."
        Case 4
            Wscript.Echo "Operation result: The operation failed to complete."
        Case 5
            Wscript.Echo "Operation result: The operation was aborted."
        Case Else
            Wscript.Echo "The operation result could not be determined."
    End Select

    Set objIdentity = objEntry.UpdateIdentity
    Wscript.Echo "Update ID: " & objIdentity.UpdateID
    Wscript.Echo
Next

This script begins by creating an instance of the Microsoft.Update.Session object, then uses the CreateUpdateSearcher method to create an instance of the Searcher object.

Note. We could actually create the Searcher object directly, and thus save one line of code. However, by using the Session object we can get this script to run against remote computers. For some reason, while we can use the Searcher object against remote computers, we can’t directly create it on remote computers. Go figure.

After creating our objects we use this code to get the total number of entries in the update history:

intHistoryCount = objSearcher.GetTotalHistoryCount

We need to do that because, in a minute, we’re going to use the QueryHistory method to retrieve all the entries in the history collection. When we call this method we have to specify – using index numbers – the first update we want to retrieve and the last update we want to retrieve. If we want to retrieve all the updates, we need to start with 0 and end with whatever number happens to represent the last item in the history list. By using the preceding line of code, we’ll have that last item stored in a variable named intHistoryCount, meaning we can retrieve all the update entries doing nothing more than this:

Set colHistory = objSearcher.QueryHistory(0, intHistoryCount)

After that we simply set up a For Each loop and walk through the history collection, echoing back some of the more useful property values along the way.

Yet Another Note. History entries are stored in inverse order: the last update event to take place is item 0, the next-to-the-last update event is item 1, and so on. If you only want to see information about the last update event, use this line of code:

Set colHistory = objSearcher.QueryHistory(0, 1)

Searching for Updates

This script can be run against remote computers.

We’re already running a bit long for a Tales from the Script column, so consider this script a bonus: it goes out to the Windows Update site and retrieves detailed information about all the software updates available for a computer. (Or, if you’re running an internal update server, it searches there instead.) We won’t dissect this script line-by-line, but we’ll make it available if you want to give it a try:

Set objSession = CreateObject("Microsoft.Update.Session")
Set objSearcher = objSession.CreateUpdateSearcher
Set objResults = objSearcher.Search("Type='Software'")
Set colUpdates = objResults.Updates

For i = 0 to colUpdates.Count - 1
    Wscript.Echo "Title: " & colUpdates.Item(i).Title
    Wscript.Echo "Autoselect on Web sites: " & colUpdates.Item(i).AutoSelectOnWebSites
    For Each strUpdate in colUpdates.Item(i).BundledUpdates
        Wscript.Echo "Bundled update: " & strUpdate
    Next
    Wscript.Echo "Can require source: " & colUpdates.Item(i).CanRequireSource
    Set objCategories = colUpdates.Item(i).Categories

    For z = 0 to objCategories.Count - 1
        Wscript.Echo "Category name: " & objCategories.Item(z).Name
        Wscript.Echo "Category ID: " & objCategories.Item(z).CategoryID
        For Each strChild in objCategories.Item(z).Children
            Wscript.Echo "Child category: " & strChild
        Next
        Wscript.Echo "Category description: " & objCategories.Item(z).Description
        Wscript.Echo "Category type: " & objCategories.Item(z).Type
    Next

    Wscript.Echo "Deadline: " & colUpdates.Item(i).Deadline
    Wscript.Echo "Delta compressed content available: " & _
        colUpdates.Item(i).DeltaCompressedContentAvailable
    Wscript.Echo "Delta compressed content preferred: " & _
        colUpdates.Item(i).DeltaCompressedContentPreferred
    Wscript.Echo "Description: " & colUpdates.Item(i).Description
    Wscript.Echo "EULA accepted: " & colUpdates.Item(i).EULAAccepted
    Wscript.Echo "EULA text: " & colUpdates.Item(i).EULAText
    Wscript.Echo "Handler ID: " & colUpdates.Item(i).HandlerID

    Set objIdentity = colUpdates.Item(i).Identity
    Wscript.Echo "Revision number: " & objIdentity.RevisionNumber
    Wscript.Echo "Update ID: " & objIdentity.UpdateID

    Set objInstallationBehavior = colUpdates.Item(i).InstallationBehavior
    Wscript.Echo "Can request user input: " & objInstallationBehavior.CanRequestUserInput

    Select Case objInstallationBehavior.Impact
        Case 0
            Wscript.Echo "Installation impact: Typical"
        Case 1
            Wscript.Echo "Installation impact: Negligible"
        Case 2
            Wscript.Echo "Installation impact: High"
        Case Else
            Wscript.Echo "The installation impact could not be determined."
    End Select

    Select Case objInstallationBehavior.RebootBehavior
        Case 0
            Wscript.Echo "Reboot behavior: No reboot required after installation."
        Case 1
            Wscript.Echo "Reboot behavior: A reboot is required after installation."
        Case 2
            Wscript.Echo "Reboot behavior: A reboot might be required after installation."
        Case Else
            Wscript.Echo "Reboot behavior: No information available regarding the need for a reboot."
    End Select

    Wscript.Echo "Requires network connectivity: " & objInstallationBehavior.RequiresNetworkConnectivity
    Wscript.Echo "Is beta: " & colUpdates.Item(i).IsBeta
    Wscript.Echo "Is hidden: " & colUpdates.Item(i).IsHidden
    Wscript.Echo "Is installed: " & colUpdates.Item(i).IsInstalled
    Wscript.Echo "Is mandatory: " & colUpdates.Item(i).IsMandatory
    Wscript.Echo "Is uninstallable: " & colUpdates.Item(i).IsUninstallable
    For Each strLanguage in colUpdates.Item(i).Languages
        Wscript.Echo "Supported language: " & strLanguage
    Next

    Wscript.Echo "Last deployment change time: " & colUpdates.Item(i).LastDeploymentChangeTime
    Wscript.Echo "Maximum download size: " & colUpdates.Item(i).MaxDownloadSize
    Wscript.Echo "Minimum download size: " & colUpdates.Item(i).MinDownloadSize
    Wscript.Echo "Microsoft Security Response Center severity: " & colUpdates.Item(i).MsrcSeverity
    Wscript.Echo "Support URL: " & colUpdates.Item(i).SupportURL

    Select Case colUpdates.Item(i).Type
        Case 1
            Wscript.Echo "Update type: Software"
        Case 2
            Wscript.Echo "Update type: Driver"
       Case Else
            Wscript.Echo "Update type: The update type could not be determined."
    End Select

    Wscript.Echo "Uninstallation notes: " & colUpdates.Item(i).UninstallationNotes

    x = 1
    For Each strStep in colUpdates.Item(i).UninstallationSteps
        Wscript.Echo x & " -- " & strStep
        x = x + 1
    Next

    For Each strArticle in colUpdates.Item(i).KBArticleIDs
        Wscript.Echo "KB article: " & strArticle
    Next

    Wscript.Echo

Next

As we noted, the preceding script looks at software updates. If you want to check for driver and other hardware updates then simply change line 3 to this:

Set objResults = objSearcher.Search("Type='Driver'")

Determining if a Particular Update has Been Installed

This script can be run against remote computers.

OK, just one more script then we’re done. The search mechanism for Automatic Updates is somewhat limited in scope: although you can filter by properties such as Type and IsInstalled, you can’t really search for a specific update (e.g., by Title). That leads to an obvious question: if you can’t search for a specific update, then how can you write a script that tells you whether a particular update is installed or not?

The answer is to use brute force: to “search” for a specific update all you have to do is return a collection of updates and then loop through that collection, checking for the update and whether or not it has been installed. Here’s a sample script that checks to see if the Microsoft Windows Rights Management Services Client with Service Pack 1 update has been installed on a computer:

Set objSession = CreateObject("Microsoft.Update.Session")
Set objSearcher = objSession.CreateUpdateSearcher
Set objResults = objSearcher.Search("Type='Software'")
Set colUpdates = objResults.Updates

For i = 0 to colUpdates.Count - 1
    If colUpdates.Item(i).Title = _
        "Microsoft Windows Rights Management Services Client with Service Pack 1" Then
        If colUpdates.Item(i).IsInstalled <> 0 Then
            Wscript.Echo "This update is installed."
            Wscript.Quit
        Else
            Wscript.Echo "This update is not installed."
            Wscript.Quit
        End If
    End If
Next

We begin by creating a series of object references. If these object references look familiar, they should: the first five lines of code are exactly the same as our previous script, the one that returned a collection of all the updates. There’s a good reason for that: this script also returns a collection of all the updates.

It’s only when we get inside our For Next loop that the two scripts diverge. In our previous script we simply began echoing back property values for the updates. With this script, we aren’t interested in all the updates; we’re interested in only one particular update. Therefore, as we loop through the collection we use this line of code to determine if the Title of the current update is equal to Microsoft Windows Rights Management Services Client with Service Pack 1:

If colUpdates.Item(i).Title = _
    "Microsoft Windows Rights Management Services Client with Service Pack 1" Then

What happens if we find an update by that name? We use this line of code to check the value of the IsInstalled property:

If colUpdates.Item(i).IsInstalled <> 0 Then

If IsInstalled is equal to 0 that means the update is not installed. By extension, then, if IsInstalled is not equal to 0 that means the update is installed. If that’s the case, we echo a message saying that the update is installed. We then use the Wscript.Quit method to exit the script. (Why? Well, we’ve found the update and determined that it’s already installed; because of that, there’s no need to continue searching. Therefore, we just exit the script.)

If IsInstalled equals 0, then the update is not installed. Consequently we echo a message to that effect, and then terminate the script. It’s not quite as elegant as a full-fledged search, but the net result is the same: we know whether or not this particular update is installed on the computer.

Toto, I've a Feeling We Can’t Complain About Windows Update Any More

After Glinda told Dorothy about the ruby slippers, and about how she could have used them at any time to go home, the Scarecrow got a little upset. “Then why didn’t you tell her?” he demanded. “Because she wouldn’t have believed me,” replied Glinda. “She had to learn it for herself.” Admittedly, had we just come out and told you that you could use scripts to manage Automatic Updates you probably would have believed us; still, we hope that learning it for yourselves wasn’t a total loss. Don’t forget, too, we’ve only scratched the surface of what you can do to automatic Windows Update; for more information, see the Windows Update Agent API.

Oh, and the next time you’re bemoaning the lack of an easy way to carry out some sort of system administration task, just remember the words of the Cowardly Lion: “I do believe in scripts. I do believe in scripts. I do, I do, I do, I do, I do believe in scripts….”

If you have questions or comments about this month’s column, please send them (preferably by flying monkey) to scripter@microsoft.com (in English, if possible).