5

对于 Active Directory 在站点之间复制数据的时间过长的情况,我需要确保本地 AD 副本包含最新信息。

  • 如何获取当前站点的域控制器列表?

我在CodeprojectStackOverflow上没有找到任何东西

4

4 回答 4

9

解决所有这些麻烦可能是浪费精力。除非您在查找域控制器的内置逻辑方面遇到问题,否则您应该使用返回一个的内置方法。根据微软的说法,它会自动尝试找到关闭的: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;

    }
于 2012-07-13T01:55:07.773 回答
2

首先,我将回答您实际提出的问题:

System.DirectoryServices.ActiveDirectory.ActiveDirectorySite.GetComputerSite().Servers

但似乎您在问如何确保您正在与可能的最近的域控制器交谈。Windows 并不完全提供此功能,它会做的最好的事情是在运行代码的同一站点中为您提供域控制器。

我认为首先要检查的是您的站点和子网配置是否正确。运行 Active Directory 站点和服务,并确保将子网和域控制器分配给正确的站点。

这个 MSDN 页面(以及 Peter 的回答中的 Technet 文章)说您必须通过 DNS 名称搜索 DC Locator 才能尝试在当前站点中查找 DC。不知道Domain类的Name属性是不是DNS域名。

我必须假设 DomainController.FindOne 是DsGetDcName. 在该链接中,您可以找到如何为该功能打开跟踪。如果您仍然有问题,您可以使用它,或者您应该只 PInvoke 这个函数。

于 2012-11-21T16:33:28.613 回答
1

这是一个没有 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;
    }
于 2012-06-12T17:44:59.117 回答
0

这是我使用 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)",""
于 2017-10-12T16:07:50.353 回答