Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Daylight Saving Time 2007: Update Windows Servers and Workstations

3.00/5 (1 vote)
8 Mar 2007CPOL1 min read 1   171  
Search through your Active Directory structure to find Windows OSs then apply new Daylight Saving Time rules without paying for the hotfix update or needing to reboot due to Group Policy.

Introduction

New Daylight Saving Time rules go into effect on March 11th, 2007 at 2 AM. Microsoft has provided some sample instructions for updating systems, but there are some serious drawbacks:

  • There is no support for Windows 2000 servers or workstations. Actually there is but you have to pay for "Extended Support" to get it.
  • The patch for Windows Server 2003 is "optional" so you have to select Custom Windows Updates - not Critical Updates which are the default. THIS IS NO LONGER THE CASE; MICROSOFT RECENTLY CHANGED THE PATCH TO CRITICAL.
  • The solution Microsoft proposes for updating multiple computers involves a Computer node Group Policy Object, which is fine but it does require a reboot.

Here is the Microsoft KB on the subject.

Solution

What I did was put together a console application that queries the AD structure by operating system, then uses SysInternal's PsExec tool to execute a registry update on multiple remote machines.

ENVIRONMENT: Visual Studio 2005, .NET 2.0, C# (you will need to add the reference for System.DirectoryServices)

Here is the code:

C#
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.DirectoryServices;
using System.Diagnostics;

namespace MyNamespace
{
  class Program
  {
  static void Main(string[] args)
  {
    SearchResultCollection results = null;

    StreamWriter sw = new StreamWriter("\\\\sharename\\DST$\\results.log", true);
    StreamWriter swerr = new StreamWriter("\\\\sharename\\DST$\\errors.log", true);

    try
    {
    // Bind to a container.
    string path = "<a href="ldap://DC=ABC,DC=DEF,DC=org/">ldap://DC=ABC,DC=DEF,DC=org/</a>";

    DirectoryEntry entry = new DirectoryEntry(path);

    // Create a DirectorySearcher object.
    DirectorySearcher mySearcher = new DirectorySearcher(entry);
    mySearcher.PropertiesToLoad.Add("name");
    mySearcher.PropertiesToLoad.Add("operatingsystem");
    // Set a filter for W2K servers. Can also be used for 2003
    // mySearcher.Filter = 
    // "(&(objectCategory=computer)(operatingSystem=Windows Server 2003))";
    // Testing a single machine would look like this
    // mySearcher.Filter = "(&(objectCategory=computer)
    // (operatingSystem=Windows 2000 Server)(name=SERVERNAME))";

    mySearcher.Filter = "(&(objectCategory=computer)
                    (operatingSystem=Windows 2000 Server))";

    results = mySearcher.FindAll();

    foreach (SearchResult searchResult in results)
      {
        ResultPropertyValueCollection valcol = searchResult.Properties["name"];
        {
        // Write the value contained in index position 0 in the name attribute.

        string pc = valcol[0].ToString();

        // User needs to be a Domain Admin or a local admin on the remote computer
        string psargs = "\\\\" + pc + " -u DOMAIN\\username -p password 
                    <a>\\\\sharename\\DST$\\DSTUpdate.bat";

</a>        Process proc = new Process();
        proc.StartInfo.FileName = "C:\\sharename\\DST\\psexec.exe";
        proc.StartInfo.Arguments = psargs;
        proc.StartInfo.UseShellExecute = false;
        proc.StartInfo.RedirectStandardOutput = true;
        proc.Start();
        proc.WaitForExit();

        string output = proc.StandardOutput.ReadToEnd();

        // This is done this way because SysInternal's PsExec 
        // does not handle StandardOutput and StandardError
        // when running on a remote machine 
        sw.WriteLine("Computer: " + pc + 
                 " Result(blank = no update): " + output + "\r\n");
        sw.Flush();

        proc.Close();

        }
      }
    }

    catch (Exception ex)
    {
      swerr.WriteLine("Error: " + ex.Message);
    }

    finally
    {
      // To prevent memory leaks, always call 
      // SearchResultCollection.Dispose() manually.
      if (null != results)
      {
      results.Dispose();
      results = null;
      }

    sw.Close();
    swerr.Close();
    }

  }//end main
  }//end class
}// end namespace

The file DTSUpdate.bat has just three lines:

@echo off
regedit /s \\sharename\DST$\DSTRegistry.reg
cscript \\sharename\DST$\DSTInfo.vbs

Both of these files (DSTRegistry.reg and DSTInfo.vbs) come directly from Microsoft's Web site.

Conclusion

It seems like the DST issue is sneaking up on a lot of companies. It's probably not going to be that big of a deal, but it is best to be prepared. I thought there would already be something similar posted, but I found nothing... so I am putting it out for general use. If someone finds a way to pipe the PsExec output to a file, I would really like to know how that is done. Thanks.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)