How to Get Update Details

 

Applies To: Windows Server Update Services

Use the following procedure to query the local Microsoft Windows Server Update Services (WSUS) server for detailed information for each of its updates. The example that follows is a Microsoft Visual C# command-line application that obtains detailed update information and writes that data to an XML file.

To get update details

  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. Instantiate an IUpdateServer object by using the static AdminProxy.GetUpdateServer method.

    // Connect to the local WSUS server  
    IUpdateServer server = AdminProxy.GetUpdateServer();  
    
  4. Get the list of updates from the WSUS server object by calling the IUpdateServer.GetUpdates method. The following code snippet illustrates one technique for obtaining a collection comprising all of the server’s updates. Note the use of the ApprovedStates.Any enum value passed as the first parameter, which results in all updates being added to the collection regardless of their approved state (LatestRevisionApproved, HasStaleUpdateApprovals, NotApproved, and Declined). The second and third parameters (DateTime.MinValue and DateTime.MaxValue, respectively) represent the "from" and "to" arrival dates. Therefore, in this situation the code is obtaining all updates regardless of when the update arrived. Finally, the last two parameters (updateCategories and updateClassifications, respectively) enable the filtering of the updates returned. As mentioned, this snippet obtains all of the updates, so these values are set to null.

    // Get all updates from the WSUS server  
    UpdateCollection updateCollection = updateServer.GetUpdates(ApprovedStates.Any, DateTime.MinValue, DateTime.MaxValue, null, null);  
    
  5. There are several IUpdate members that return System.Collections.Specialized.StringCollection objects. These include the properties listed in the following table. Once you access these properties, a foreach loop can be utilized to iterate over the returned collection of strings to process the desired type of information.

    IUpdate Member Description
    AdditionalInformationUrls Gets a collection of URLs provided by the publisher of the update that provide additional information about the update.
    KnowledgebaseArticles Gets the Knowledge Base article numbers that describe an issue related to or fixed by this update.
    SecurityBulletins Gets Security Bulletin numbers. The bulletins describe security issues and changes that are related to the update.
    // Get any MSRC security bulletins  
    System.Collections.Specialized.StringCollection securityBulletins = update.SecurityBulletins;  
    foreach (string securityBulletin in securityBulletins)  
    {  
      Console.WriteLine("MSRC Number: {0}", securityBulletin);  
    }  
    
    // Get any KB articles  
    System.Collections.Specialized.StringCollection kbArticles = update.KnowledgebaseArticles;  
    foreach (string kbArticle in kbArticles)  
    {  
      Console.WriteLine("KB Article Number: {0}", kbArticle);  
    }  
    
    // Get any "additional information URLs"  
    System.Collections.Specialized.StringCollection additionalInformationUrls = update.AdditionalInformationUrls;  
    foreach (string additionalInformationUrl in additionalInformationUrls)  
    {  
      Console.WriteLine("Additional Information URL: {0}", additionalInformationUrl);  
    }  
    
  6. Another key IUpdate member that is utilized for obtaining update information is the IUpdate.GetRelatedUpdates method. The IUpdate.GetRelatedUpdates method takes as its only parameter an UpdateRelationship enum value that describes the relationship between updates. For example, calling IUpdateGetRelatedUpdates and passing a value of UpdateRelationship.UpdatesBundledByThisUpdate will result in an UpdateCollection containing child updates that are bundled in this update. A foreach loop can then be utilized to iterate over the returned collection. The following code snippet illustrates how to both call the IUpdate.GetRelatedUpdates method as well as how to process the returned UpdateCollection collection.

    // If there are bundled updates, get their details too  
    UpdateCollection bundledUpdates = update.GetRelatedUpdates(UpdateRelationship.UpdatesBundledByThisUpdate);  
    if (bundledUpdates.Count > 0)  
    {  
      foreach (IUpdate bundledUpdate in bundledUpdates)  
      {  
        Console.WriteLine("UpdateID: {0}", bundledUpdate.Id.UpdateId.ToString().ToUpper());  
        Console.WriteLine("Title: {0}", bundledUpdate.Title);  
        Console.WriteLine("Classification: {0}", bundledUpdate.UpdateClassificationTitle);  
      }  
    }  
    

Example

The following is the complete code listing for a Visual C# console application that creates an XML file with a list of all updates and many of the key information details about each update.

