Поиск с помощью интерфейса IDirectorySearch

Интерфейс IDirectorySearch предоставляет высокоуровневый и низкоуровневый интерфейс для запроса данных каталога или глобального каталога. COM-интерфейс IDirectorySearch можно использовать только с 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. Получите COM-интерфейс IDirectorySearch с вызовом QueryInterface. Эта операция может быть выполнена на шаге 1 во время начальной привязки.

    При необходимости вызовите SetSearchPreference , чтобы выбрать параметры обработки результатов поиска.

  3. Вызов ExecuteSearch. В зависимости от параметров, заданных в SetSearchPreference , это может быть возможно или не может начать выполнение запроса.

  4. Вызовите GetNextRow, чтобы переместить индекс строки (внутренний в IDirectorySearch) в первую строку.

  5. Считывайте данные из строки с помощью GetColumn, а затем вызовите FreeColumn, чтобы освободить память, выделенную GetColumn.

  6. Повторите шаг 5, пока все данные не будут получены из результата поиска или пока GetNextRow не возвращает S_ADS_NOMORE_ROWS.

  7. По завершении вызовите 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.

Теперь, когда существует COM-интерфейс для экземпляра IDirectoryInterface, вызовите 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);