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()
…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()
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()
It is slowly getting there. I will check back shortly and see if it has completed yet.
There we go. Now we are ready to jump back into working with updates.
Let’s try this again…
$updates = $wsus.GetUpdates()
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”)
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
$update = $wsus.SearchUpdates(‘943485’)
$update.count
$update | Select Title
$patches = $wsus.SearchUpdates(‘Windows 7’)
$patches.count
$patches | Select Title
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)
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)
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”)
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
0 comments