//-----------------------------------------------------------------------  
//  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.  
//-----------------------------------------------------------------------  
using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using Microsoft.UpdateServices.Administration;  
using System.Xml;  
  
namespace WsusSamples  
{  
  class GetUpdateDetails  
  {  
    static void Main(string[] args)  
    {  
      GetUpdateDetails program = new GetUpdateDetails();  
      program.ProcessUpdates();  
    }  
  
    public void ProcessUpdates()  
    {    
      // Connect to the local WSUS server  
      IUpdateServer updateServer = AdminProxy.GetUpdateServer();  
      XmlTextWriter xml = new XmlTextWriter(Environment.CurrentDirectory + @"\UpdateDetails.xml", System.Text.Encoding.UTF8);  
  
      try  
      {  
        Console.WriteLine("Getting list of updates...");  
  
        // Open the XML file  
        xml.Formatting = Formatting.Indented;  
        xml.Indentation = 4;  
        xml.WriteStartDocument(true);  
        // <Updates>  
        xml.WriteStartElement("Updates");  
  
        // Get the list of updates  
        UpdateCollection updateCollection = updateServer.GetUpdates(ApprovedStates.Any, DateTime.MinValue, DateTime.MaxValue, null, null);  
  
        foreach (IUpdate update in updateCollection)  
        {  
          // Loop through the updates and get interesting information   
          ProcessUpdateDetails(xml, update);  
        }  
  
        // </Updates>  
        xml.WriteEndElement();  
        xml.Close();  
  
        Console.WriteLine("Done. Results are written to the UpdateDetails.xml file in the current folder");  
      }  
      catch(Exception ex)  
      {  
        Console.WriteLine("An error occurred: {0}\r\n" +  
                          "Stack trace: {1}",  
                          ex.Message,  
                          ex.StackTrace);  
        if (null != xml) xml.Close();  
      }  
    } // ProcessUpdates  
  
