Active Directory를 통해 사용자의 모든 직접 보고서를 재귀 적으로 가져 오려고합니다. 그래서 주어진 사용자가 관리자로이 사람을 가진 모든 사용자의 목록으로 끝나게 될 것입니다. 관리자로 사람이 있고 관리자로 사람이있는 사람은 결국 관리자로 입력 된 사용자를 갖게됩니다.Active Directory에서 모든 직접 보고서 가져 오기
내 현재의 시도가 다소 느리다 : 기본적으로
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;
}
,이 기능은 입력으로 고유 이름을 사용합니다 (CN = 마이클 방부제로 발효를 막다, OU = 테스트, DC = 서브, DC = 도메인, DC = com)을 , 그걸로 ds.FindOne()에 대한 호출이 느립니다.
userPrincipalName을 검색하는 것이 훨씬 빠르다는 것을 알았습니다. 내 문제 : sr.Properties [ "directReports"]는 문자열의 목록 일 뿐이며 distinguishedName은 검색 속도가 느립니다.
distinguishedName과 userPrincipalName 사이를 변환하는 빠른 방법이 있습니까? 또는 작업 할 distinguishedName 만 있으면 사용자를 검색하는 더 빠른 방법이 있습니까?
편집 : 답변 감사합니다! Manager-Field를 검색하면 기능이 90 초에서 4 초로 향상되었습니다. 여기에보다 신속하고 읽을 수있는 새로운 및 향상된 코드입니다합니다 (elapsedTime 기능에 버그가 가장 가능성이 있습니다 만, 함수의 실제 코어 작동) :
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;
}
DirectoryEntry 및 DirectorySearcher를 재귀에서 제외하면 속도가 향상 될 수 있습니다. 그들은 변화하지 않는다. – Tomalak
더 이상 없습니다. 내가 말하지 않은 것은 :이 매개 변수는 SPSecurity.RunWithElevatedPrivileges 호출로 둘러싸인 Sharepoint 환경에서 사용됩니다. 즉, ref 매개 변수가 가능하지 않으며 일반적인 매개 변수로 전달하는 것이 확실하지 않습니다. 이상한 Sharepoint Security) –
나는 그것이 작동해야한다고 생각한다. 객체는 항상 ref, AFAIK로 전달됩니다. 참조 : http://stackoverflow.com/questions/186891/why-use-ref-keyword-when-passing-an-object – Tomalak