获取当前 AD 站点中最近的域控制器,而无需硬编码信息
本文关键字:信息 编码 控制器 域控 AD 站点 最近 获取 | 更新日期: 2023-09-27 18:36:59
对于 Active Directory 在站点之间复制数据的时间过长的情况,我需要确保本地 AD 副本包含最新信息。
- 如何获取当前站点的域控制器列表?
我在Codeproject或StackOverflow上没有找到任何东西。
去找所有这些麻烦可能是白费力气。 除非在查找域控制器的内置逻辑方面遇到问题,否则应使用返回域控制器的内置方法。 根据Microsoft它会自动尝试找到关闭的:http://technet.microsoft.com/en-us/library/cc978016.aspx。
只需使用静态DomainController.FindOne
方法并传入您的directorycontext
即可。
更新
好的,尝试下面的代码,让我知道它是如何为您工作的。 它 ping 每个,返回往返时间,如果 -1(无连接)它会跳过它。 标记 PDC 状态(如果存在)。 按 PDC 状态排序,然后是 ping 往返。
static void Main(string[] args)
{
var dcsInOrder = (from DomainController c in Domain.GetCurrentDomain().DomainControllers
let responseTime = Pinger(c.Name)
where responseTime >=0
let pdcStatus = c.Roles.Contains(ActiveDirectoryRole.PdcRole)
orderby pdcStatus, responseTime
select new {DC = c, ResponseTime = responseTime}
).ToList();
foreach (var dc in dcsInOrder)
{
System.Console.WriteLine(dc.DC.Name + " - " + dc.ResponseTime);
}
System.Console.ReadLine();
}
private static int Pinger(string address)
{
Ping p = new Ping();
try
{
PingReply reply = p.Send(address, 3000);
if (reply.Status == IPStatus.Success) return (int)reply.RoundtripTime;
}
catch { }
return -1;
}
首先,我将回答您实际提出的问题:
System.DirectoryServices.ActiveDirectory.ActiveDirectorySite.GetComputerSite().Servers
但似乎你在问如何确保你正在与最近的域控制器交谈。 Windows 并不完全提供此功能,它所做的最好的事情是在运行代码的同一站点中为您提供域控制器。
我认为首先要检查的是您是否正确配置了站点和子网。 运行 Active Directory 站点和服务,并确保将子网和域控制器分配给正确的站点。
此 MSDN 页面(以及 Peter 的答案中的 Technet 文章)指出,您必须按 DNS 名称搜索 DC 定位器,才能尝试在当前站点中查找 DC。 我不知道域类的 Name 属性是否为 DNS 域名。
我必须假设DomainController.FindOne是DsGetDcName
的包装器。 在该链接中,您可以找到如何为该功能启用跟踪。 如果您仍然遇到问题,您可以使用它,或者您可能应该只调用此函数。
下面是没有 DC 硬编码的代码示例。 欢迎评论和批评。
/// <summary>
/// For best results ensure all hosts are pingable, and turned on.
/// </summary>
/// <returns>An ordered list of DCs with the PDCE first</returns>
static LinkedList<DomainController> GetNearbyDCs()
{
LinkedList<DomainController> preferredDCs = new LinkedList<DomainController>();
List<string> TestedDCs = new List<string>();
using (var mysite = ActiveDirectorySite.GetComputerSite())
{
using (var currentDomain = Domain.GetCurrentDomain())
{
DirectoryContext dctx = new DirectoryContext(DirectoryContextType.Domain, currentDomain.Name);
var listOfDCs = DomainController.FindAll(dctx, mysite.Name);
foreach (DomainController item in listOfDCs)
{
Console.WriteLine(item.Name );
if (IsConnected(item.IPAddress))
{
// Enumerating "Roles" will cause the object to bind to the server
ActiveDirectoryRoleCollection rollColl = item.Roles;
if (rollColl.Count > 0)
{
foreach (ActiveDirectoryRole roleItem in rollColl)
{
if (!TestedDCs.Contains(item.Name))
{
TestedDCs.Add(item.Name);
if (roleItem == ActiveDirectoryRole.PdcRole)
{
preferredDCs.AddFirst(item);
break;
}
else
{
if (preferredDCs.Count > 0)
{
var tmp = preferredDCs.First;
preferredDCs.AddBefore(tmp, item);
}
else
{
preferredDCs.AddFirst(item);
}
break;
}
}
}
}
else
{
// The DC exists but has no roles
TestedDCs.Add(item.Name);
if (preferredDCs.Count > 0)
{
var tmp = preferredDCs.First;
preferredDCs.AddBefore(tmp, item);
}
else
{
preferredDCs.AddFirst(item);
}
}
}
else
{
preferredDCs.AddLast(item);
}
}
}
}
return preferredDCs;
}
static bool IsConnected(string hostToPing)
{
string pingurl = string.Format("{0}", hostToPing);
string host = pingurl;
bool result = false;
Ping p = new Ping();
try
{
PingReply reply = p.Send(host, 3000);
if (reply.Status == IPStatus.Success)
return true;
}
catch { }
return result;
}
使用 powershell 的方法,但我确信它是 c# 等中的简单实现。 如果 DHCP 设置正确,则子网中的主 DNS 服务器应该是最近的域控制器。 因此,以下代码应获取第一个 DNS IP 并将其解析为最近的 DC 的主机名。 这不需要 RSAT 或凭据,并且不包含当前域的特定属性。
$NetItems = @(Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter "IPEnabled = 'True'" -ComputerName $env:COMPUTERNAME)
foreach ($objItem in $NetItems)
{
if ($objItem.{DNSServerSearchOrder}.Count -ge 1)
{
$PrimaryDNS = $objItem.DNSServerSearchOrder[0]
$domain = $objItem.DNSDomain
break
}
}
[System.Net.Dns]::GetHostbyAddress($PrimaryDNS).hostname -replace ".$($domain)",""