執行屬性範圍查詢
屬性範圍查詢是搜尋喜好設定,可搜尋要執行對象的辨別名稱值屬性。 要搜尋的屬性可以是單一或多重值,但必須是 ADS_DN_STRING 類型。 執行搜尋時,ADSI 會列舉屬性的辨別名稱值,並在辨別名稱所代表的物件上執行搜尋。 例如,如果屬性範圍搜尋是針對群組對象的成員屬性執行,ADSI 會列舉成員屬性中的辨別名稱,並搜尋群組中每個成員的指定搜尋準則。
如果在不是 類型ADS_DN_STRING的屬性上執行屬性範圍查詢,搜尋將會失敗。 屬性範圍查詢也需要 將ADS_SEARCHPREF_SEARCH_SCOPE 喜好設定為 ADS_SCOPE_BASE。 ADS_SEARCHPREF_SEARCH_SCOPE喜好設定會自動設定為 ADS_SCOPE_BASE,但如果ADS_SEARCHPREF_SEARCH_SCOPE喜好設定設定為任何其他值,IDirectorySearch::SetSearchPreference 將會失敗並E_ADS_BAD_PARAMETER。
屬性範圍查詢的結果可能會跨越多部伺服器,而且伺服器可能不會傳回針對所傳回所有數據列所要求的所有數據。 如果發生這種情況,呼叫 IDirectorySearch::GetNextRow 或 IDirectorySearch::GetFirstRow 來擷取最後一個數據列時,ADSI 會傳回S_ADS_ERRORSOCCURRED而不是S_ADS_NOMORE_ROWS。
若要指定屬性範圍查詢,請設定ADS_SEARCHPREF_ATTRIBUTE_QUERY搜尋選項,並將ADSTYPE_CASE_IGNORE_STRING值設定為屬性的 lDAPDisplayName,以在傳遞至 IDirectorySearch::SetSearchPreference 方法的ADS_SEARCHPREF_INFO數位中搜尋。 此作業會顯示在下列程式代碼範例中。
ADS_SEARCHPREF_INFO SearchPref;
SearchPref.dwSearchPref = ADS_SEARCHPREF_ATTRIBUTE_QUERY;
SearchPref.vValue.dwType = ADSTYPE_CASE_IGNORE_STRING;
SearchPref.vValue.Boolean = L"member";
下列程式代碼範例示範如何使用 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;
}
執行此搜尋並列舉結果時,會傳回群組成員屬性清單中所有使用者物件的名稱、電話號碼和辦公室號碼。
錯誤處理:屬性範圍查詢的結果可能會跨越多部伺服器,而且伺服器可能不會傳回針對傳回之所有數據列所要求的所有數據。 如果發生這種情況,呼叫 GetNextRow 或 GetFirstRow 擷取最後一個數據列時,ADSI 會傳回S_ADS_ERRORSOCCURRED,而不是S_ADS_NOMORE_ROWS。