我正在为Active Directory中的所有组运行以下代码。
我要执行的操作是首先运行查询以获取Active Directory中的所有组并返回其专有名称。接下来,我使用下面的代码来获取每个组中所有子组的列表。这包括嵌套的子组。该代码可以正常运行,尽管它确实很慢。
LDAP查询始终执行得非常快,但是当我尝试使用结果时,它却非常慢。有什么我可以用来加快这个过程的吗?
目前,我花了大约2个小时才能执行大约20000个小组。 (我的广告中有超过200万)。
以下是我使用的代码:
获取所有群组
public override IEnumerable<ADGroupObj> GetCustomGroupAndMember(ADSetting setting)
{
var m_strADFilter = configHandler.GetCustomGroupFilterString().ToString();
string classAndMethodName = $"{this.GetType().Name}.{MethodBase.GetCurrentMethod().Name}";
string[] properties = { "objectGUID", "cn", "distinguishedName", "member", "objectSid" };
//group
m_log.DebugFormat("[{0}]: [GetAllGroupAndMemberFromDomainController] m_strADFilter = {1}", classAndMethodName, m_strADFilter);
if (string.IsNullOrWhiteSpace(m_strADFilter))
{
string strErrorMsg = string.Format("[{0}]: Incorrect AD filter string !!!", classAndMethodName);
m_log.ErrorFormat(strErrorMsg);
throw new Exception(strErrorMsg);
}
bool isSuccess = false;
using (ADServerWrapper instADServer = ADServerWrapper.GetADServerWrapper(setting, this.ConnectType))
{
int iTotalCount = 0;
int iInvalidCount = 0;
int iValidCount = 0;
var results = instADServer.QueryADbyFilterObj(m_strADFilter, properties);
if (results == null)
{ throw new Exception("Error occured while invoking instADServer.QueryADbyFilterObj."); }
(var whiteListDomainOUs, var blackListDomainOUs) = configHandler.GetADSpecifyDomainOU();
foreach (SearchResult result in results)
{
++iTotalCount;
// Check Result valid or not
ADGroupObj adGroup = AnalyzeADGroupObj(result.Properties, whiteListDomainOUs, blackListDomainOUs);
adGroup = GetAllGrpMembers(adGroup,setting);
if (adGroup != null && ValidateADGroup(adGroup))
{
++iValidCount;
configHandler.UpdateCustomGroupDN(adGroup.DN);
yield return adGroup;
m_log.DebugFormat("[{0}]: AD Group ([Valid]/[total] count=[{1}]/[{2}]): {3}", classAndMethodName, iValidCount, iTotalCount, adGroup.Name);
}
else
{
++iInvalidCount;
m_log.DebugFormat("[{0}]: AD Group ([Null or inValid]/[total] count={1}/{2})", classAndMethodName, iInvalidCount, iTotalCount);
}
}
isSuccess = true;
}
if (!isSuccess)
{
string strErrorMsg = string.Format("[{0}]: Did not complete successfully, isSuccess == false.", classAndMethodName);
m_log.ErrorFormat(strErrorMsg);
throw new Exception(strErrorMsg);
}
}
获取所有子组
protected ADGroupObj GetAllGrpMembers(ADGroupObj aDGroup, ADSetting setting) {
string methodName = MethodBase.GetCurrentMethod().Name;
var forUserConnectType = ADServiceConnectType.AD_CONNECT_TYPE_GC | (this.connectType & ADServiceConnectType.AD_CONNECT_TYPE_SSL);
var instADServer = ADServerWrapper.GetADServerWrapper(setting, forUserConnectType);
string m_strADFilter = $"(&(objectCategory=group)(memberOf:1.2.840.113556.1.4.1941:={aDGroup.DN}))";
string[] properties = {
"distinguishedName"
};
try
{
aDGroup.Members = new List<string>();
IEnumerable<SearchResult> results = instADServer.QueryADbyFilterObj(m_strADFilter, properties);
if (results != null)
{
foreach (SearchResult result in results)
{
if (result.Properties["distinguishedName"] != null && result.Properties["distinguishedName"].Count > 0)
{
var user = result.Properties["distinguishedName"][0];
aDGroup.Members.Add(user.ToString());
}
}
}
else
m_log.DebugFormat("[{0}]:No value with member attribute!", methodName);
}
catch (Exception e)
{
}
return aDGroup;
}
这两个区域中的foreach结果列最耗时。而不是按过滤对象查询广告。
供参考: QueruADByFilterObj
public IEnumerable<SearchResult> QueryADbyFilterObj(string strFilter, string[] properties)
{
using (var searcher = new DirectorySearcher(m_ADEntryObject))
{
searcher.Filter = strFilter;
searcher.SizeLimit = int.MaxValue;
searcher.PageSize = int.MaxValue;
searcher.CacheResults = false;
searcher.PropertiesToLoad.AddRange(properties);
//searcher.ReferralChasing = ReferralChasingOption.All;
using (SearchResultCollection searchResults = searcher.FindAll())
{
foreach (SearchResult result in searchResults)
{
yield return result;
}
}
}
}
答案 0 :(得分:0)
您正在执行的操作将花费很长时间。您正在提取大量数据。
我写了一篇有关使用AD进行编程时获取better performance的文章,但看来您已经按照搜索建议(确保使用PropertiesToLoad
)进行了推荐。但是看来您还没有在此处共享一些代码,因此您可以对其进行检查,看看是否还有其他可以调整的地方。
读取结果要花费很长时间,因为结果会出现在页面中。您将PageSize
设置为int.MaxValue
,但是AD一次不会返回超过1000个结果。因此,结果将在1000页中发送给您。这意味着当您尝试处理结果1001时,它将暂停,进入AD并获取下一页结果。在2001、3001等处也是如此
这也可能有助于了解为什么首先要提取所有这些数据。将其全部存储在AD中似乎很奇怪。但是我知道您可能刚刚被告知要这样做。。。这是我的事。
作为旁注,您是否了解C#中的string interpolation?它可以使您的string.Format
行更加容易阅读。例如,这一行:
string strErrorMsg = string.Format("[{0}]: Incorrect AD filter string !!!", classAndMethodName);
可以简化为:
var strErrorMsg = $"[{classAndMethodName}]: Incorrect AD filter string !!!";