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
Add the
Microsoft.UpdateServices.Administration
assembly to your project.Insert a
using
statement for theMicrosoft.UpdateServices.Administration
namespace.using Microsoft.UpdateServices.Administration;
Instantiate an
IUpdateServer
object by using the staticAdminProxy.GetUpdateServer
method.// Connect to the local WSUS server IUpdateServer server = AdminProxy.GetUpdateServer();
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 theApprovedStates.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
, andDeclined
). The second and third parameters (DateTime.MinValue
andDateTime.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
andupdateClassifications
, 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);
There are several
IUpdate
members that returnSystem.Collections.Specialized.StringCollection
objects. These include the properties listed in the following table. Once you access these properties, aforeach
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); }
Another key
IUpdate
member that is utilized for obtaining update information is theIUpdate.GetRelatedUpdates
method. TheIUpdate.GetRelatedUpdates
method takes as its only parameter anUpdateRelationship
enum value that describes the relationship between updates. For example, callingIUpdateGetRelatedUpdates
and passing a value ofUpdateRelationship.UpdatesBundledByThisUpdate
will result in anUpdateCollection
containing child updates that are bundled in this update. Aforeach
loop can then be utilized to iterate over the returned collection. The following code snippet illustrates how to both call theIUpdate.GetRelatedUpdates
method as well as how to process the returnedUpdateCollection
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