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.

Photo of book cover

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.comscriptw2
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