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は一度に1行ずつ前に戻ります。 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. 検索結果からすべてのデータが取得されるか、GetNextRowがS_ADS_NOMORE_ROWSを返すまで、手順5.を繰り返します。

  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は最初のページ (ページサイズ=ページ内の行数) が返されるまでブロックします。 ページサイズが設定されていて、クエリを並べ替える必要があり、少なくとも1つのインデックス付き属性で検索していない場合、ページサイズの値は無視され、サーバーはデータを返す前に結果セット全体を計算します。 これにより、クエリが完了するまでGetNextRowがブロックされます。

Note

このクエリをディレクトリ検索からグローバルカタログ検索に変更するには、ADsOpenObject呼び出しを変更します。

 

// Open a connection with the server.
hr = ADsOpenObject(L"GC://coho.salmon.Fabrikam.com", 
szUsername, 
szPassword, 
ADS_SECURE_AUTHENTICATION,
IID_IDirectorySearch,
(void **)&pDSSearch);