Auflisten von Domänencontrollern

In früheren Versionen von Windows konnte eine Anwendung nur einen einzelnen Domänencontroller in einer Domäne abrufen, indem Sie DsGetDcName aufruft. Es gab keine Möglichkeit, vorherzusagen, welcher Domänencontroller abgerufen werden würde, oder eine Liste der Domänencontroller abzurufen. Windows ermöglicht einer Anwendung das Auflisten der Domänencontroller in einer Domäne mithilfe der Funktionen DsGetDcOpen, DsGetDcNext und DsGetDcClose .

Um einen Domänencontroller aufzulisten, rufen Sie DsGetDcOpen auf. Diese Funktion verwendet Parameter, die die Domäne definieren, um die Enumerationsoptionen und andere Enumerationsoptionen aufzulisten. DsGetDcOpen stellt ein Domänenaufzählungskontexthandle bereit, das verwendet wird, um den Enumerationsvorgang zu identifizieren, wenn DsGetDcNext und DsGetDcClose aufgerufen werden.

Die DsGetDcNext-Funktion wird mit dem Domänenaufzählungskontexthandle aufgerufen, um den nächsten Domänencontroller in der Enumeration abzurufen. Wenn diese Funktion zum ersten Mal aufgerufen wird, wird der erste Domänencontroller in der Enumeration abgerufen. Beim zweiten Aufruf dieser Funktion wird der zweite Domänencontroller in der Enumeration abgerufen. Dieser Prozess wird wiederholt, bis DsGetDcNextERROR_NO_MORE_ITEMS zurückgibt, das das Ende der Enumeration angibt.

Die DsGetDcNext-Funktion listet die Domänencontroller in zwei Gruppen auf. Die erste Gruppe enthält die Domänencontroller, die den Standort des Computers abdecken, auf dem die Funktion ausgeführt wird, und die zweite Gruppe enthält die Domänencontroller, die nicht den Standort des Computers abdecken, auf dem die Funktion ausgeführt wird. Wenn das DS_NOTIFY_AFTER_SITE_RECORDS-Flag im OptionFlags-Parameter in DsGetDcOpen angegeben ist, gibt die DsGetDcNext-FunktionERROR_FILEMARK_DETECTED zurück, nachdem alle standortspezifischen Domänencontroller abgerufen wurden. DsGetDcNext beginnt dann mit dem Aufzählen der zweiten Gruppe, die alle Domänencontroller in der Domäne enthält, einschließlich der standortspezifischen Domänencontroller in der ersten Gruppe.

Domänencontroller, die den Standort des Computers behandeln, auf dem die Funktion ausgeführt wird, werden zuerst aufgelistet, gefolgt von den Domänencontrollern, die den Standort des Computers, auf dem die Funktion ausgeführt wird, nicht abdecken. Ein Domänencontroller deckt einen Standort ab, wenn der Domänencontroller so konfiguriert ist, dass er sich an diesem Standort befindet oder wenn sich der Domänencontroller an einem Standort befindet, der dem betreffenden Standort in Bezug auf die konfigurierten Kosten für die Standortverknüpfung am nächsten ist. Wenn sowohl in der Gruppe der Domänencontroller, die den Computerstandort abdecken, als auch in der Gruppe der Domänencontroller, die den Computerstandort nicht abdecken, Domänencontroller vorhanden sind, werden Domänencontroller innerhalb der Gruppe in der Reihenfolge ihrer konfigurierten Prioritäten und Gewichtungen zurückgegeben, die in DNS angegeben sind. Domänencontroller mit niedrigerer numerischer Priorität werden zuerst innerhalb einer Gruppe zurückgegeben. Wenn innerhalb einer standortbezogenen Gruppe eine Untergruppe aus mehreren Domänencontrollern mit der gleichen Priorität vorhanden ist, werden Domänencontroller in einer gewichteten zufälligen Reihenfolge zurückgegeben, wobei Domänencontroller mit höherer Gewichtung eine höhere Wahrscheinlichkeit haben, zuerst zurückgegeben zu werden. Die Standorte, Prioritäten und Gewichtungen werden vom Domänenadministrator konfiguriert, um einen effektiven Leistungs- und Lastenausgleich zwischen mehreren in der Domäne verfügbaren Domänencontrollern zu erzielen. Aus diesem Gründen nutzen Anwendungen, die die DsGetDcOpen/DsGetDcNext/DsGetDcClose-Funktionen verwenden, diese Optimierungen automatisch.

Wenn die Enumeration abgeschlossen ist oder nicht mehr erforderlich ist, muss die Enumeration durch Aufrufen von DsGetDcClose mit dem Domänenaufzählungskontexthandle geschlossen werden.

Um die Enumeration zurückzusetzen, müssen Sie die aktuelle Enumeration schließen, indem Sie DsGetDcClose aufrufen und dann die Enumeration erneut öffnen, indem Sie DsGetDcOpen erneut aufrufen.

Beispiel

Das folgende Codebeispiel zeigt, wie Sie diese Funktionen verwenden, um die Domänencontroller in der lokalen Domäne aufzulisten.

DWORD dwRet;
PDOMAIN_CONTROLLER_INFO pdcInfo;

// Get a domain controller for the domain this computer is on.
dwRet = DsGetDcName(NULL, NULL, NULL, NULL, 0, &pdcInfo);
if(ERROR_SUCCESS == dwRet)
{
    HANDLE hGetDc;
    
    // Open the enumeration.
    dwRet = DsGetDcOpen(    pdcInfo->DomainName,
                            DS_NOTIFY_AFTER_SITE_RECORDS,
                            NULL,
                            NULL,
                            NULL,
                            0,
                            &hGetDc);
    if(ERROR_SUCCESS == dwRet)
    {
        LPTSTR pszDnsHostName;

        /*
        Enumerate each domain controller and print its name to the 
        debug window.
        */
        while(TRUE)
        {
            ULONG ulSocketCount;
            LPSOCKET_ADDRESS rgSocketAddresses;

            dwRet = DsGetDcNext(
                hGetDc, 
                &ulSocketCount, 
                &rgSocketAddresses, 
                &pszDnsHostName);
            
            if(ERROR_SUCCESS == dwRet)
            {
                OutputDebugString(pszDnsHostName);
                OutputDebugString(TEXT("\n"));
                
                // Free the allocated string.
                NetApiBufferFree(pszDnsHostName);

                // Free the socket address array.
                LocalFree(rgSocketAddresses);
            }
            else if(ERROR_NO_MORE_ITEMS == dwRet)
            {
                // The end of the list has been reached.
                break;
            }
            else if(ERROR_FILEMARK_DETECTED == dwRet)
            {
                /*
                DS_NOTIFY_AFTER_SITE_RECORDS was specified in 
                DsGetDcOpen and the end of the site-specific 
                records was reached.
                */
                OutputDebugString(
                  TEXT("End of site-specific domain controllers\n"));
                continue;
            }
            else
            {
                // Some other error occurred.
                break;
            }
        }
        
        // Close the enumeration.
        DsGetDcClose(hGetDc);
    }
    
    // Free the DOMAIN_CONTROLLER_INFO structure. 
    NetApiBufferFree(pdcInfo);
}