共用方式為


列舉域控制器

在舊版 Windows 中,應用程式只能藉由呼叫 DsGetDcName來取得網域中的單一域控制器。 無法預測要擷取的域控制器,或取得域控制器的清單。 Windows 可讓應用程式使用 DsGetDcOpenDsGetDcNextDsGetDcClose 函式來列舉網域中的域控制器。

若要列舉域控制器,請呼叫 DsGetDcOpen。 此函式會採用定義域的參數來列舉和其他列舉選項。 DsGetDcOpen 提供網域列舉上下文控制代碼,當 DsGetDcNextDsGetDcClose 被呼叫時,用來識別列舉操作。

DsGetDcNext 函式會使用網域列舉內容句柄呼叫,以擷取列舉中的下一個域控制器。 第一次呼叫此函式時,會擷取列舉中的第一個域控制器。 第二次呼叫此函式時,會擷取列舉中的第二個域控制器。 這個程式會重複執行,直到 DsGetDcNext 傳回 ERROR_NO_MORE_ITEMS,表示列舉的結尾。

DsGetDcNext 函式會列舉兩個群組中的域控制器。 第一個群組包含涵蓋執行函式的計算機站點的域控制器,而第二個群組則包含未涵蓋執行函式的計算機站點的域控制器。 如果在 DsGetDcOpenOptionFlags 參數中指定 DS_NOTIFY_AFTER_SITE_RECORDS 旗標,則擷取所有站點特定域控制器之後,DsGetDcNext 函式會傳回 ERROR_FILEMARK_DETECTEDDsGetDcNext 接著會開始列舉第二個群組,其中包含網域中的所有域控制器,包括第一個群組中包含的站點特定域控制器。

首先列舉處理執行函數之計算機站點的域控制器,然後列出未涵蓋該站點的其他域控制器。 如果網域控制器設定為位於該站點,或者網域控制器位於在設定的網站間連結成本方面距離該站點最近的站點,則表示網域控制器涵蓋該站點。 如果有任何域控制器同時出現在涵蓋計算機網站的域控制器群組和未涵蓋的計算機網站的域控制器群組中,則會根據在 DNS 中設定的優先順序和權重,在這些群組內按順序傳回這些域控制器。 具有較低數值優先順序的域控制器會先在群組內傳回。 如果在站點相關群組中有一個具有相同優先順序的多個域控制器的子群組,域控制器會以加權隨機順序被選出,其中具有較高權重的域控制器被選出的機率較高。 網域系統管理員會設定站點、優先權和權重,以在網域中多個可用域控制器之間達成效能最佳化和負載平衡。 因此,使用 DsGetDcOpen/DsGetDcNext/DsGetDcClose 函式的應用程式會自動利用這些優化。

當列舉完成或不再需要時,必須使用網域列舉內容句柄呼叫 DsGetDcClose 來關閉列舉。

若要重設列舉,您必須呼叫 DsGetDcClose 關閉目前的列舉,然後再次呼叫 DsGetDcOpen 重新開啟列舉。

下列程式代碼範例示範如何使用這些函式來列舉本機網域中的域控制器。

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