Esecuzione di una query di ambito attributo

La query dell'ambito dell'attributo è una preferenza di ricerca che consente di eseguire una ricerca degli attributi di nome distinti di un oggetto. L'attributo da cercare può essere singolo o multivalore, ma deve essere del tipo ADS_DN_STRING . Quando viene eseguita la ricerca, ADSI enumera i valori dei nomi distinti dell'attributo ed esegue la ricerca sugli oggetti rappresentati dai nomi distinti. Ad esempio, se viene eseguita una ricerca con ambito attributo dell'attributo membro di un oggetto gruppo, ADSI enumera i nomi distinti nell'attributo membro e cerca ognuno dei membri del gruppo per i criteri di ricerca specificati.

Se viene eseguita una query con ambito attributo su un attributo che non è di tipo ADS_DN_STRING, la ricerca avrà esito negativo. La query con ambito attributo richiede anche che la preferenza ADS_SEARCHPREF_SEARCH_SCOPE sia impostata su ADS_SCOPE_BASE. La preferenza ADS_SEARCHPREF_SEARCH_SCOPE verrà impostata automaticamente su ADS_SCOPE_BASE, ma se la preferenza ADS_SEARCHPREF_SEARCH_SCOPE è impostata su qualsiasi altro valore, IDirectorySearch::SetSearchPreference avrà esito negativo con E_ADS_BAD_PARAMETER.

I risultati di una query con ambito attributo possono estendersi su più server e un server potrebbe non restituire tutti i dati richiesti per tutte le righe restituite. In questo caso, quando l'ultima riga viene recuperata chiamando IDirectorySearch::GetNextRow o IDirectorySearch::GetFirstRow, ADSI restituirà S_ADS_ERRORSOCCURRED anziché S_ADS_NOMORE_ROWS.

Per specificare una query dell'ambito dell'attributo, impostare un'opzione di ricerca ADS_SEARCHPREF_ATTRIBUTE_QUERY con un valore ADSTYPE_CASE_IGNORE_STRING impostato sul valore lDAPDisplayName dell'attributo per la ricerca nella matriceADS_SEARCHPREF_INFO passata al metodo IDirectorySearch::SetSearchPreference. Questa operazione viene illustrata nell'esempio di codice seguente.

ADS_SEARCHPREF_INFO SearchPref;
SearchPref.dwSearchPref = ADS_SEARCHPREF_ATTRIBUTE_QUERY;
SearchPref.vValue.dwType = ADSTYPE_CASE_IGNORE_STRING;
SearchPref.vValue.Boolean = L"member";

Nell'esempio di codice seguente viene illustrato come usare l'opzione di ricerca ADS_SEARCHPREF_ATTRIBUTE_QUERY .

/***************************************************************************

    SearchGroupMembers()

    Searches the members of a group that are of type user and prints each 
    user's cn and distinguishedName values to the console.

    Parameters:

    pwszGroupDN - Contains the distinguished name of the group whose 
    members will be searched.

***************************************************************************/

HRESULT SearchGroupMembers(LPCWSTR pwszGroupDN)
{
    HRESULT hr;
    CComPtr<IDirectorySearch> spSearch;
    CComBSTR sbstrADsPath;
 
    // Bind to the group and get the IDirectorySearch interface.
    sbstrADsPath = "LDAP://";
    sbstrADsPath += pwszGroupDN;
    hr = ADsOpenObject(sbstrADsPath,
        NULL,
        NULL,
        ADS_SECURE_AUTHENTICATION,
        IID_IDirectorySearch,
        (void**)&spSearch);
    if(FAILED(hr))
    {
        return hr;
    }
 
    ADS_SEARCHPREF_INFO SearchPrefs[1];

    // Set the ADS_SEARCHPREF_ATTRIBUTE_QUERY search preference.
    SearchPrefs[0].dwSearchPref = ADS_SEARCHPREF_ATTRIBUTE_QUERY;
    SearchPrefs[0].vValue.dwType = ADSTYPE_CASE_IGNORE_STRING;
    SearchPrefs[0].vValue.CaseIgnoreString = L"member";

    // Set the search preferences.
    hr = spSearch->SetSearchPreference(SearchPrefs, sizeof(SearchPrefs)/sizeof(ADS_SEARCHPREF_INFO));
    if(FAILED(hr))
    {
        return hr;
    }

    ADS_SEARCH_HANDLE hSearch;
    
    // Create the search filter.
    LPWSTR pwszSearchFilter = L"(&(objectClass=user))";
 
    // Set attributes to return.
    LPWSTR rgpwszAttributes[] = {L"cn", L"distinguishedName"};
    DWORD dwNumAttributes = sizeof(rgpwszAttributes)/sizeof(LPWSTR);
 
    // Execute the search.
    hr = spSearch->ExecuteSearch(pwszSearchFilter,
        rgpwszAttributes,
        dwNumAttributes,
        &hSearch);
    if(FAILED(hr))
    {
        return hr;
    }

    // Get the first result row.
    hr = spSearch->GetFirstRow(hSearch);
    while(S_OK == hr)
    {
        ADS_SEARCH_COLUMN col;

        // Enumerate the retrieved attributes.
        for(DWORD i = 0; i < dwNumAttributes; i++)
        {
            hr = spSearch->GetColumn(hSearch, rgpwszAttributes[i], &col);
            if(SUCCEEDED(hr))
            {
                switch(col.dwADsType)
                {
                case ADSTYPE_DN_STRING:
                    wprintf(L"%s: %s\n\n", rgpwszAttributes[i], col.pADsValues[0].DNString);
                    break;

                case ADSTYPE_CASE_IGNORE_STRING:
                    wprintf(L"%s: %s\n\n", rgpwszAttributes[i], col.pADsValues[0].CaseExactString);
                    break;

                default:
                    break;
                }
                
                // Free the column.
                spSearch->FreeColumn(&col);
            }
        }
        
        // Get the next row.
        hr = spSearch->GetNextRow(hSearch);
    }

    // Close the search handle to cleanup.
    hr = spSearch->CloseSearchHandle(hSearch);

    return hr;
}

Quando questa ricerca viene eseguita e i risultati vengono enumerati, restituirà il nome, il numero di telefono e il numero di ufficio di tutti gli oggetti utente contenuti nell'elenco di attributi membro del gruppo.

Gestione degli errori: i risultati di una query con ambito attributo possono estendersi su più server e un server potrebbe non restituire tutti i dati richiesti per tutte le righe restituite. In questo caso, quando l'ultima riga viene recuperata chiamando GetNextRow o GetFirstRow, ADSI restituirà S_ADS_ERRORSOCCURRED anziché S_ADS_NOMORE_ROWS.