使用 IDirectorySearch 介面進行搜尋

IDirectorySearch介面提供高階和低額外負荷介面,用於查詢目錄或通用類別目錄的資料。 IDirectorySearch COM 介面只能與 vtable 搭配使用,因此不適用於以自動化為基礎的開發環境。

執行搜尋

  1. 系結至目錄中的物件。
  2. 呼叫 QueryInterface 以取得 IDirectorySearch 指標。
  3. 使用 IDirectorySearch 指標執行搜尋。 呼叫 IDirectorySearch::ExecuteSearch 方法,並傳遞搜尋篩選、要求的屬性名稱和其他參數。

如需搜尋篩選語法的詳細資訊,請參閱 搜尋篩選語法

查詢執行是提供者特定的。 在某些提供者中,在呼叫 IDirectorySearch::GetFirstRowIDirectorySearch::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 以完成搜尋作業。

執行目錄搜尋

  1. 系結至 LDAP 提供者。 它可能是網域控制站或通用類別目錄提供者。

  2. 使用對 QueryInterface的呼叫來擷取IDirectorySearch COM 介面;此作業可能已在初始系結期間于步驟 1 中完成。

    或者,呼叫 SetSearchPreference 以選取處理搜尋結果的選項。

  3. 呼叫 ExecuteSearch。 視 SetSearchPreference 中設定的選項而定,這可能會或可能不會開始執行查詢。

  4. 呼叫 GetNextRow 將資料列索引 (內部移至 IDirectorySearch) 至第一個資料列。

  5. 使用 GetColumn從資料列讀取資料,然後呼叫 FreeColumn 以釋放 GetColumn配置的記憶體。

  6. 重複步驟 5,直到從搜尋結果擷取所有資料,或直到 GetNextRow 傳回S_ADS_NOMORE_ROWS為止。

  7. 完成時呼叫 AbandonSearchCloseSearchHandle

下列程式碼範例顯示此案例。 若要開始系結至 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);