Approve or Decline WSUS Updates by Using PowerShell

Approve or Decline WSUS Updates by Using PowerShell

  • Comments 10
  • Likes

Summary: Guest blogger, Boe Prox, shows how to use Windows PowerShell to approve or to decline updates for WSUS.

Microsoft Scripting Guy, Ed Wilson, is here. Welcome to the third day of Boe Prox as our guest blogger talking about using Windows PowerShell with WSUS.

Day 1: Introduction to WSUS and PowerShell

Day 2: Use PowerShell to Perform Basic Administrative Tasks on WSUS

Here’s Boe…

Continuing on from yesterday’s post where we looked at managing clients and groups, it is time to look at that one thing that really defines the WSUS server. I am talking about updates, of course! We will start by performing a basic query to locate updates and explore the update object to see what methods we have available, and then we will go into approving and declining updates.

Update queries

Using our existing connection from the previous day’s examples, let’s look at the possible methods related to locating updates on the WSUS server.

GetUpdates()

This method will give you back EVERY SINGLE UPDATE on your WSUS server. (This is assuming that you have completed a successful synchronization—if not, synchronize your WSUS server now.) This method is painfully slow to run and it is not a recommended method to gather information about updates.

$wsus.GetUpdates()

Image of command output

…Well, this is awkward. Oh wait, since I just installed this WSUS server, I have not performed a critical task that will allow me to start viewing updates. I need to synchronize this WSUS server with the Microsoft upstream server and get all of my update data.

WSUS synchronization

Let’s take a detour on our little trip through working with updates to get this server synced up and ready to go. To get this going, we need to look at the GetSubscription() method to see when the last synchronization was and also to use that object’s method to work with the synchronization. The object that is returned when you use this method is Microsoft.UpdateServices.Internal.BaseApi.Subscription.

$wsus.GetSubscription()

Image of command output

Take a look at LastSynchronizationTime, and you will see that this WSUS server has not been synced yet. Synching this server is pretty simple. We will use this object’s method, which is conveniently named StartSynchronization(). Let’s go ahead and kick this off.

$subscription = $wsus.GetSubscription()

$subscription.StartSynchronization()

Nothing is returned when you kick this off, so we need a way to track this process and find out when it is finished. Enter the GetSynchronizationProgress() method, which will tell us exactly where we are with the sync process.

$subscription.GetSynchronizationProgress()

Image of command output

It is slowly getting there. I will check back shortly and see if it has completed yet.

Image of command output

There we go. Now we are ready to jump back into working with updates.

Let’s try this again…

$updates = $wsus.GetUpdates()

Image of command output

That’s more like it. Now I have over 5500 updates to work with.

As you can see, calling GetUpdates() will get every single update on the server. But, what if we only want to get a specific update or updates? Instead of getting all of the updates and using Where-Object to filter them, you can use one of the following methods to accomplish that goal. (By the way, there is one more thing that we can use with GetUpdates() to get specific updates, but I am leaving that piece out until later in the week.)

$wsus.GetUpdate()

This method is quick to get the update that you are looking for. The only issue is that this method requires you to know the update ID, which is a GUID. Not exactly something a person will know off of the top of one’s head, but it is an option regardless.

$wsus.GetUpdate([guid]” fc08b450-6bdd-400e-9a1a-2f86e23ce462”)

Image of command output

Now, on to the last way to get more specific updates—this time using the following method:

SearchUpdates()

This method is very flexible to use because it only requires a string for input. This string can be anything from the KB number for the patch, the actual patch name, or even something as simple as the type of system that the patch would be installed on (such as Exchange Server). Let’s look at a few examples of performing some searches:

$SQL = $wsus.SearchUpdates(‘SQL’)

$SQL.count

$SQL | Select Title

Image of command output

$update = $wsus.SearchUpdates('943485')

$update.count

$update | Select Title

Image of command output

$patches = $wsus.SearchUpdates(‘Windows 7’)

$patches.count

$patches | Select Title

Image of command output

Now that we know how to find updates on the WSUS server, we can start to explore the update object (Microsoft.UpdateServices.Internal.BaseApi.Update).

There quite a few methods that are available for the update object, so we will focus on three methods that are pretty useful for administering updates on the server.

Accepting license agreements

You might be asking me why accepting license agreements would be one of the three things that I would want to focus on. Well, this is not an issue…until it becomes an issue when you are trying to approve an update. There is a property that has a Boolean value called RequireLicenseAgreementAcceptance that we can use in our filtering to locate any updates that require a license acceptance before you can approve the updates.

$license = $updates | Where {$_.RequiresLicenseAgreementAcceptance}

$license | Select Title

We can use the method AcceptLicenseAgreement() to accept the agreement for the update.

$license | ForEach {$_.AcceptLicenseAgreement()}

With that, all of the updates that had a requirement to accept a license agreement have been taken care of, allowing us to start approving some updates!

Approving updates

There are three ways that you can approve updates on the WSUS server by using PowerShell—one by using ApproveForOptionalInstall() and two by using Approve(). They require that we use the TargetGroup object to tell the server what group we will approve each update for. Yesterday, I talked about how to get a target group; now we can easily grab a group to use for each type of approval. The Approve method also requires that you pick an installation action (I will go into more detail when we get to that method).

The main difference between ApproveForOptionalInstall and Approve is that ApproveForOptionalInstall will approve the update for the target group, but the update will not actually install. However, it is made available to the user for installation via Add/Remove Programs. Approve will approve the update with or without a deadline (your choice—I will explain later how to do this).

