使用 IDirectorySearch 介面搜尋

IDirectorySearch 介面提供高階和低負荷介面,用於查詢目錄或全域編錄的數據。 IDirectorySearch COM 介面只能與 vtable 搭配使用,因此無法供以自動化為基礎的開發環境使用。

執行搜尋

  1. 系結至目錄中的物件。
  2. 呼叫 QueryInterface 以取得 IDirectorySearch 指標。
  3. 使用 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 以完成搜尋作業。

若要執行目錄搜尋

  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 以反覆運算結果中的數據列。 接著會查詢每個數據列的「描述」屬性。 如果找到屬性,則會顯示它。

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);