How to Determine All Approved Updates

 

Applies To: Windows Server Update Services

Use the following procedure to determine all approved updates for the current Windows Server Update Services (WSUS) server. The example that follows shows a working command-line application where all approved updates are written to an XML file for reporting purposes.

To determine all approved updates

  1. Add the Microsoft.UpdateServices.Administration assembly to your project.

  2. Insert a using statement for the Microsoft.UpdateServices.Administration namespace.

    using Microsoft.UpdateServices.Administration;  
    
  3. Using the AdminProxy.GetUpdateServer method, connect to the local WSUS server.

    // Connect to the local server  
    IUpdateServer updateServer = AdminProxy.GetUpdateServer();  
    
  4. Instantiate an UpdateScope object and after setting its ApprovedStates property to reflect the updates you’re looking for, call the IUpdateServer.GetUpdates method, passing in the UpdateScope object.

    // Get the list of updates that are approved or that have an older revision that is approved  
    UpdateScope updateScope = new UpdateScope();  
    updateScope.ApprovedStates = ApprovedStates.HasStaleUpdateApprovals | ApprovedStates.LatestRevisionApproved;  
    UpdateCollection updates = updateServer.GetUpdates(updateScope);  
    
  5. Calling the IUpdate.GetUpdateApprovals method once for each update is inefficient in this particular case. Therefore, call the IUpdateServer.GetUpdateApprovals method to get all approvals for all updates at once.

    // Get all approvals for all updates at once  
    UpdateApprovalCollection allUpdateApprovals = updateServer.GetUpdateApprovals(updateScope);  
    
  6. Instantiate a .NET Dictionary object that will have as its key the UpdateRevisionId and, as its value, an UpdateApprovalCollection object containing all approvals for that UpdateRevisionId.

    // Create a dictionary so we can look up the list of approvals for any given update  
    Dictionary<UpdateRevisionId, UpdateApprovalCollection> updateApprovalDictionary = new Dictionary<UpdateRevisionId, UpdateApprovalCollection>();  
    foreach (IUpdateApproval updateApproval in allUpdateApprovals)  
    {  
       // If there is no entry in the dictionary for this update, then add one  
       if (!updateApprovalDictionary.ContainsKey(updateApproval.UpdateId))  
       {  
          updateApprovalDictionary.Add(updateApproval.UpdateId, new UpdateApprovalCollection());  
       }  
    
       // Add this approval to the corresponding update's list of approvals  
       updateApprovalDictionary[updateApproval.UpdateId].Add(updateApproval);  
    }  
    
  7. Using the IUpdateServer.GetComputerTargetGroups method, get the collection of all target groups for the WSUS server.

    // Get all target groups  
    ComputerTargetGroupCollection allTargetGroups = new ComputerTargetGroupCollection();  
    allTargetGroups = updateServer.GetComputerTargetGroups();  
    
  8. Instantiate a .NET Dictionary object that will have as its key the target group GUID and, as its value, the corresponding IComputerTargetGroup object.

    // Create a dictionary for the target groups (GUID -> IComputerTargetGroup)  
    Dictionary<Guid, IComputerTargetGroup> targetGroupDictionary = new Dictionary<Guid, IComputerTargetGroup>();  
    
  9. For each target group, add an entry in the dictionary pointing the target group GUID to the IComputerTargetGroup object.

    // For each target group, add an entry in the dictionary pointing the target group GUID to the IComputerTargetGroup object  
    foreach (IComputerTargetGroup targetGroup in allTargetGroups)  
    {  
       targetGroupDictionary.Add(targetGroup.Id, targetGroup);  
    }  
    
  10. Code a foreach loop that will iterate through all of the updates returned from the IUpdateServer.GetUpdates method call. If the IUpdate.IsApproved property is set to true, a helper method (WriteApprovals) is called. (The WriterApproval method is listed in the next section along with all of the source code for this sample.) If the IUpdate.IsApproved property is false and the IUpdateHasStaleUpdateApprovals property is true, the code loops through all approved older revisions, calling the WriteApprovals method for each.

    //Loop through the updates, writing any approvals they have to the XML file  
    foreach (IUpdate update in updates)  
    {  
       ...  
       if (update.IsApproved == true)  
       {  
          //This revision (the latest revision) is approved; get the approvals and write them  
          WriteApprovals(xmlWriter, update.Id.RevisionNumber, updateApprovalDictionary[update.Id], targetGroupDictionary);  
       }  
       else if (update.HasStaleUpdateApprovals)   
       {  
          //This revision has older revisions that are approved; get their approvals and write them  
          foreach (IUpdate revision in update.GetRelatedUpdates(UpdateRelationship.AllRevisionsOfThisUpdate))  
          {  
             //If this revision is approved then write its approvals  
             if (revision.IsApproved)  
             {  
                WriteApprovals(xmlWriter, revision.Id.RevisionNumber, revision.GetUpdateApprovals(), targetGroupDictionary);  
             }  
          }  
       }  
    }  
    