Let’s start with the optional installation first…

$update = $wsus.SearchUpdates('Windows 7 for x64-based Systems (KB2639417)')

$group = $wsus.GetComputerTargetGroups() | where {$_.Name -eq 'TESTGROUP'}

$update[0].ApproveForOptionalInstall($Group)

Image of command output

Here I approved a Windows 7 update for my TESTGROUP in which my laptop is currently a member. Notice that it returns another object called Microsoft.UpdateServices.Internal.BaseApi.UpdateApproval. This object tells you when it was approved, the time that the update will “go live,” and who approved the update. It is important to note that the update object you get is a collection, even if you only get one item back. Therefore, I had to be sure to use the first index of the collection to use this method for approval.

By using Approve() method, we have two ways in which to approve the updates. Both require that you have the target group object, but one also has the requirement of setting a deadline by using the [datetime] object.

Do you remember when I mentioned using an installation action for the approval? Well, now it is time to use one of those actions for this approval. But how do we know what installation actions we can use? We will find out what our options are by using Microsoft.UpdateServices.Administration.UpdateApprovalAction.

[Microsoft.UpdateServices.Administration.UpdateApprovalAction] | gm -static -Type Property | Select –expand Name

The installation actions that are returned are:

All

Install

NotApproved

Uninstall

Now that we know what kinds of actions we can use, let’s make an approval without using a deadline.

$update = $wsus.SearchUpdates(‘Update for 2007 Microsoft Office System (KB932080)')

$group = $wsus.GetComputerTargetGroups() | where {$_.Name -eq 'TESTGROUP'}

$update[0].Approve(“Install”,$Group)

Image of command output

Again, the same object type is returned with the same data that we would expect.

We can set a deadline on our next update for approval. Basically, setting a deadline on a patch will force that update to be installed at that specific time. For instance, I will approve an update that will get installed on Dec. 15 at 11:00 PM.

$update = $wsus.SearchUpdates(‘932080’)

$group = $wsus.GetComputerTargetGroups() | where {$_.Name -eq 'TESTGROUP'}

$update[0].Approve(“Install”,$Group,[datetime]”12/15/2011 11:00PM”)

Image of command output

Notice that the Deadline is set to the time that I specified instead of it being way out in the year 9999. Now the update will install on the server at that specific time without manual intervention.

You might be asking, “How were you able to determine what updates were required by your systems?” Well, besides jumping into the WSUS Administration Console to view those updates, there is another way that I can locate updates, but that will have to wait until later this week when I introduce another object and way to search for updates.

Declining an update

So we have approved updates, but we also need to know how to decline updates that are not needed by any system or are deemed unneeded by us for various reasons. Luckily, declining an update is as simple as using the Decline() method.

$update = $wsus.SearchUpdates(‘932080’)

$update[0].Decline()

Unlike the approvals, no object is returned when you decline an update. Regardless, this is a simple and effective way to decline updates that you do not need.

That wraps it up for today’s blog focusing on update management by using Windows PowerShell. Although I really only scratched the surface of working with updates, I hope I was able to give you enough information to make the leap into patch management using Windows PowerShell. Tomorrow I will dive into working with the computer scope object and how you can use that object with some of the objects we have seen this week and some of their associated methods that only accept the computer scope object.

~Boe

Boe, thank you once again for a very useful and informative blog about using Windows PowerShell and WSUS. WSUS Week will continue tomorrow.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • <p>How do I decline all updates and start from scratch my initial sync did not finish becase it ran out of disk space </p>

  • <p>@Andrew</p> <p>Can you elaborate more on what you mean by &quot;starting from scratch&quot;?</p> <p>You can run the following code to decline all updates in WSUS:</p> <p>[void][reflection.assembly]::LoadWithPartialName(&quot;Microsoft.UpdateServices.Administration&quot;)</p> <p>$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer(“WSUSServer”,$False)</p> <p>$wsus.GetUpdates() | ForEach {</p> <p> &nbsp; &nbsp;Write-Verbose (&quot;Declining {0}&quot; -f $_.Title) -Verbose</p> <p> &nbsp; &nbsp;$_.Decline()</p> <p>}</p> <p>Hope this helps...</p>

  • <p>how do I get a list of needed updates for a computer or a computer group?</p> <p>and then how do I approve those updates for the computer or the group?</p> <p>Thanks</p>

  • <p>I have a group in WSUS called NoDotNetPatches and I want all updates apart from any .Net patches to be approved every month. &nbsp;Any help on how to script this in Powershell would be greatly appreciated as I&#39;ve only just started using Powershell.</p>

  • I get the following, "You cannot call a method on a null-valued expression."

  • @Joel At what part do you get that error message?

  • @Andre Check out this article on finding updates that are needed by clients: http://blogs.technet.com/b/heyscriptingguy/archive/2012/01/19/use-powershell-to-find-missing-updates-on-wsus-client-computers.aspx You can then pull those updates and run a ForEach using my examples in this article to approve each update for the Target Group.

  • Is there a way to approve all updates without going through each one at a time? I'm doing it as a ForEach right now and it takes extremely long when there is a large number of updates. Thanks!

  • @Cliff<br/><br/>Unfortunately, there really is not a quick way to approve a lot of updates. Your method of using ForEach is the best method to accomplish this.