使用 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 以逐一查看結果中的資料列。 接著會查詢每個資料列的 「description」 屬性。 如果找到屬性,則會顯示它。
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);