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

  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. Connect to the local WSUS server by calling the AdminProxy.GetUpdateServer method.

    IUpdateServer updateServer = AdminProxy.GetUpdateServer();  
    
  4. Filter out the computers that do not have the PendingReboot status. To create the filter, or scope, instantiate a ComputerTargetScope object and set its IncludedInstallationStates to the desired value, which is InstalledPendingReboot in this case. After you’ve set up the ComputerTargetScope object, pass it to the IUpdateServer.GetComputerTargets method, which will return a ComputerTargetCollection object containing only the desired computers.

    ComputerTargetScope computerScope = new ComputerTargetScope();  
    computerScope.IncludedInstallationStates = UpdateInstallationStates.InstalledPendingReboot;  
    ComputerTargetCollection computers = updateServer.GetComputerTargets(computerScope);  
    
  5. 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:

    1. Instantiate an UpdateScope object, setting its scope, or filter, to only those updates that require a reboot to complete their installation (UpdateInstallationStates.InstalledPendingReboot).

    2. For each update requiring a reboot, add that update to a collection (via the UpdateCollection.Add method) for later processing.

    3. 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  
  }  
}