Ricerca con l'interfaccia IDirectorySearch

L'interfaccia IDirectorySearch offre un'interfaccia di alto livello e basso sovraccarico per l'esecuzione di query sui dati di una directory o di un catalogo globale. L'interfaccia COM IDirectorySearch può essere usata solo con una tabella virtuale e pertanto non è disponibile per gli ambienti di sviluppo basati su Automazione.

Per eseguire una ricerca

  1. Eseguire il binding a un oggetto nella directory .
  2. Chiamare QueryInterface per ottenere il puntatore IDirectorySearch.
  3. Eseguire la ricerca usando il puntatore IDirectorySearch. Chiamare il metodo IDirectorySearch::ExecuteSearch e passare un filtro di ricerca, i nomi degli attributi richiesti e altri parametri.

Per altre informazioni sulla sintassi del filtro di ricerca, vedere sintassi del filtro di ricerca.

L'esecuzione della query è specifica del provider. Con alcuni provider, l'esecuzione effettiva della query non viene eseguita finché non viene chiamato IDirectorySearch::GetFirstRow o IDirectorySearch::GetNextRow. L'interfaccia IDirectorySearch funziona direttamente con i filtri di ricerca. Non è necessario né il dialetto SQL né il dialetto LDAP.

L'interfaccia IDirectorySearch fornisce metodi per enumerare il set di risultati, riga per riga. Il metodo IDirectorySearch::GetFirstRow recupera la prima riga e IDirectorySearch::GetNextRow sposta la riga successiva dalla riga corrente. Dopo aver raggiunto l'ultima riga, la chiamata a questi metodi restituisce il codice di errore S_ADS_NOMORE_ROWS. Viceversa, IDirectorySearch::GetPreviousRow ti sposta indietro di una riga alla volta. Un valore restituito S_ADS_NOMORE_ROWS indica che è stata raggiunta la prima riga del set di risultati. Questi metodi operano sul set di risultati, residente in memoria, sul client. Pertanto, quando vengono eseguite ricerche in pagine e asincrone e l'opzione _CACHE_RESULTS è disattivata, lo scorrimento indietro può avere conseguenze impreviste.

Quando si trova la riga appropriata, chiamare IDirectorySearch::GetColumn per ottenere elementi di dati, colonna per colonna. Per ogni chiamata si passa il nome della colonna di interesse. L'elemento di dati restituito è un puntatore a una struttura ADS_edizione StandardARCH_COLUMN. GetColumn alloca automaticamente questa struttura, ma è necessario liberarla usando FreeColumn. Chiamare CloseSearchHandle per completare l'operazione di ricerca.

Per eseguire una ricerca nella directory

  1. Eseguire l'associazione a un provider LDAP. Può trattarsi di un controller di dominio o di un provider di catalogo globale.

  2. Recuperare l'interfaccia COM IDirectorySearch con una chiamata a QueryInterface. Questa operazione potrebbe essere stata eseguita nel passaggio 1 durante l'associazione iniziale.

    Facoltativamente, chiamare SetSearchPreference per selezionare le opzioni per la gestione dei risultati della ricerca.

  3. Chiamare ExecuteSearch. A seconda delle opzioni impostate in SetSearchPreference , è possibile che l'esecuzione della query venga avviata o meno.

  4. Chiamare GetNextRow per spostare l'indice di riga (interno a IDirectorySearch) alla prima riga.

  5. Leggere i dati dalla riga usando GetColumn, quindi chiamare FreeColumn per rilasciare la memoria allocata da GetColumn.

  6. Ripetere il passaggio 5 finché tutti i dati non vengono recuperati dal risultato della ricerca o fino a quando GetNextRow non restituisce S_ADS_NOMORE_ROWS.

  7. Al termine, chiamare AbandonSearch e CloseSearchHandle.

L'esempio di codice seguente illustra questo scenario. Per avviare l'associazione ad ADSI, chiamare la funzione 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);

In questo modo viene fornito un puntatore all'interfaccia IDirectorySearch .

Ora che è disponibile un'interfaccia COM per un'istanza IDirectoryInterface, chiamare IDirectorySearch::SetSearchPreference.

Compilare una matrice di nomi di attributo per preparare la chiamata alla funzione IDirectorySearch::ExecuteSearch . I nomi degli attributi vengono definiti all'interno dello schema di Active Directory. Per altre informazioni sulla definizione dello schema, vedere Modello di schema ADSI. I nomi degli attributi elencati vengono restituiti, se supportati dall'oggetto, come set di risultati della ricerca.

LPWSTR pszAttr[] = { L"description", L"Name", L"distinguishedname" };
ADS_SEARCH_HANDLE hSearch;
DWORD dwCount = 0;
DWORD dwAttrNameSize = sizeof(pszAttr)/sizeof(LPWSTR);

Chiamare ora la funzione ExecuteSearch . La ricerca non viene eseguita finché non si chiama il metodo GetNextRow.

// Search for all objects with the 'cn' property that start with c.
hr = pDSSearch->ExecuteSearch(L"(cn=c*)",pszAttr ,dwAttrNameSize,&hSearch );

Chiamare GetNextRow per scorrere le righe nel risultato. Ogni riga viene quindi eseguita una query per l'attributo "description". Se l'attributo viene trovato, viene visualizzato.

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

Per terminare la ricerca, chiamare il metodo AbandonSearch.

Tenere presente che se le dimensioni di una pagina non sono impostate, GetNextRow si blocca fino a quando l'intero set di risultati non viene restituito al client. Se la dimensione della pagina è impostata, GetNextRow si blocca fino a quando non viene restituita la prima pagina (dimensione pagina = numero di righe in una pagina). Se la dimensione della pagina è impostata e la query deve essere ordinata e non si esegue la ricerca in almeno un attributo indicizzato, il valore delle dimensioni della pagina viene ignorato e il server calcola l'intero set di risultati prima di restituire i dati. Questo ha l'effetto del blocco GetNextRow fino al completamento della query.

Nota

Per modificare questa query da una ricerca di directory a una ricerca di catalogo globale, la chiamata ADsOpenObject viene modificata.

 

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