How to Determine Out-Of-Compliance Computers

 

Applies To: Windows Server Update Services

Use the following procedure to determine which computers do not have all of the approved updates installed. The example that follows the procedure is a complete Microsoft Visual C# command-line application that performs these steps, writing an HTML file with the results for reporting and maintenance purposes.

To determine non-compliant computers

  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.

    IUpdateServer updateServer = AdminProxy.GetUpdateServer();  
    
  4. Call the IUpdateServer.GetComputerTargets. There are two overloads to this method. One overload takes a ComputerTargetScope object, which enables you to filter which computers are returned. In this case, the code is using the parameterless overload, which returns all computers in a ComputerTargetCollection collection object.

    ComputerTargetCollection computers = updateServer.GetComputerTargets();  
    
  5. Implement a foreach loop to iterate over the ComputerTargetCollection collection object returned from the previous step. Each computer will be represented by an IComputerTarget object.

    foreach (IComputerTarget computer in computers)  
    {  
    }  
    
  6. For each IComputerTarget object, call its GetUpdateInstallationInfoPerUpdate method. This will return a collection (in the form of an UpdateInstallationInfoCollection object) representing the status of all updates for the computer.

    UpdateInstallationInfoCollection installInfoCollection = computer.GetUpdateInstallationInfoPerUpdate();  
    
  7. Iterate over the UpdateInstallationInfoCollection collection, checking the IUpdateInstallationInfo.UpdateInstallationState property. As the following code demonstrates, if the value is equal to UpdateInstallationState.Failed, UpdateInstallationState.Downloaded, or UpdateInstallationState.NotInstalled, the update has not been applied.

    foreach (IUpdateInstallationInfo installInfo in installInfoCollection)  
    {  
      // Is this update in a needed or failed state?  
      if ((installInfo.UpdateInstallationState == UpdateInstallationState.Failed)   
      ||  (installInfo.UpdateInstallationState == UpdateInstallationState.Downloaded)   
      ||  (installInfo.UpdateInstallationState == UpdateInstallationState.NotInstalled))  
      {  
        // This computer is out of compliance!  
      }  
    }  
    

Example

The following is the complete code listing for a Visual C# console application that determines the computers that do not have all of the approved updates installed. The results of this scan are then written to an HTML file for reporting and maintenance purposes.