Example

The following is the complete code listing for a console application that approves the specified update for optional install.

/*----------------------------------------------------------------------  
This file is part of the Microsoft Windows Server Update Services  
API Code Samples.  
  
DISCLAIMER OF WARRANTY: THIS CODE AND INFORMATION ARE PROVIDED "AS-IS."    
YOU BEAR THE RISK OF USING IT.  MICROSOFT GIVES NO EXPRESS WARRANTIES,   
GUARANTEES OR CONDITIONS.  YOU MAY HAVE ADDITIONAL CONSUMER RIGHTS   
UNDER YOUR LOCAL LAWS WHICH THIS AGREEMENT CANNOT CHANGE.    
TO THE EXTENT PERMITTED UNDER YOUR LOCAL LAWS, MICROSOFT EXCLUDES   
THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR   
PURPOSE AND NON-INFRINGEMENT.  
----------------------------------------------------------------------*/  
  
/*   
 * This application:  
 *  1. Connects to the local WSUS server  
 *  2. Gets a list of updates that are approved or that have an older revision that was approved  
 *  3. Gets all approvals for all updates  
 *  4. Loops through the updates, writing to an XML file all approvals  
*/  
  
using System;  
using Microsoft.UpdateServices.Administration;  
using System.Xml;  
using System.Collections.Generic;  
using System.Text;  
  
