Condividi tramite


Enumerazione dei controller di dominio

Nelle versioni precedenti di Windows, un'applicazione potrebbe ottenere un solo controller di dominio in un dominio chiamando DsGetDcName. Non è stato possibile prevedere quale controller di dominio sarebbe stato recuperato o ottenere un elenco dei controller di dominio. Windows consente a un'applicazione di enumerare i controller di dominio in un dominio usando le funzioni DsGetDcOpen, DsGetDcNext e DsGetDcClose.

Per enumerare un controller di dominio, chiamare DsGetDcOpen. Questa funzione accetta parametri che definiscono il dominio per enumerare e altre opzioni di enumerazione. DsGetDcOpen fornisce un handle di contesto di enumerazione di dominio usato per identificare l'operazione di enumerazione quando vengono chiamati DsGetDcNext e DsGetDcClose.

La funzione DsGetDcNext viene chiamata con l'handle del contesto di enumerazione del dominio per recuperare il controller di dominio successivo nell'enumerazione . La prima volta che questa funzione viene chiamata, viene recuperato il primo controller di dominio nell'enumerazione . La seconda volta che questa funzione viene chiamata, viene recuperato il secondo controller di dominio nell'enumerazione . Questo processo viene ripetuto fino a quando DsGetDcNext non restituisce ERROR_NO_MORE_ITEMS, che indica la fine dell'enumerazione.

La funzione DsGetDcNext enumera i controller di dominio in due gruppi. Il primo gruppo contiene i controller di dominio che coprono il sito del computer in cui viene eseguita la funzione e il secondo gruppo contiene i controller di dominio che non coprono il sito del computer in cui viene eseguita la funzione. Se il flag DS_NOTIFY_AFTER_SITE_RECORDS viene specificato nel parametro OptionFlags in DsGetDcOpen, la funzione DsGetDcNext restituirà ERROR_FILEMARK_DETECTED dopo il recupero di tutti i controller di dominio specifici del sito. DsGetDcNext inizierà quindi a enumerare il secondo gruppo, che contiene tutti i controller di dominio nel dominio, inclusi i controller di dominio specifici del sito contenuti nel primo gruppo.

I controller di dominio che gestiscono il sito del computer in cui viene eseguita la funzione vengono enumerati prima seguiti dai controller di dominio che non coprono il sito del computer in cui viene eseguita la funzione. Un controller di dominio viene detto coprire un sito se il controller di dominio è configurato per risiedere in tale sito o se il controller di dominio risiede in un sito più vicino al sito in questione in termini di costo del collegamento tra siti configurato. Se sono presenti controller di dominio nel gruppo di controller di dominio che coprono e il gruppo di controller di dominio che non coprono il sito del computer, i controller di dominio vengono restituiti all'interno del gruppo in ordine di priorità e pesi configurati specificati in DNS. I controller di dominio con priorità numerica inferiore vengono restituiti prima all'interno di un gruppo. Se all'interno di un gruppo correlato al sito è presente un sottogruppo di più controller di dominio con la stessa priorità, i controller di dominio vengono restituiti in un ordine casuale ponderato in cui i controller di dominio con peso maggiore hanno più probabilità di essere restituiti per primi. I siti, le priorità e i pesi sono configurati dall'amministratore di dominio per ottenere prestazioni efficaci e bilanciamento del carico tra più controller di dominio disponibili nel dominio. Per questo motivo, le applicazioni che usano le funzioni DsGetDcOpen/DsGetDcNext/DsGetDcClose sfruttano automaticamente queste ottimizzazioni.

Quando l'enumerazione è completa o non è più necessaria, l'enumerazione deve essere chiusa chiamando DsGetDcClose con l'handle del contesto di enumerazione del dominio.

Per reimpostare l'enumerazione, è necessario chiudere l'enumerazione corrente chiamando DsGetDcClose e quindi riaprire l'enumerazione chiamando di nuovo DsGetDcOpen.

Esempio

Nell'esempio di codice seguente viene illustrato come usare queste funzioni per enumerare i controller di dominio nel dominio locale.

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