/*----------------------------------------------------------------------  
This file is part of the Microsoft Windows Server Update Services  
API Code Samples.  
  
Copyright (C) Microsoft Corporation.  All rights reserved.  
  
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 System.IO;  
using Microsoft.UpdateServices.Administration;  
  
namespace WsusSamples  
{  
  class DetermineOutOfComplianceComputers  
  {  
    static void Main(string[] args)  
    {  
      try  
      {  
        // Connect to the local server  
        IUpdateServer updateServer = AdminProxy.GetUpdateServer();  
  
        // Get the computers  
        ComputerTargetCollection computers = updateServer.GetComputerTargets();  
  
        // Update user  
        Console.WriteLine("Getting computer status...");  
  
        // Initialize counters  
        int outOfComplianceCount = 0;  
        int inComplianceCount = 0;  
        StringBuilder inComplianceComputers = new StringBuilder();  
        StringBuilder outOfComplianceComputers = new StringBuilder();  
  
        // Loop through all computers and get the status of updates  
        foreach (IComputerTarget computer in computers)  
        {  
          // Get the status of all the updates on the computer  
          UpdateInstallationInfoCollection installInfoCollection = computer.GetUpdateInstallationInfoPerUpdate();  
  
          // Clear the counter used to track the number of needed updates that have not been fully installed  
          int needUpdates = 0;  
  
          foreach (IUpdateInstallationInfo installInfo in installInfoCollection)  
          {  
            // Is this update in a needed or failed state?  
            if ((installInfo.UpdateInstallationState == UpdateInstallationState.Failed)   
            ||  (installInfo.UpdateInstallationState == UpdateInstallationState.Downloaded)   
            ||  (installInfo.UpdateInstallationState == UpdateInstallationState.NotInstalled))  
            {  
              // If it is, set the flag to true to indicate that this computer is out of compliance  
              needUpdates++;  
            }  
          }  
  
          // Write a line for the computer  
          if (needUpdates > 0)  
          {  
            outOfComplianceComputers.AppendFormat("<tr><td >{0}</td><td >{1}</td><td>{2}</td></tr>",   
                                                  computer.FullDomainName,   
                                                  needUpdates.ToString(),   
                                                  computer.LastSyncTime);  
            outOfComplianceCount++;  
          }  
          else  
          {  
            inComplianceComputers.AppendFormat("<tr><td>{0}</td><td >{1}</td><td>{2}</td></tr>",   
                                               computer.FullDomainName,   
                                               needUpdates.ToString(),   
                                               computer.LastSyncTime);  
            inComplianceCount++;  
          }  
        }  
  
        string fileName = WriteSummary(computers.Count,   
                                       outOfComplianceCount, inComplianceCount,  
                                       outOfComplianceComputers, inComplianceComputers);  
  
        Console.WriteLine("Results have been saved to {0}", fileName);  
      }  
      catch (Exception ex)  
      {  
        Console.WriteLine("An error occurred: {0}", ex.Message);  
      }  
    }  
  
    static string WriteSummary(int totalComputers,   
                             int outOfComplianceCount, int inComplianceCount, StringBuilder   
                             outOfComplianceComputers, StringBuilder inComplianceComputers)  
    {  
      StringBuilder fileName = new StringBuilder();  
      fileName.AppendFormat(@"{0}\Compliance report - {1}.html",  
                            Environment.CurrentDirectory,  
                            DateTime.Now.ToLongDateString());  
  
      // Create the HTML html  
      StringBuilder html = new StringBuilder();  
      html.Append("<html><head><meta http-equiv='Content-Language' content='en-us'>" +  
                  "<meta http-equiv='Content-Type' content='text/html; charset=windows-1252'>" +  
                  "<style><!--.SectionHead { font-family: Tahoma; font-size: 8pt; color: #FFFFFF; " +  
                  "font-weight: bold; margin: 4 5; background-color: #ABA483 }.SubTable    " +  
                  "{ font-family: Tahoma; font-size: 8pt; margin-left: 10; margin-right: 10 }.MainTable   " +  
                  "{ font-family: Tahoma; font-size: 8pt; border: 2px solid #ABA483 }--></style></head><html>");  
      html.AppendFormat("<table border='1' width='98%' id='MainTable' class='MainTable' " +  
                        "style='border-collapse: collapse; border-width: 1px'> <tr><td class='SectionHead' " +  
                        "nowrap align='left' valign='top'>Computer Compliance Report</td></tr><tr>" +  
                        "<td style='border-bottom-style: none; border-bottom-width: medium'>" +  
                        "There are {0} out of {1} computers that need updates as of {2}.<br><br></td></tr>",   
                        outOfComplianceCount, totalComputers, DateTime.Now.ToString());  
  
      // Fill in the details for the out-of-compliance computers  
      html.AppendFormat("<tr><td class='SectionHead' nowrap align='left' valign='top'>computers out of compliance: " +  
                        "{0}</td></tr><tr><td>",   
                        outOfComplianceCount.ToString());  
      html.Append("<table border='0' width='90%' id='NeedingUpdates' class='SubTable' style='border-collapse: collapse'>");  
      html.AppendFormat("<tr><td><b>Computer Name</b></td><td><b>Needed Updates</b></td><td ><b>Last Contact</b></td></tr>");  
      html.Append(outOfComplianceComputers);  
      html.Append("</table>");  
  
      // Fill in the details for the in-compliance computers  
      html.AppendFormat("<tr><td class='SectionHead' nowrap align='left' valign='top'>computers in compliance: " +   
                        "{0}</td></tr><tr><td>",   
                        inComplianceCount.ToString());  
      html.Append("<table border='0' width='90%' id='NotNeedingUpdates' class='SubTable' style='border-collapse: collapse'>");  
      html.AppendFormat("<tr><td ><b>Computer Name</b></td><td ><b>Needed Updates</b></td><td ><b>Last Contact</b></td></tr>");  
      html.Append(inComplianceComputers);  
      html.Append("</table>");  
      html.Append("</table></html></html>");  
  
      // Write the results to the file.   
      Console.WriteLine("Creating HTML file...");  
      StreamWriter file = new StreamWriter(fileName.ToString());  
  
      Console.WriteLine("Writing results to HTML file...");  
      file.Write(html.ToString());  
      Console.WriteLine("Saving HTML file...");  
      file.Close();  
  
      return fileName.ToString();  
    }  
  }  
}