Summary: Honorary Scripting Guy, Boe Prox, shares an excerpt from his contribution to the book, PowerShell Deep Dives.
Microsoft Scripting Guy, Ed Wilson, is here. This week we will not have our usual PowerTip. Instead we have excerpts from seven books from Manning Press. In addition, each blog will have a special code for 50% off the book being excerpted that day. Remember that the code is valid only for the day the excerpt is posted. The coupon code is also valid for a second book from the Manning collection.
Today, the excerpt is from PowerShell Deep Dives
Edited by Jeffery Hicks, Richard Siddaway, Oisin Grehan, and Aleksandar Nikolic.
Whether you just started using Windows PowerShell or are at a more advanced level, there are two things you should always look at while writing a script: performance and execution time. With the introduction of Windows PowerShell 3.0 there are a lot of new modules and cmdlets available to you. What a lot of people don’t realize is that Microsoft also improves and expands already existing modules, and their cmdlets. This is especially the case with Windows PowerShell 3.0.
Here’s Boe…
Although the UI can be clunky and slow, there is an API with WSUS, a new module that is available in Windows Server 2012, and even an open source WSUS module that I wrote called PoshWSUS, which can more effectively allow you to quickly manage and generate reports by using Windows PowerShell.
Instead of looking at the existing cmdlets available in the 2012 Windows Server Update Services module, I will dive into the API and show you some tricks to further extend the reach of Windows PowerShell into WSUS. I’ll show how to:
- Look at the WSUS configuration and events.
- Provide reporting on various client and patch statuses.
- Start and view synchronization progress and history.
- Viewing and create automatic installation rules to simplify patch management by approving the common updates that your clients require.
WSUS server configuration and events
In WSUS, some of the most basic administration concepts are client management and patch management. Before Windows Server 2012, the only two solutions to this were working with the UI or digging into the API via scripts or the open source module, PoshWSUS. With Server 2012, we now have a WSUS module called UpdateServices that makes managing clients easier. The UpdateServices module is only available to use on the WSUS server, which isn’t bad if you plan to use Windows PowerShell remoting to manage the server. If you are not running Windows Server 2012, the module will not be available, and you need to use the API to manage a remote WSUS server.
Initial connection
To make a connection to the WSUS server locally or remotely with the API, you need the WSUS Administration console installed on the system that you will be making the connection from. After the console has been installed, you will have access to the required assemblies that you can the load and use for the WSUS connection. So with that, lets load the assembly, and then we can make the initial connection to the WSUS server.
[reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration") | out-null
For the connection attempt, I will be using the Microsoft.UpdateServices.Administration.AdminProxy class along with the GetUpdateServer() method. This method accepts 1 of 3 parameter sets based on your WSUS configuration and if it is a remote or local connection. For the remote connection that I will be making, I need only supply the remote system name, a Boolean value that will say whether the connection is secure, and the remote port that I need to connect to on the WSUS server. (Acceptable ports for WSUS are 8080 and 8530 for non-secure ports and 443 and 8531 for SSL.)
$Wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer(
"Boe-PC",
$False,
"8530"
)
$Wsus
WebServiceUrl : http://BOE-PC:8530/ApiRemoting30/WebService.asmx
BypassApiRemoting : False
IsServerLocal : True
Name : BOE-PC
Version : 6.2.9200.16384
IsConnectionSecureForApiRemoting : True
PortNumber : 8530
PreferredCulture : en
ServerName : BOE-PC
UseSecureConnection : False
ServerProtocolVersion : 1.8
From here, you can see what version of the WSUS software you are running, among other things. The most important thing here is that you can now see that we have successfully connected to the WSUS server.
Viewing WSUS configuration
After the initial connection has been made, you can easily take a look at the internal configuration settings of the WSUS server by using the GetConfiguration()method of the Microsoft.UpdateServices.Internal.BaseApi.UpdateServer object.
$wsus.GetConfiguration()
UpdateServer : Microsoft.UpdateServices.Internal.BaseApi.UpdateServer
LastConfigChange : 9/17/2012 2:22:43 AM
ServerId : 64ad0f03-e81d-4539-883d-0c08066d1e82
SupportedUpdateLanguages : {he, cs, fr, es...}
TargetingMode : Server
SyncFromMicrosoftUpdate : True
IsReplicaServer : False
HostBinariesOnMicrosoftUpdate : False
UpstreamWsusServerName :
UpstreamWsusServerPortNumber : 8530
UpstreamWsusServerUseSsl : False
UseProxy : False
ProxyName :
ProxyServerPort : 80
UseSeparateProxyForSsl : False
SslProxyName :
SslProxyServerPort : 443
AnonymousProxyAccess : True
ProxyUserName :
ProxyUserDomain :
HasProxyPassword : False
AllowProxyCredentialsOverNonSsl : False
…
This is just a marginal number of the 121 properties that are returned with this method. The majority of these properties are settable, meaning that you can easily update these from Windows PowerShell. Use caution when making any changes to the properties because it could leave your server in an unusable state!
Viewing the WSUS database connection
You can take a look at the database connection and the database properties from your WSUS server by using the GetDatabaseConfiguration() method and the CreateConnection() method from the created Microsoft.UpdateServices.Internal.DatabaseConfiguration object.
$wsus.GetDatabaseConfiguration()
UpdateServer : Microsoft.UpdateServices.Internal.BaseApi.UpdateServer
ServerName : MICROSOFT##WID
DatabaseName : SUSDB
IsUsingWindowsInternalDatabase : True
AuthenticationMode : WindowsAuthentication
UserName :
Password :
$wsus.GetDatabaseConfiguration().CreateConnection()
QueryTimeOut : 150
LoginTimeOut : 60
ConnectionPooling : True
ApplicationName : WSUS:powershell:1824
UserLoginName :
UseIntegrated : True
ConnectionString :
MaxPoolSize : 100
DoRetry : False
DefaultRetryTimes : 3
ServerName : MICROSOFT##WID
DatabaseName : SUSDB
Password :
IsConnected : False
InTransaction : False
The amount of detail that you can get regarding the database is pretty nice. In fact, you could dive even deeper into the database if you wanted, but that is beyond the scope of this blog.
Viewing WSUS event history
If you are interested in viewing the event history of the WSUS server, it can be reached by calling the GetUpdateEventHistory(StartDate,EndDate)method and supplying a Start Date and an End Date. In this case, I just want to look at the events that have occurred during the past hour.
$wsus.GetUpdateEventHistory("$((Get-Date).AddHours(-1))","$(Get-Date)")
UpdateServer : Microsoft.UpdateServices.Internal.BaseApi.UpdateServer
HasAssociatedUpdate : False
UpdateId : Microsoft.UpdateServices.Administration.UpdateRevisionId
HasAssociatedComputer : False
ComputerId :
Status : Unknown
WsusEventId : ContentSynchronizationSucceeded
WsusEventSource : Server
Id : f01cb84f-9a0b-4da8-a12a-39a6866c5787
CreationDate : 9/23/2012 7:08:20 PM
Message : Content synchronization succeeded.
IsError : False
ErrorCode : 0
Row : Microsoft.UpdateServices.Internal.DatabaseAccess.EventHistoryTableRow
UpdateServer : Microsoft.UpdateServices.Internal.BaseApi.UpdateServer
HasAssociatedUpdate : True
UpdateId : Microsoft.UpdateServices.Administration.UpdateRevisionId
HasAssociatedComputer : False
ComputerId :
Status : Unknown
WsusEventId : ContentSynchronizationFileDownloadSucceeded
WsusEventSource : Server
Id : 0c7ade08-87d6-4019-b676-0f50ce486591
CreationDate : 9/23/2012 7:08:20 PM
Message : Content file download succeeded. Digest: Source File: /msdownload/update/v3-19990518/cabpool/w
indowsinstaller-kb893803-v2-x86_830994754ba721add8a13bd0266d2e092f21cab0.exe Destination File:
F:\WsusContent\B0\830994754BA721ADD8A13BD0266D2E092F21CAB0.exe.
IsError : False
ErrorCode : 0
Row : Microsoft.UpdateServices.Internal.DatabaseAccess.EventHistoryTableRow
With this information, you could audit for any possible failures that have occurred with a recent synchronization or some other issue that might be cause for a WSUS issue.
Automatic Approval Rules
With WSUS, you can automate your patch approvals simply by creating and configuring Automatic Approval Rules. You can specify categories, target groups among other things to use for the rules.
Locating approval rules
To find out what approval rules are currently on the WSUS server, use the GetApprovalRules() method from the Microsoft.UpdateServices.Internal.BaseApi.UpdateServer object created from the initial connection.
$wsus.GetInstallApprovalRules()
UpdateServer : Microsoft.UpdateServices.Internal.BaseApi.UpdateServer
Id : 2
Name : Default Automatic Approval Rule
Enabled : False
Action : Install
Deadline :
CanSetDeadline : True
This is not actually all of the information for the approval rules. To find out what Target Groups, Classifications, and Categories are contained in the Microsoft.UpdateServices.Internal.BaseApi.AutomaticUpdateApprovalRule object, you need to use the GetComputerTargetGroups(), GetUpdateClassifications(), and GetUpdateCategories() methods, respectively.
$approvalRules = $wsus.GetInstallApprovalRules()
#Get the Update Classifications
$wsus.GetInstallApprovalRules()[0].GetUpdateClassifications()
UpdateServer : Microsoft.UpdateServices.Internal.BaseApi.UpdateSer
ver
Id : e6cf1350-c01b-414d-a61f-263d14d133b4
Title : Critical Updates
Description : A broadly released fix for a specific problem
addressing a critical, non-security related bug.
ReleaseNotes :
DefaultPropertiesLanguage :
DisplayOrder : 2147483647
ArrivalDate : 9/23/2012 6:51:37 PM
UpdateServer : Microsoft.UpdateServices.Internal.BaseApi.UpdateSer
ver
Id : 0fa1201d-4330-4fa8-8ae9-b877473b6441
Title : Security Updates
Description : A broadly released fix for a product-specific
security-related vulnerability. Security
vulnerabilities are rated based on their severity
which is indicated in the Microsoft® security
bulletin as critical, important, moderate, or low.
ReleaseNotes :
DefaultPropertiesLanguage :
DisplayOrder : 2147483647
ArrivalDate : 9/23/2012 6:40:34 PM
#Get the Computer Target Groups
$wsus.GetInstallApprovalRules()[0].GetComputerTargetGroups()
UpdateServer Id Name
------------ -- ----
Microsoft.UpdateService... a0a08746-4dbe-4a37-9adf... All Computers
#Get the Categories
$wsus.GetInstallApprovalRules()[0].GetCategories()
Type : Product
ProhibitsSubcategories : True
ProhibitsUpdates : False
UpdateSource : MicrosoftUpdate
UpdateServer : Microsoft.UpdateServices.Internal.BaseApi.UpdateSer
ver
Id : a105a108-7c9b-4518-bbbe-73f0fe30012b
Title : Windows Server 2012
Description : Windows Server 2012
ReleaseNotes :
DefaultPropertiesLanguage :
DisplayOrder : 2147483647
ArrivalDate : 9/23/2012 6:47:20 PM
Creating approval rules
Creating an approval is a simple process that involves first creating the approval object with a name and then filling in the blanks for the rest of the configuration (Target Groups, Categories, Classifications, and so on) on the object before deploying it on the server. First, verify that the rule I am going to create (named “2012Servers”) doesn’t exist:
#Look at current rules
$wsus.GetInstallApprovalRules()
UpdateServer : Microsoft.UpdateServices.Internal.BaseApi.UpdateServer
Id : 2
Name : Default Automatic Approval Rule
Enabled : False
Action : Install
Deadline :
CanSetDeadline : True
No Rules exist with the name I plan to use, so I can continue with the creation of the new Approval Rule.
Listing 1: Creating an Approval Rule
[cmdletbinding()]
Param (
[parameter(ValueFromPipeline=$True,Mandatory=$True,
HelpMessage="Name of WSUS server to connect to.")]
[Alias('WSUSServer')]
[string]$Computername,
[parameter()]
[Switch]$UseSSL
)
[reflection.assembly]::LoadWithPartialName(
"Microsoft.UpdateServices.Administration"
) | out-null
$Wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer(
$Computername,$UseSSL,$Port
)
#Create New Rule Object
$newRule = $wsus.CreateInstallApprovalRule("2012Servers")
##Categories
#Get Categories for Windows Server
$updateCategories = $wsus.GetUpdateCategories() | Where {
$_.Title -LIKE "Windows Server 2012*"
}
#Create collection for Categories
$categoryCollection = New-Object Microsoft.UpdateServices.Administration.UpdateCategoryCollection
$categoryCollection.AddRange($updateCategories)
#Add the Categories to the Rule
$newRule.SetCategories($categoryCollection)
##Classifications
#Get all Classifications for specific Classifications
$updateClassifications = $wsus.GetUpdateClassifications() | Where {
$_.Title -Match "Critical Updates|Service Packs|Updates|Security Updates"
}
#Create collection for Categories
$classificationCollection = New-Object Microsoft.UpdateServices.Administration.UpdateClassificationCollection
$classificationCollection.AddRange($updateClassifications )
#Add the Classifications to the Rule
$newRule.SetUpdateClassifications($classificationCollection)
##Target Groups
#Get Target Groups required for Rule
$targetGroups = $wsus.GetComputerTargetGroups() | Where {
$_.Name -Match "All Computers"
}
#Create collection for TargetGroups
$targetgroupCollection = New-Object Microsoft.UpdateServices.Administration.ComputerTargetGroupCollection
$targetgroupCollection.AddRange($targetGroups)
#Add the Target Groups to the Rule
$newRule.SetComputerTargetGroups($targetgroupCollection)
#Finalize the creation of the rule object
$newRule.Enabled = $True
$newRule.Save()
#Run the rule
$newRule.ApplyRule()
Let’s make sure that the rule is now created.
$wsus.GetInstallApprovalRules()
UpdateServer : Microsoft.UpdateServices.Internal.BaseApi.UpdateServer
Id : 2
Name : Default Automatic Approval Rule
Enabled : False
Action : Install
Deadline :
CanSetDeadline : True
UpdateServer : Microsoft.UpdateServices.Internal.BaseApi.UpdateServer
Id : 6
Name : 2012Servers
Enabled : True
Action : Install
Deadline :
CanSetDeadline : True
Now we have a new Approval Rule that will run to approve only the updates I specified to only Windows Server 2012 systems. Keep in mind that the automatic approval rules only run after WSUS synchronizes, and only synched updates will be eligible for the rule unless you run the rule manually.
In today’s blog, I showed a number of things that you can do with Windows PowerShell to manage your WSUS server by using the available APIs, such as looking at the configuration settings of the WSUS server and auditing events. Auditing and building Automatic Approval Rules and providing more detailed reporting is easily accomplished by using the APIs.
With Windows Server 2012, you do have the option of using the Update Services module to perform some basic WSUS administration such as patch approvals, but for more advanced configurations and reporting, the APIs are definitely the way to go.
There is also a module that I wrote called PoshWSUS that provides cmdlets that allow for a more advanced administration. With multiple options for automating your WSUS server, you can’t go wrong. If you write some scripts for your own WSUS server, I hope that you will share those with the rest of the community.
Here is the code for the discount offer today at www.manning.com: scriptw2
Valid for 50% off PowerShell Deep Dives and SQL Server Deep MVP Dives
Offer valid from April 2, 2013 12:01 AM until April 3 midnight (EST)
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