Obtenga el controlador de dominio más cercano en el sitio AD actual sin información de codificación fija

Para los casos en que Active Directory tarda demasiado en replicar datos entre sitios, debo asegurarme de que la réplica local de AD contenga la información más actualizada.

  • ¿Cómo puedo obtener una lista de DomainControllers para el sitio actual?

no he encontrado nada en Proyecto de código o en StackOverflow

preguntado el 12 de junio de 12 a las 16:06

¿Tuviste la oportunidad de echar un vistazo a la actualización que agregué a mi respuesta? -

4 Respuestas

Pasar por todo este problema probablemente sea un esfuerzo desperdiciado. A menos que tenga problemas con la lógica incorporada para encontrar un controlador de dominio, debe usar el método incorporado que devuelve uno. Según Microsoft, automáticamente intenta encontrar el más cercano: http://technet.microsoft.com/en-us/library/cc978016.aspx.

Solo usa la estática DomainController.FindOne método y pase su directorycontext.

Noticias
Muy bien, prueba el código a continuación, hazme saber cómo funciona para ti. Hace ping a cada uno, devuelve el tiempo de ida y vuelta, si -1 (sin conexión) lo omite. Marca el estado del PDC si está presente. Pedidos por estado de PDC, seguido de ping de ida y vuelta.

    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;

    }

Respondido 13 Jul 12, 19:07

El problema es que no confío en que FindOne funcione de la manera que describe technet. El código en ejecución parece indicar que el servidor se elige al azar. - Christopher Jon Mankowski

@makerofthings7: actualicé mi respuesta para incluir un ejemplo que creo que funcionará para usted. - Peter

@makerofthings7 - ¿Tuviste la oportunidad de probar esto? - Peter

Gracias, aún no lo he probado, pero creo que puede funcionar. Volveré a la oficina la próxima semana y puedo probarlo entonces. Christopher Jon Mankowski

El localizador de CC devuelve el más cercano a través de una solicitud de DNS que utiliza turnos rotativos. El problema es que el más cercano puede tener un rendimiento de canal bajo. La solución de ping es buena: oldovets

Primero, responderé la pregunta que realmente hiciste:

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

Pero parece que está preguntando cómo asegurarse de que está hablando con el controlador de dominio más cercano posible. Windows no proporciona exactamente esta funcionalidad, lo mejor que hará es darle un controlador de dominio en el mismo sitio desde el que se ejecuta el código.

Creo que lo primero que debe verificar es que tenga sus sitios y subredes configurados correctamente. Ejecute Sitios y servicios de Active Directory y asegúrese de que las subredes y los controladores de dominio estén asignados a los sitios correctos.

Esta página de MSDN (y el artículo de Technet en la respuesta de Peter) dice que debe buscar por el nombre DNS del localizador de DC para intentar encontrar un DC en el sitio actual. No sé si la propiedad Nombre de la clase Dominio es el nombre de dominio DNS.

Debo suponer que DomainController.FindOne es un contenedor para DsGetDcName. En ese enlace, puede encontrar cómo activar el seguimiento para esa función. Puede usar esto si todavía tiene problemas, o tal vez solo debería PInvocar esta función.

respondido 21 nov., 12:16

Aquí hay un ejemplo de código que no tiene codificación fija de DC. Los comentarios y las críticas son bienvenidos.

    /// <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;
    }

Respondido el 12 de junio de 12 a las 19:06

Pregunta para quien pueda responder: ¿Está obligado el cliente a disponer de cada DomainController ¿ejemplo? - Christopher Jon Mankowski

Dado que la clase implementa iDisposable, lo sugeriría. Estas clases de DirectoryEntry tienden a perder memoria. - Peter

Este es mi enfoque usando powershell, pero estoy seguro de que es una implementación simple en C#, etc. Si DHCP está configurado correctamente, el servidor DNS primario en su subred debería ser el controlador de dominio más cercano. Entonces, el siguiente código debería tomar la primera IP de DNS y resolverla en el nombre de host del DC más cercano. Esto no requiere RSAT ni credenciales y no contiene propiedades específicas del dominio actual.

$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)",""

Respondido 12 Oct 17, 17:10

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.