IDirectorySearch 인터페이스를 사용하여 검색
IDirectorySearch 인터페이스는 디렉터리 또는 글로벌 카탈로그의 데이터를 쿼리하기 위한 높은 수준의 낮은 오버헤드 인터페이스를 제공합니다. IDirectorySearch COM 인터페이스는 vtable에서만 사용할 수 있으므로 Automation 기반 개발 환경에서는 사용할 수 없습니다.
검색을 수행하려면
- 디렉터리의 개체에 바인딩합니다.
- 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에서 할당한 메모리를 해제합니다.
검색 결과에서 모든 데이터가 검색되거나 GetNextRow 가 S_ADS_NOMORE_ROWS 반환될 때까지 5단계를 반복합니다.
완료되면 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 instance 대한 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);