[c#] Obtenir tous les rapports directs à partir d'Active Directory


Answers

Question

J'essaie d'obtenir tous les rapports directs d'un utilisateur via Active Directory, de manière récursive. Donc, compte tenu d'un utilisateur, je finirai avec une liste de tous les utilisateurs qui ont cette personne en tant que gestionnaire ou qui ont une personne en tant que gestionnaire qui a une personne en tant que gestionnaire ... qui a finalement l'utilisateur d'entrée en tant que gestionnaire.

Ma tentative actuelle est plutôt lente:

private static Collection<string> GetDirectReportsInternal(string userDN, out long elapsedTime)
{
    Collection<string> result = new Collection<string>();
    Collection<string> reports = new Collection<string>();

    Stopwatch sw = new Stopwatch();
    sw.Start();

    long allSubElapsed = 0;
    string principalname = string.Empty;

    using (DirectoryEntry directoryEntry = new DirectoryEntry(string.Format("LDAP://{0}",userDN)))
    {
        using (DirectorySearcher ds = new DirectorySearcher(directoryEntry))
        {
            ds.SearchScope = SearchScope.Subtree;
            ds.PropertiesToLoad.Clear();
            ds.PropertiesToLoad.Add("directReports");
            ds.PropertiesToLoad.Add("userPrincipalName");
            ds.PageSize = 10;
            ds.ServerPageTimeLimit = TimeSpan.FromSeconds(2);
            SearchResult sr = ds.FindOne();
            if (sr != null)
            {
                principalname = (string)sr.Properties["userPrincipalName"][0];
                foreach (string s in sr.Properties["directReports"])
                {
                    reports.Add(s);
                }
            }
        }
    }

    if (!string.IsNullOrEmpty(principalname))
    {
        result.Add(principalname);
    }

    foreach (string s in reports)
    {
        long subElapsed = 0;
        Collection<string> subResult = GetDirectReportsInternal(s, out subElapsed);
        allSubElapsed += subElapsed;

        foreach (string s2 in subResult)
        {
        result.Add(s2);
        }
    }



    sw.Stop();
    elapsedTime = sw.ElapsedMilliseconds + allSubElapsed;
    return result;
}

Essentiellement, cette fonction prend un nom distinctif en entrée (CN = Michael Stum, OU = test, DC = sub, DC = domaine, DC = com), et avec cela, l'appel à ds.FindOne () est lent.

J'ai trouvé que c'est beaucoup plus rapide de chercher le userPrincipalName. Mon problème: sr.Properties ["directReports"] est juste une liste de chaînes, et c'est le distinguishedName, qui semble lent à chercher.

Je me demande, y at-il un moyen rapide de convertir entre distinguishedName et userPrincipalName? Ou y a-t-il un moyen plus rapide de rechercher un utilisateur si je n'ai que le distinguishedName avec lequel travailler?

Edit: Merci à la réponse! La recherche dans Manager-Field a amélioré la fonction de 90 secondes à 4 secondes. Voici le code nouveau et amélioré, qui est plus rapide et plus lisible (notez qu'il y a probablement un bogue dans la fonctionnalité elapsedTime, mais le noyau de la fonction fonctionne):

private static Collection<string> GetDirectReportsInternal(string ldapBase, string userDN, out long elapsedTime)
{
    Collection<string> result = new Collection<string>();

    Stopwatch sw = new Stopwatch();
    sw.Start();
    string principalname = string.Empty;

    using (DirectoryEntry directoryEntry = new DirectoryEntry(ldapBase))
    {
        using (DirectorySearcher ds = new DirectorySearcher(directoryEntry))
        {
            ds.SearchScope = SearchScope.Subtree;
            ds.PropertiesToLoad.Clear();
            ds.PropertiesToLoad.Add("userPrincipalName");
            ds.PropertiesToLoad.Add("distinguishedName");
            ds.PageSize = 10;
            ds.ServerPageTimeLimit = TimeSpan.FromSeconds(2);
            ds.Filter = string.Format("(&(objectCategory=user)(manager={0}))",userDN);

            using (SearchResultCollection src = ds.FindAll())
            {
                Collection<string> tmp = null;
                long subElapsed = 0;
                foreach (SearchResult sr in src)
                {
                    result.Add((string)sr.Properties["userPrincipalName"][0]);
                    tmp = GetDirectReportsInternal(ldapBase, (string)sr.Properties["distinguishedName"][0], out subElapsed);
                    foreach (string s in tmp)
                    {
                    result.Add(s);
                    }
                }
            }
          }
        }
    sw.Stop();
    elapsedTime = sw.ElapsedMilliseconds;
    return result;
}



Links