Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Move Computers in Active Directory Using a SQL Server Datasource

4.20/5 (3 votes)
3 Aug 2006CPOL2 min read 1   219  
Move multiple computers from one OU to another using a SQL Server table as a datasource.

Introduction

I recently began a project which involved installing a .msi package on approximately 450 computers. The organization previously implemented projects like this by visiting each desktop, but I suggested AD group policy instead. For a number of reasons, I needed to implement the GPO on the computer node, but there were two main problems: I had a list of user accounts but not computers, and I needed to move the PCs from the Computers OU to the new OU that was linked with my software distribution GPO.

Getting Started

The first step was to start capturing which PCs were tied to my list of known users. I created a *simple* logon script that captured the user name and the computer name, and wrote that to a log file:

@echo off
REM collect user name and computer name
echo %username%,%computername% >> \\servername\sharename\userpclog.txt

After about a month, I had 3500 entries. I imported the file into SQL Server, and then created a View to give me my PC-to-user list. There were 450 computers for 398 users (some users such as interns, temp staff, etc. use any available PC). I did not have info on 28 users but that I could deal with.

Move Active Directory Objects

The basic process for moving the PC from one OU to another is to create a connection to the database, get the list of PC names, then loop through the dataset and create a new DirectoryEntry instance with the current record as the Common Name (CN) in the LDAP path.

First, create a new console application in Visual Studio 2005. You will need to add references to System.DirectoryServices and System.Data. By default, you will have a file called Program.cs. Replace the contents of that file with the code below, and replace the connection to the database, command string, and LDAP paths as needed.

C#
using System;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.DirectoryServices;

class ChangeOU
{
    static void Main(string[] args)
    {
        //Set the move-to path
        string m_movetopath = "LDAP://OU=newtestou," + 
                              "DC=northamerica,DC=fabrikam,DC=com";

        DirectoryEntry DeMoveTo = new DirectoryEntry(m_movetopath);
        
        //Connect to database and get list of PC names
        string ConnectionString = "server=myservername;
        Trusted_Connection=yes; database=Users";
        string CommandString = "SELECT computername FROM vwUserpc";
        SqlDataAdapter sda = new SqlDataAdapter(CommandString, 
                                                ConnectionString);
        DataSet ds = new DataSet();
        sda.Fill(ds);
        DataTable dt = ds.Tables[0];

        foreach (DataRow dr in dt.Rows)
        {
            string pc = (string)dr["computername"].ToString();
            pc.Trim();

            //This is a fixed value.
            string MovePath = "LDAP://CN=" + pc + 
                              ",OU=testou,DC=northamerica," + 
                              "DC=fabrikam,DC=com";

            //For each PC name move it to the new OU
            try
            {
                DirectoryEntry DeMoveFrom = new DirectoryEntry(MovePath);
                DeMoveFrom.MoveTo(DeMoveTo);
            }
            catch (Exception ex)
            {
                Console.Write(ex.Message);
                Console.Write(pc);
            }
        }

        Console.Write("\r\n");
        Console.WriteLine("Completed.");

    }//end Main
} //end class

One thing that is fairly important to note is that I am a domain admin, so creating the DirectoryEntry instances works "without" security; otherwise, you will need to add the security parameters.

Conclusions

The code may seem pretty straightforward, yet I could not find any examples like this. So, I am writing it up for future reference. I hope you find it useful.

Note: Part of this project also involved scripting an ODBC connection in the registry. These scripts are included in the source files.

License

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