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
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.IUpdateServer updateServer = AdminProxy.GetUpdateServer();
Call the
IUpdateServer.GetComputerTargets
. There are two overloads to this method. One overload takes aComputerTargetScope
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 aComputerTargetCollection
collection object.ComputerTargetCollection computers = updateServer.GetComputerTargets();
Implement a
foreach
loop to iterate over theComputerTargetCollection
collection object returned from the previous step. Each computer will be represented by anIComputerTarget
object.foreach (IComputerTarget computer in computers) { }
For each
IComputerTarget
object, call itsGetUpdateInstallationInfoPerUpdate
method. This will return a collection (in the form of anUpdateInstallationInfoCollection
object) representing the status of all updates for the computer.UpdateInstallationInfoCollection installInfoCollection = computer.GetUpdateInstallationInfoPerUpdate();
Iterate over the
UpdateInstallationInfoCollection
collection, checking theIUpdateInstallationInfo.UpdateInstallationState
property. As the following code demonstrates, if the value is equal toUpdateInstallationState.Failed
,UpdateInstallationState.Downloaded
, orUpdateInstallationState.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();
}
}
}