Recherche avec l’interface IDirectorySearch
L’interface IDirectorySearch fournit une interface de haut niveau et à faible surcharge pour interroger les données d’un répertoire ou d’un catalogue global. L’interface COM IDirectorySearch ne peut être utilisée qu’avec une table virtuelle et n’est donc pas disponible pour les environnements de développement basés sur Automation.
Pour effectuer une recherche
- Lier à un objet dans le répertoire.
- Appelez QueryInterface pour obtenir le pointeur IDirectorySearch .
- Exécutez la recherche à l’aide du pointeur IDirectorySearch . Appelez la méthode IDirectorySearch::ExecuteSearch , puis passez un filtre de recherche, les noms d’attributs demandés et d’autres paramètres.
Pour plus d’informations sur la syntaxe du filtre de recherche, consultez Syntaxe du filtre de recherche.
L’exécution de la requête est spécifique au fournisseur. Avec certains fournisseurs, l’exécution réelle de la requête ne se produit pas tant que IDirectorySearch::GetFirstRow ou IDirectorySearch::GetNextRow n’est pas appelé. L’interface IDirectorySearch fonctionne directement avec les filtres de recherche. Ni le dialecte SQL ni le dialecte LDAP ne sont requis.
L’interface IDirectorySearch fournit des méthodes pour énumérer le jeu de résultats, ligne par ligne. La méthode IDirectorySearch::GetFirstRow récupère la première ligne et IDirectorySearch::GetNextRow vous déplace vers la ligne suivante à partir de la ligne actuelle. Lorsque vous avez atteint la dernière ligne, l’appel de ces méthodes renvoie le code d’erreur S_ADS_NOMORE_ROWS. À l’inverse, IDirectorySearch::GetPreviousRow vous déplace d’une ligne à la fois. Une valeur de retour S_ADS_NOMORE_ROWS indique que vous avez atteint la première ligne du jeu de résultats. Ces méthodes fonctionnent sur le jeu de résultats, résidant en mémoire, sur le client. Ainsi, lorsque des recherches paginées et asynchrones sont effectuées et que l’option _CACHE_RESULTS est désactivée, le défilement vers l’arrière peut avoir des conséquences inattendues.
Une fois que vous avez trouvé la ligne appropriée, appelez IDirectorySearch::GetColumn pour obtenir des éléments de données, colonne par colonne. Pour chaque appel, vous transmettez le nom de la colonne qui vous intéresse. L’élément de données retourné est un pointeur vers une structure ADS_SEARCH_COLUMN . GetColumn alloue cette structure pour vous, mais vous devez la libérer à l’aide de FreeColumn. Appelez CloseSearchHandle pour terminer l’opération de recherche.
Pour effectuer une recherche d’annuaire
Lier à un fournisseur LDAP. Il peut s’agir d’un contrôleur de domaine ou d’un fournisseur de catalogue global.
Récupérer l’interface COM IDirectorySearch avec un appel à QueryInterface ; cette opération peut avoir été effectuée à l’étape 1 pendant la liaison initiale.
Si vous le souhaitez, appelez SetSearchPreference pour sélectionner les options de gestion des résultats de votre recherche.
Appelez ExecuteSearch. Selon les options définies dans SetSearchPreference , cela peut, ou non, commencer l’exécution de la requête.
Appelez GetNextRow pour déplacer l’index de ligne (interne à IDirectorySearch) vers la première ligne.
Lisez les données de la ligne à l’aide de GetColumn, puis appelez FreeColumn pour libérer la mémoire allouée par GetColumn.
Répétez l’étape 5 jusqu’à ce que toutes les données soient récupérées à partir du résultat de recherche, ou jusqu’à ce que GetNextRow retourne S_ADS_NOMORE_ROWS.
Appelez AbandonSearch et CloseSearchHandle lorsque vous avez terminé.
L’exemple de code suivant illustre ce scénario. Pour commencer à lier à ADSI, appelez la fonction 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);
Cela fournit un pointeur vers l’interface IDirectorySearch .
Maintenant qu’il existe une interface COM pour un instance IDirectoryInterface, appelez IDirectorySearch::SetSearchPreference.
Créez un tableau de noms d’attributs pour préparer l’appel de la fonction IDirectorySearch::ExecuteSearch . Les noms d’attribut sont définis dans le schéma d’Active Directory. Pour plus d’informations sur la définition de schéma, consultez Modèle de schéma ADSI. Les noms d’attributs répertoriés sont retournés, s’ils sont pris en charge par l’objet, en tant que jeu de résultats de la recherche.
LPWSTR pszAttr[] = { L"description", L"Name", L"distinguishedname" };
ADS_SEARCH_HANDLE hSearch;
DWORD dwCount = 0;
DWORD dwAttrNameSize = sizeof(pszAttr)/sizeof(LPWSTR);
À présent, appelez la fonction ExecuteSearch . La recherche ne s’exécute pas tant que vous n’appelez pas la méthode GetNextRow .
// Search for all objects with the 'cn' property that start with c.
hr = pDSSearch->ExecuteSearch(L"(cn=c*)",pszAttr ,dwAttrNameSize,&hSearch );
Appelez GetNextRow pour itérer les lignes dans le résultat. Chaque ligne est ensuite interrogée pour l’attribut « description ». Si l’attribut est trouvé, il s’affiche.
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();
Pour mettre fin à la recherche, appelez la méthode AbandonSearch .
N’oubliez pas que si la taille d’une page n’est pas définie, GetNextRow est bloqué jusqu’à ce que l’ensemble du jeu de résultats soit retourné au client. Si la taille de page est définie, GetNextRow bloque jusqu’à ce que la première page (taille de page = nombre de lignes dans une page) soit retournée. Si la taille de page est définie et que la requête doit être triée et que vous ne recherchez pas sur au moins un attribut indexé, la valeur de taille de page est ignorée et le serveur calcule l’ensemble du jeu de résultats avant de renvoyer les données. Cela a pour effet de bloquer GetNextRow jusqu’à la fin de la requête.
Notes
Pour remplacer cette requête d’une recherche d’annuaire par une recherche de catalogue global, l’appel ADsOpenObject est modifié.
// Open a connection with the server.
hr = ADsOpenObject(L"GC://coho.salmon.Fabrikam.com",
szUsername,
szPassword,
ADS_SECURE_AUTHENTICATION,
IID_IDirectorySearch,
(void **)&pDSSearch);