使用 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提供者。 它可能是域控制器或全域編錄提供者。
擷取 IDirectorySearch COM 介面,並呼叫 QueryInterface;這項作業可能在初始系結期間於步驟 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);