Ausführen einer Attributbereichsabfrage

Bei der Attributbereichsabfrage handelt es sich um eine Sucheinstellung, die eine Suche nach den Attributen mit distinguished name valued eines Objekts ermöglicht. Das zu durchsuchende Attribut kann entweder ein- oder mehrwertig sein, muss aber vom typ ADS_DN_STRING sein. Wenn die Suche ausgeführt wird, listet ADSI die Distinguished Name-Werte des Attributs auf und führt die Suche nach den Objekten durch, die durch die distinguished Names dargestellt werden. Wenn beispielsweise eine attributbezogene Suche für das Elementattribut eines Gruppenobjekts durchgeführt wird, listet ADSI die distinguished Names im Memberattribut auf und durchsucht jedes Mitglied der Gruppe nach den angegebenen Suchkriterien.

Wenn eine attributbezogene Abfrage für ein Attribut ausgeführt wird, das nicht vom Typ ADS_DN_STRING ist, schlägt die Suche fehl. Für die Abfrage im Attributbereich muss außerdem die Einstellung ADS_SEARCHPREF_SEARCH_SCOPE auf ADS_SCOPE_BASE festgelegt werden. Die ADS_SEARCHPREF_SEARCH_SCOPE Einstellung wird automatisch auf ADS_SCOPE_BASE festgelegt, aber wenn die ADS_SEARCHPREF_SEARCH_SCOPE Einstellung auf einen anderen Wert festgelegt ist, schlägt IDirectorySearch::SetSearchPreference mit E_ADS_BAD_PARAMETER fehl.

Die Ergebnisse einer Abfrage im Attributbereich umfassen möglicherweise mehrere Server, und ein Server gibt möglicherweise nicht alle angeforderten Daten für alle zurückgegebenen Zeilen zurück. Wenn die letzte Zeile durch Aufrufen von IDirectorySearch::GetNextRow oder IDirectorySearch::GetFirstRow abgerufen wird, gibt ADSI S_ADS_ERRORSOCCURRED anstelle von S_ADS_NOMORE_ROWS zurück.

Um eine Attributbereichsabfrage anzugeben, legen Sie eine ADS_SEARCHPREF_ATTRIBUTE_QUERY Suchoption mit einem ADSTYPE_CASE_IGNORE_STRING Wert fest, der auf lDAPDisplayName des Attributs festgelegt ist, um im ADS_SEARCHPREF_INFO Array zu suchen, das an die IDirectorySearch::SetSearchPreference-Methode übergeben wird. Dieser Vorgang wird im folgenden Codebeispiel gezeigt.

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

Im folgenden Codebeispiel wird die Verwendung der Suchoption ADS_SEARCHPREF_ATTRIBUTE_QUERY veranschaulicht.

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

    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;
}

Wenn diese Suche ausgeführt und die Ergebnisse aufgezählt werden, wird der Name, die Telefonnummer und die Büronummer aller Benutzerobjekte zurückgegeben, die in der Mitgliederattributliste der Gruppe enthalten sind.

Fehlerbehandlung: Die Ergebnisse einer Abfrage im Attributbereich umfassen möglicherweise mehrere Server, und ein Server gibt möglicherweise nicht alle angeforderten Daten für alle zurückgegebenen Zeilen zurück. Wenn die letzte Zeile durch Aufrufen von GetNextRow oder GetFirstRow abgerufen wird, gibt ADSI S_ADS_ERRORSOCCURRED anstelle von S_ADS_NOMORE_ROWS zurück.