    public void ProcessUpdateDetails(XmlTextWriter xml, IUpdate update)  
    {  
      // <Update>  
      xml.WriteStartElement("Update");  
  
      xml.WriteAttributeString("UpdateID", update.Id.UpdateId.ToString().ToUpper());  
      xml.WriteAttributeString("Title", update.Title);  
      xml.WriteAttributeString("Classification", update.UpdateClassificationTitle);  
      xml.WriteAttributeString("LegacyName", update.LegacyName);  
      xml.WriteAttributeString("Description", update.Description);  
      xml.WriteAttributeString("SyncDate", update.ArrivalDate.ToLocalTime().ToShortDateString() + " " + update.ArrivalDate.ToLocalTime().ToShortTimeString());  
      xml.WriteAttributeString("ReleaseDate", update.CreationDate.ToLocalTime().ToShortDateString() + " " + update.CreationDate.ToLocalTime().ToShortTimeString());  
      xml.WriteAttributeString("MsrcSeverity", update.MsrcSeverity.ToString());  
  
      // <SecurityBulletins>  
      xml.WriteStartElement("SecurityBulletins");  
      // Get any MSRC security bulletins  
      System.Collections.Specialized.StringCollection securityBulletins = update.SecurityBulletins;  
      // If there are any, list them  
      foreach (string securityBulletin in securityBulletins)  
      {  
        // <SecurityBulletin>  
        xml.WriteStartElement("SecurityBulletin");  
        xml.WriteAttributeString("Number", securityBulletin);  
        // </SecurityBulletin>  
        xml.WriteEndElement();  
      }  
      // </SecurityBulletins>  
      xml.WriteEndElement();  
  
      // <KBArticles>  
      xml.WriteStartElement("KBArticles");  
      // Get any KB articles  
      System.Collections.Specialized.StringCollection kbArticles = update.KnowledgebaseArticles;  
      // if there are any, list them  
      foreach (string kbArticle in kbArticles)  
      {  
        // <KBArticle>  
        xml.WriteStartElement("KBArticle");  
        xml.WriteAttributeString("ArticleNumber", kbArticle);  
        // </KBArticle>  
        xml.WriteEndElement();  
      }  
      // </KBArticles>  
      xml.WriteEndElement();  
  
      // <AdditionalInformationUrls>  
      xml.WriteStartElement("AdditionalInformationUrls");  
      System.Collections.Specialized.StringCollection additionalInformationUrls = update.AdditionalInformationUrls;  
      foreach (string additionalInformationUrl in additionalInformationUrls)  
      {  
        // <AdditionalInformationUrl>  
        xml.WriteStartElement("AdditionalInformationUrl");  
        xml.WriteAttributeString("URL", additionalInformationUrl);  
        // </AdditionalInformationUrl>  
        xml.WriteEndElement();  
      }  
      // </AdditionalInformationUrls>  
      xml.WriteEndElement();  
  
      // If there are bundled updates, get their details too  
      UpdateCollection bundledUpdates = update.GetRelatedUpdates(UpdateRelationship.UpdatesBundledByThisUpdate);  
      if (bundledUpdates.Count > 0)  
      {  
        // <UpdatesIncludedByThisUpdate>  
        xml.WriteStartElement("UpdatesIncludedByThisUpdate");  
        foreach (IUpdate bundledUpdate in bundledUpdates)  
        {  
          xml.WriteStartElement("Update");  
          xml.WriteAttributeString("UpdateID", bundledUpdate.Id.UpdateId.ToString().ToUpper());  
          xml.WriteAttributeString("Title", bundledUpdate.Title);  
          xml.WriteAttributeString("Classification", bundledUpdate.UpdateClassificationTitle);  
          xml.WriteEndElement();  
        }  
        xml.WriteEndElement();  
        // </UpdatesIncludedByThisUpdate>  
      }  
  
      // If there are bundling updates, get their details too  
      UpdateCollection bundlingUpdates = update.GetRelatedUpdates(UpdateRelationship.UpdatesThatBundleThisUpdate);  
      if (bundlingUpdates.Count > 0)  
      {  
        // <UpdatesThatIncludThisUpdate>  
        xml.WriteStartElement("UpdatesThatIncludThisUpdate");  
        foreach (IUpdate bundlingUpdate in bundlingUpdates)  
        {  
          xml.WriteStartElement("Update");  
          xml.WriteAttributeString("UpdateID", bundlingUpdate.Id.UpdateId.ToString().ToUpper());  
          xml.WriteAttributeString("Title", bundlingUpdate.Title);  
          xml.WriteAttributeString("Classification", bundlingUpdate.UpdateClassificationTitle);  
          xml.WriteEndElement();  
        }  
        xml.WriteEndElement();  
        // </UpdatesThatIncludThisUpdate>  
      }  
  
      // If there are superseded updates, get their details too  
      UpdateCollection supersededUpdates = update.GetRelatedUpdates(UpdateRelationship.UpdatesSupersededByThisUpdate);  
      if (supersededUpdates.Count > 0)  
      {  
        // <UpdatesSupersededByThisUpdate>  
        xml.WriteStartElement("UpdatesSupersededByThisUpdate");  
        foreach (IUpdate supercededUpdate in supersededUpdates)  
        {  
          xml.WriteStartElement("Update");  
          xml.WriteAttributeString("UpdateID", supercededUpdate.Id.UpdateId.ToString().ToUpper());  
          xml.WriteAttributeString("Title", supercededUpdate.Title);  
          xml.WriteAttributeString("Classification", supercededUpdate.UpdateClassificationTitle);  
          xml.WriteEndElement();  
        }  
        xml.WriteEndElement();  
        // </UpdatesSupersededByThisUpdate>  
      }  
  
      // If there are superseding updates, get their details too  
      UpdateCollection supersedingUpdates = update.GetRelatedUpdates(UpdateRelationship.UpdatesThatSupersedeThisUpdate);  
      if (supersedingUpdates.Count > 0)  
      {  
          // <UpdatesThatSupersedeThisUpdate>  
          xml.WriteStartElement("UpdatesThatSupersedeThisUpdate");  
          foreach (IUpdate supercedingUpdate in supersedingUpdates)  
          {  
            xml.WriteStartElement("Update");  
            xml.WriteAttributeString("UpdateID", supercedingUpdate.Id.UpdateId.ToString().ToUpper());  
            xml.WriteAttributeString("Title", supercedingUpdate.Title);  
            xml.WriteAttributeString("Classification", supercedingUpdate.UpdateClassificationTitle);  
            xml.WriteEndElement();  
          }  
          xml.WriteEndElement();  
          // </UpdatesThatSupersedeThisUpdate>  
      }  
  
      // </Update>  
      xml.WriteEndElement();  
    } // ProcessUpdateDetails  
  } // class  
} // namespace