How to Identify Computers Needing Reboot
Applies To: Windows Server Update Services
Use the following procedure to identify computers needing reboot after approved updates have been installed. The procedure demonstrates the WSUS API calls required to perform this task. The example following the procedure is the source code for a command-line application that generates an HTML page listing all computers needing to be rebooted to complete the installation of the updates.
To identify computers needing reboot
Add the
Microsoft.UpdateServices.Administration
assembly to your project.Insert a
using
statement for theMicrosoft.UpdateServices.Administration
namespace.using Microsoft.UpdateServices.Administration;
Connect to the local WSUS server by calling the AdminProxy.GetUpdateServer method.
IUpdateServer updateServer = AdminProxy.GetUpdateServer();
Filter out the computers that do not have the PendingReboot status. To create the filter, or scope, instantiate a
ComputerTargetScope
object and set itsIncludedInstallationStates
to the desired value, which isInstalledPendingReboot
in this case. After you’ve set up theComputerTargetScope
object, pass it to theIUpdateServer.GetComputerTargets
method, which will return aComputerTargetCollection
object containing only the desired computers.ComputerTargetScope computerScope = new ComputerTargetScope(); computerScope.IncludedInstallationStates = UpdateInstallationStates.InstalledPendingReboot; ComputerTargetCollection computers = updateServer.GetComputerTargets(computerScope);
At this point, you have a collection of computers that need to be rebooted, but you don’t know for which updates. In the same way that you obtained a collection containing only the computers requiring a reboot, the following code will perform the following operations:
Instantiate an
UpdateScope
object, setting its scope, or filter, to only those updates that require a reboot to complete their installation (UpdateInstallationStates.InstalledPendingReboot
).For each update requiring a reboot, add that update to a collection (via the
UpdateCollection.Add
method) for later processing.At this point, you have a collection,
neededUpdates
, of all updated computers that require a reboot. Simply iterate over that collection, performing whatever tasks you want to perform with this data.
foreach (IComputerTarget computer in computers) { // 1) Get a collection of the installed updates that are pending a reboot. UpdateScope updateScope = new UpdateScope(); updateScope.IncludedInstallationStates = UpdateInstallationStates.InstalledPendingReboot; UpdateInstallationInfoCollection installInfoCollection = computer.GetUpdateInstallationInfoPerUpdate(updateScope); // 2) When you have the collection of installed updates requiring a reboot, iterate // over that collection, adding each update to the needingUpdates collection. UpdateCollection neededUpdates = new UpdateCollection(); neededUpdates.Clear(); foreach (IUpdateInstallationInfo installInfo in installInfoCollection) { neededUpdates.Add(installInfo.GetUpdate()); } // 3) Iterate over the neededUpdates collection, performing the desired action. foreach (IUpdate update in neededUpdates) { // Perform desired action here for each update. } }
Example
The following is the complete code listing for a console application that writes to an HTML file the computers that have installed updates but that still require a reboot to be fully patched.
/*----------------------------------------------------------------------
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;
namespace WsusSamples
{
class IdentifyComputersNeedingReboot
{
static void Main(string[] args)
{
try
{
StringBuilder rebootRequiredComputers = new StringBuilder();
// Connect to the local WSUS server by calling the AdminProxy.GetUpdateServer method.
IUpdateServer iUpdateServer = AdminProxy.GetUpdateServer();
// Define the scope (ComputerTargetScope) as only those computers requiring
ComputerTargetScope computerScope = new ComputerTargetScope();
computerScope.IncludedInstallationStates = UpdateInstallationStates.InstalledPendingReboot;
ComputerTargetCollection computers = iUpdateServer.GetComputerTargets(computerScope);
Console.WriteLine("Getting the status of computers...\r\n");
// Iterate over the computers needing to be rebooted collection (computers)
foreach (IComputerTarget computer in computers)
{
Console.WriteLine("Getting status for {0}...", computer.FullDomainName);
// Instantiate an UpdateScope object, setting its scope, or filter, to only those updates
// that require a reboot in order to complete their installation.
UpdateScope updateScope = new UpdateScope();
updateScope.IncludedInstallationStates = UpdateInstallationStates.InstalledPendingReboot;
UpdateInstallationInfoCollection installInfoCollection = computer.GetUpdateInstallationInfoPerUpdate(updateScope);
// Clear the collection used to hold the needed updates.
UpdateCollection neededUpdates = new UpdateCollection();
neededUpdates.Clear();
// Iterate over the current computer's installed updates that require a reboot, adding them
// to a collection (neededUpdate) for later processing.
foreach (IUpdateInstallationInfo installInfo in installInfoCollection)
{
// Add the update to the collection of needed updates
neededUpdates.Add(installInfo.GetUpdate());
}
// Write the computer element to the HTML file.
rebootRequiredComputers.AppendFormat("<tr><td>{0}</td><td >{1}</td><td>{2}</td></tr>",
computer.FullDomainName,
neededUpdates.Count.ToString(),
computer.LastReportedStatusTime);
rebootRequiredComputers.AppendFormat("<tr><td>");
rebootRequiredComputers.AppendFormat("<table border='1' width='98%' class='MainTable' " +
"style='border-collapse: collapse; border-width: 1px'> " +
"<tr><td class='SectionHead' nowrap align='left' valign='top'> " +
"Updates needing reboot</td></tr>");
foreach (IUpdate update in neededUpdates)
{
rebootRequiredComputers.AppendFormat("<tr><td>{0}</td></tr>", update.Title);
}
rebootRequiredComputers.AppendFormat("</tr></td></table>");
}
// create the HTML body
StringBuilder htmlBody = new StringBuilder();
htmlBody.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><body>");
htmlBody.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'>" +
"computers Requiring Reboot Report</td></tr><tr><td style='border-bottom-style: none; " +
"border-bottom-width: medium'>There are {0} out of {1} computers that require a reboot as " +
"of {2}.<br><br></td></tr>",
computers.Count,
iUpdateServer.GetComputerTargetCount(),
DateTime.Now.ToString());
// Fill in the details for the out of compliance computers.
htmlBody.AppendFormat("<tr><td class='SectionHead' nowrap align='left' valign='top'>computers requiring a reboot: " +
"{0}</td></tr><tr><td>",
computers.Count.ToString());
htmlBody.Append("<table border='0' width='90%' id='NeedingUpdates' class='SubTable' style='border-collapse: collapse'>");
htmlBody.Append("<tr><td><b>computer Name</b></td><td><b>Needed Updates</b></td><td ><b>Last Reported</b></td></tr>");
htmlBody.Append(rebootRequiredComputers);
htmlBody.Append("</table>");
htmlBody.Append("</table></body></html>");
// Write the results to the file.
Console.WriteLine("Creating HTML file...");
String filename = DateTime.Now.ToLongDateString() + ".html";
System.IO.StreamWriter file =
new System.IO.StreamWriter(Environment.CurrentDirectory +
"\\Computers Requiring Reboot Report - " +
filename);
Console.WriteLine("Writing results to HTML file...");
file.Write(htmlBody.ToString());
Console.WriteLine("Saving HTML file...");
file.Close();
Console.WriteLine("Complete. Results are saved to the {0}\\computers Requiring Reboot Report - {1} file",
Environment.CurrentDirectory,
filename);
} // try
catch (Exception ex)
{
Console.WriteLine("An error occurred: {0}", ex.ToString());
}
} // main
}
}