使用 IDirectorySearch 介面搜尋
IDirectorySearch 介面提供高階和低負荷介面,用於查詢目錄或全域編錄的數據。 IDirectorySearch COM 介面只能與 vtable 搭配使用,因此無法供以自動化為基礎的開發環境使用。
執行搜尋
- 系結至目錄中的物件。
- 呼叫 QueryInterface 以取得 IDirectorySearch 指標。
- 使用 IDirectorySearch 指標執行搜尋。 呼叫 IDirectorySearch::ExecuteSearch 方法,並傳遞搜尋篩選、要求的屬性名稱和其他參數。
如需搜尋篩選語法的詳細資訊,請參閱 搜尋篩選語法。
查詢執行是提供者特定的。 使用某些提供者時,在呼叫 IDirectorySearch::GetFirstRow 或 IDirectorySearch::GetNextRow 之前,不會執行實際的查詢執行。 IDirectorySearch 介面可直接與搜尋篩選搭配使用。 不需要 SQL 方言或 LDAP 方言。
IDirectorySearch 介面提供方法來列舉結果集,逐列列出。 IDirectorySearch::GetFirstRow 方法會擷取第一個數據列,而 IDirectorySearch::GetNextRow 會將您移至目前數據列的下一個數據列。 當您到達最後一個數據列時,呼叫這些方法會傳回S_ADS_NOMORE_ROWS錯誤碼。 相反地, IDirectorySearch::GetPreviousRow 會一次將您移回一個數據列。 S_ADS_NOMORE_ROWS傳回值表示您已到達結果集的第一個數據列。 這些方法會在用戶端上位於記憶體中的結果集上運作。 因此,執行分頁和異步搜尋並關閉_CACHE_RESULTS選項時,向後捲動可能會產生非預期的結果。
當您找到適當的數據列時,請呼叫 IDirectorySearch::GetColumn 以依數據行取得數據項。 針對每個呼叫,您會傳遞感興趣的數據行名稱。 傳回的數據項是ADS_SEARCH_COLUMN結構的指標。 GetColumn 會為您配置此結構,但您必須使用 FreeColumn來釋放它。 呼叫 CloseSearchHandle 以完成搜尋作業。
若要執行目錄搜尋
系結至LDAP提供者。 它可能是域控制器或全域編錄提供者。
使用對 QueryInterface 的呼叫擷取 IDirectorySearch COM 介面;此作業可能在初始系結期間於步驟 1 中完成。
您可以選擇性地呼叫 SetSearchPreference 來選取選項來處理搜尋的結果。
呼叫 ExecuteSearch。 視 SetSearchPreference 中設定的選項而定,這可能會或可能不會開始執行查詢。
呼叫 GetNextRow ,將數據列索引 (內部移至 IDirectorySearch) 移至第一個數據列。
使用 GetColumn 從數據列讀取數據,然後呼叫 FreeColumn 以釋放 GetColumn 所設定的記憶體。
重複步驟 5,直到從搜尋結果擷取所有數據,或直到 GetNextRow 傳回S_ADS_NOMORE_ROWS為止。
完成時呼叫 AbandonSearch 和 CloseSearchHandle。
下列程式代碼範例顯示此案例。 若要開始系結至 ADSI,請呼叫 ADsOpenObject 函式。
HRESULT hr = S_OK; // COM result variable
ADS_SEARCH_COLUMN col; // COL for iterations
LPWSTR szUsername = NULL; // user name
LPWSTR szPassword = NULL; // password
// Interface Pointers.
IDirectorySearch *pDSSearch =NULL;
// Initialize COM.
CoInitialize(0);
// Add code to securely retrieve the user name and password or
// leave both as NULL to use the default security context.
// Open a connection with server.
hr = ADsOpenObject(L"LDAP://coho.salmon.Fabrikam.com",
szUsername,
szPassword,
ADS_SECURE_AUTHENTICATION,
IID_IDirectorySearch,
(void **)&pDSSearch);
這會提供 IDirectorySearch 介面的指標。
現在 IDirectoryInterface 實例有 COM 介面,請呼叫 IDirectorySearch::SetSearchPreference。
建置屬性名稱陣列,以準備呼叫 IDirectorySearch::ExecuteSearch 函式。 屬性名稱定義於 Active Directory 的架構內。 如需架構定義的詳細資訊,請參閱 ADSI 架構模型。 如果物件支援,則會傳回列出的屬性名稱,做為搜尋的結果集。
LPWSTR pszAttr[] = { L"description", L"Name", L"distinguishedname" };
ADS_SEARCH_HANDLE hSearch;
DWORD dwCount = 0;
DWORD dwAttrNameSize = sizeof(pszAttr)/sizeof(LPWSTR);
現在,呼叫 ExecuteSearch 函式。 在您呼叫 GetNextRow 方法之前,搜尋不會執行。
// Search for all objects with the 'cn' property that start with c.
hr = pDSSearch->ExecuteSearch(L"(cn=c*)",pszAttr ,dwAttrNameSize,&hSearch );
呼叫 GetNextRow 以反覆運算結果中的數據列。 接著會查詢每個數據列的「描述」屬性。 如果找到屬性,則會顯示它。
LPWSTR pszColumn;
while( pDSSearch->GetNextRow( hSearch) != S_ADS_NOMORE_ROWS )
{
// Get the property.
hr = pDSSearch->GetColumn( hSearch, L"description", &col );
// If this object supports this attribute, display it.
if ( SUCCEEDED(hr) )
{
if (col.dwADsType == ADSTYPE_CASE_IGNORE_STRING)
wprintf(L"The description property:%s\r\n", col.pADsValues->CaseIgnoreString);
pDSSearch->FreeColumn( &col );
}
else
puts("description property NOT available");
puts("------------------------------------------------");
dwCount++;
}
pDSSearch->CloseSearchHandle(hSearch);
pDSSearch->Release();
若要結束搜尋,請呼叫 AbandonSearch 方法。
請注意,如果未設定頁面大小, GetNextRow 會封鎖,直到整個結果集傳回客戶端為止。 如果已設定頁面大小,則會 傳回 GetNextRow 區塊,直到第一頁 (頁面大小 = 頁面中的數據列數目) 為止。 如果已設定頁面大小,而且要排序查詢,而且您未搜尋至少一個索引屬性,則會忽略頁面大小值,而且伺服器會在傳回數據之前計算整個結果集。 這會影響 GetNextRow 封鎖,直到查詢完成為止。
注意
若要將此查詢從目錄搜尋變更為全域編錄搜尋, ADsOpenObject 呼叫會變更。
// Open a connection with the server.
hr = ADsOpenObject(L"GC://coho.salmon.Fabrikam.com",
szUsername,
szPassword,
ADS_SECURE_AUTHENTICATION,
IID_IDirectorySearch,
(void **)&pDSSearch);