namespace WsusSamples  
{  
  class DetermineAllApprovedUpdates  
  {  
    static void Main(string[] args)  
    {  
      try  
      {  
        Console.WriteLine("Getting list of approved updates");  
  
        // Create the XML file that will hold our output  
        string fileName = String.Format("ApprovedUpdates {0}.xml", DateTime.Now.ToLongDateString());  
        XmlTextWriter xmlWriter = new XmlTextWriter(fileName, System.Text.Encoding.UTF8);  
        xmlWriter.Formatting = Formatting.Indented;  
        xmlWriter.Indentation = 4;  
        xmlWriter.WriteStartDocument(true);  
  
        // Connect to the local server  
        IUpdateServer updateServer = AdminProxy.GetUpdateServer();  
  
        // Get the list of updates that are approved or that have an older revision that is approved  
        UpdateScope updateScope = new UpdateScope();  
        updateScope.ApprovedStates = ApprovedStates.HasStaleUpdateApprovals | ApprovedStates.LatestRevisionApproved;  
        UpdateCollection updates = updateServer.GetUpdates(updateScope);  
  
        // Get all approvals for all updates at once  
        UpdateApprovalCollection allUpdateApprovals = updateServer.GetUpdateApprovals(updateScope);  
  
        // Create a dictionary so we can look up the list of approvals for any given update  
        Dictionary<UpdateRevisionId, UpdateApprovalCollection> updateApprovalDictionary = new Dictionary<UpdateRevisionId, UpdateApprovalCollection>();  
        foreach (IUpdateApproval updateApproval in allUpdateApprovals)  
        {  
          // If there is no entry in the dictionary for this update, then add one  
          if (!updateApprovalDictionary.ContainsKey(updateApproval.UpdateId))  
          {  
            updateApprovalDictionary.Add(updateApproval.UpdateId, new UpdateApprovalCollection());  
          }  
  
          // Add this approval to the corresponding update's list of approvals  
          updateApprovalDictionary[updateApproval.UpdateId].Add(updateApproval);  
        }  
  
        // Get all target groups  
        ComputerTargetGroupCollection allTargetGroups = new ComputerTargetGroupCollection();  
        allTargetGroups = updateServer.GetComputerTargetGroups();  
  
        // Create a dictionary for the target groups (GUID -> IComputerTargetGroup)  
        Dictionary<Guid, IComputerTargetGroup> targetGroupDictionary = new Dictionary<Guid, IComputerTargetGroup>();  
  
        // For each target group, add an entry in the dictionary pointing the target group GUID to the IComputerTargetGroup object  
        foreach (IComputerTargetGroup targetGroup in allTargetGroups)  
        {  
          targetGroupDictionary.Add(targetGroup.Id, targetGroup);  
        }  
  
        // <ApprovedUpdates>  
        xmlWriter.WriteStartElement("ApprovedUpdates");  
  
        //Loop through the updates, writing any approvals they have to the XML file  
        foreach (IUpdate update in updates)  
        {  
          //<Update Id="update ID" UpdateTitle="title" Classification="classification">  
          xmlWriter.WriteStartElement("Update");  
          xmlWriter.WriteAttributeString("Id", update.Id.UpdateId.ToString());  
          xmlWriter.WriteAttributeString("UpdateTitle", update.Title);  
          xmlWriter.WriteAttributeString("Classification", update.UpdateClassificationTitle);  
  
          //<Approvals>  
          xmlWriter.WriteStartElement("Approvals");  
  
          if (update.IsApproved == true)  
          {  
            //This revision (the latest revision) is approved; get the approvals and write them  
            WriteApprovals(xmlWriter, update.Id.RevisionNumber, updateApprovalDictionary[update.Id], targetGroupDictionary);  
          }  
          else if (update.HasStaleUpdateApprovals)   
          {  
            //This revision has older revisions that are approved; get their approvals and write them  
            foreach (IUpdate revision in update.GetRelatedUpdates(UpdateRelationship.AllRevisionsOfThisUpdate))  
            {  
              //If this revision is approved then write its approvals  
              if (revision.IsApproved)  
              {  
                WriteApprovals(xmlWriter, revision.Id.RevisionNumber, revision.GetUpdateApprovals(), targetGroupDictionary);  
              }  
            }  
          }  
  
          //</Approvals>  
          xmlWriter.WriteEndElement();  
  
          // </Update>  
          xmlWriter.WriteEndElement();  
        }  
  
        //</ApprovedUpdates>  
        xmlWriter.WriteEndElement();  
  
        //done writing the document  
        xmlWriter.Close();  
        xmlWriter = null;  
  
        Console.WriteLine("Complete. Results written to the {0} file in the current folder", fileName);  
      }  
      catch (Exception ex)  
      {  
        Console.WriteLine("An error occurred:\r\n" +  
                          "Error text: {0}\r\n" +  
                          "Stack trace: {1}\r\n",  
                          ex.Message, ex.StackTrace);  
      }  
    }  
  
    static void WriteApprovals(XmlTextWriter xmlWriter,   
                               int revisionNumber,   
                               UpdateApprovalCollection updateApprovals,   
                               Dictionary<Guid, IComputerTargetGroup> targetGroupDictionary)  
    {  
      //loop through the approvals for the update  
      foreach (IUpdateApproval approval in updateApprovals)  
      {  
          StringBuilder deadline = new StringBuilder();  
  
          //is there a deadline?  
          if (approval.Deadline < DateTime.MaxValue)   
          {  
            deadline.Append(approval.Deadline.ToLongDateString() + " " + approval.Deadline.ToShortTimeString());  
          }  
          else deadline.Append("None");  
  
          //<Approval RevisionNumber="update revision number" TargetGroup="target group name" Approval="approval action" Deadline="deadline" ApprovalDate="approval date">  
          xmlWriter.WriteStartElement("Approval");  
          xmlWriter.WriteAttributeString("RevisionNumber", revisionNumber.ToString());  
          xmlWriter.WriteAttributeString("TargetGroup", targetGroupDictionary[approval.ComputerTargetGroupId].Name);  
          xmlWriter.WriteAttributeString("Approval", approval.Action.ToString());  
          xmlWriter.WriteAttributeString("Deadline", deadline.ToString());  
          xmlWriter.WriteAttributeString("ApprovalDate", approval.CreationDate.ToString());  
  
          //</Approval>  
          xmlWriter.WriteEndElement();  
      }  
    }  
  }  
}