使用SQL Server数据源在Active Directory中移动计算机
使用 SQL Server 表作为数据源,将多台计算机从一个 OU 移动到另一个 OU。
引言
我最近开始了一个项目,涉及在大约 450 台计算机上安装一个 .msi 包。 该组织以前通过访问每台桌面计算机来实施此类项目,但我建议使用 AD 组策略。 由于多种原因,我需要在计算机节点上实施 GPO,但存在两个主要问题:我有一份用户帐户列表,但没有计算机列表,并且我需要将 PC 从 Computers OU 移动到与我的软件分发 GPO 关联的新 OU。
入门
第一步是开始捕获哪些 PC 与我的已知用户列表相关联。 我创建了一个*简单*的登录脚本,用于捕获用户名和计算机名,并将这些信息写入日志文件
@echo off
REM collect user name and computer name
echo %username%,%computername% >> \\servername\sharename\userpclog.txt
大约一个月后,我得到了 3500 个条目。 我将该文件导入到 SQL Server 中,然后创建了一个视图,以提供我的 PC 到用户列表。 398 个用户使用了 450 台计算机(某些用户,如实习生、临时员工等,可以使用任何可用的 PC)。 我没有 28 个用户的信息,但我可以处理这些。
移动 Active Directory 对象
将 PC 从一个 OU 移动到另一个 OU 的基本过程是创建与数据库的连接,获取 PC 名称列表,然后循环访问数据集,并使用当前记录作为 LDAP 路径中的通用名称 (CN) 创建一个新的 DirectoryEntry
实例。
首先,在 Visual Studio 2005 中创建一个新的控制台应用程序。 你需要添加对 System.DirectoryServices
和 System.Data
的引用。 默认情况下,你将有一个名为 Program.cs 的文件。 将该文件的内容替换为以下代码,并根据需要替换与数据库的连接、命令字符串和 LDAP 路径。
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
需要注意的一件事是,我是一名域管理员,因此创建 DirectoryEntry
实例可以在“没有”安全性的情况下工作; 否则,你需要添加安全参数。
结论
这段代码看起来可能很简单,但我找不到任何类似的例子。 因此,我将其编写出来供将来参考。 我希望你觉得它有用。
注意:此项目的一部分还涉及在注册表中编写 ODBC 连接的脚本。 这些脚本包含在源文件中。