列舉域控制器
在舊版 Windows 中,應用程式只能藉由呼叫 DsGetDcName 來取得網域中的單一域控制器。 無法預測要擷取的域控制器,或取得域控制器的清單。 Windows 可讓應用程式使用 DsGetDcOpen、DsGetDcNext 和 DsGetDcClose 函式列舉網域中的域控制器。
若要列舉域控制器,請呼叫 DsGetDcOpen。 此函式會採用定義域的參數來列舉和其他列舉選項。 DsGetDcOpen 提供網域列舉內容句柄,用來識別呼叫 DsGetDcNext 和 DsGetDcClose 時的列舉作業。
使用網域列舉內容句柄呼叫 DsGetDcNext 函式,以擷取列舉中的下一個域控制器。 第一次呼叫此函式時,會擷取列舉中的第一個域控制器。 第二次呼叫此函式時,會擷取列舉中的第二個域控制器。 此程式會重複執行,直到 DsGetDcNext 傳回 ERROR_NO_MORE_ITEMS,表示列舉的結尾。
DsGetDcNext 函式會列舉兩個群組中的域控制器。 第一個群組包含涵蓋執行函式之計算機的月臺的域控制器,而第二個群組則包含未涵蓋執行函式之計算機月臺的域控制器。 如果在 DsGetDcOpen 的 OptionFlags 參數中指定DS_NOTIFY_AFTER_SITE_RECORDS旗標,DsGetDcNext 函式會在擷取所有月臺特定域控制器之後傳回ERROR_FILEMARK_DETECTED。 DsGetDcNext 接著會開始列舉第二個群組,其中包含網域中的所有域控制器,包括第一個群組中包含的月臺特定域控制器。
處理執行函式之計算機的月臺的域控制器會先列舉,後面接著未涵蓋執行函式之計算機的月臺的域控制器。 如果域控制器設定為位於該網站,或者域控制器位於網站中,或域控制器位於月臺內,就設定的網站間連結成本而言,表示域控制器會涵蓋網站。 如果涵蓋的域控制器群組和未涵蓋計算機網站的域控制器群組中有任何域控制器,則域控制器會依照其設定的優先順序和 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);
}