Привет, все, что я портирую через мой VBScript на C #. И я столкнулся с проблемой, что поиск свойств Active Directory намного медленнее в C #.
Это мой неполный код C #
foreach(string s in dictLast.Keys)
{
if(s.Contains("/"))
str = s.Insert(s.IndexOf('/'), "\\");
else
str = s;
dEntry = new DirectoryEntry("LDAP://" + str);
strUAC = dEntry.Properties["userAccountControl"].Value.ToString();
cmd.CommandText = "INSERT INTO [NOW](readTime) VALUES(\"" + test.Elapsed.Milliseconds.ToString() + "\")";
cmd.ExecuteNonQuery();
test.Reset();
test.Start();
}
Если я закомментирую эту строку.
strUAC = dEntry.Properties ["userAccountControl"]. Value.ToString ();
Это работает в 11 секунд. Но если я этого не сделаю, это будет длиться 2 минуты 35 секунд. Количество записей 3700. В среднем каждая запись длится 50 секунд. Я использую класс секундомера.
Мой VBscript запускается всего за 39 секунд (с использованием разницы во времени). С каждой записью 0 или 15 миллисекунд. Я использую разницу Timer ().
Вот мой VBscript
strAttributes = "displayName, pwdLastSet, whenCreated, whenChanged, userAccountControl"
For Each strUser In objList.Keys
prevTime = Timer()
strFilter = "(sAMAccountName=" & strUser & ")"
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
adoCommand.CommandText = strQuery
Set adoRecordset = adoCommand.Execute
On Error Resume Next
If (adoRecordset.Fields("displayName") = null) Then
strCN = "-"
Else
strCN = adoRecordset.Fields("displayName")
End If
If (Err.Number <> 0) Then
MsgBox(strUser)
End If
strCr8 = DateAdd("h", 8, adoRecordset.Fields("whenCreated"))
strUAC = adoRecordset.Fields("userAccountControl")
If (strUAC AND ADS_UF_DONT_EXPIRE_PASSWD) Then
strPW = "Never expires"
Else
If (TypeName(adoRecordset.Fields("pwdLastSet").Value) = "Object") Then
Set objDate = adoRecordset.Fields("pwdLastSet").Value
dtmPwdLastSet = Integer8Date(objDate, lngBias)
Else
dtmPwdLastSet = #1/1/1601#
End If
If (dtmPwdLastSet = #1/1/1601#) Then
strPW = "Must Change at Next Logon"
Else
strPW = DateAdd("d", sngMaxPwdAge, dtmPwdLastSet)
End If
End If
retTime = Timer() - prevTime
If (objList.Item(strUser) = #1/1/1601#) Then
Wscript.Echo strCN & ";" & strUser & ";" & strPW & ";" & strCr8 & ";" & ObjChange.Item(strUser) & ";0;" & strUAC & ";" & retTime
Else
Wscript.Echo strCN & ";" & strUser & ";" & strPW & ";" & strCr8 & ";" & ObjChange.Item(strUser) & ";" & objList.Item(strUser) & ";" & strUAC & ";" & retTime
End If
Next
Есть идеи, в чем проблема?
Пожалуйста, скажите мне, если я не даю достаточно информации. Спасибо.
Директория поиска. 1 мин 8 сек.
dEntry = new DirectoryEntry("LDAP://" + strDNSDomain);
string[] strAttr = {"userAccountControl"};
foreach(string s in dictLast.Keys)
{
if(s.Contains("/"))
str = s.Insert(s.IndexOf('/'), "\\");
else
str = s;
ds = new DirectorySearcher(de, "(sAMAccountName=" + s + ")", strAttr, SearchScope.Subtree);
ds.PropertiesToLoad.Add("userAccountControl");
SearchResult rs = ds.FindOne();
strUAC = rs.Properties["userAccountControl"][0].ToString();
cmd.CommandText = "INSERT INTO [NOW](readTime) VALUES(\"" + test.Elapsed.Milliseconds.ToString() + "\")";
cmd.ExecuteNonQuery();
test.Reset();
test.Start();
}
где strDNSDomain - это defaultNamingContext. Я пытался с доменным именем, но оно работает хуже, в 3 минуты 30 секунд.
Глядя на чужой код. Будет ли разница, если мы опустим доменную часть?
using (var LDAPConnection = new DirectoryEntry("LDAP://domain/dc=domain,dc=com", "username", "password"))
И просто используйте вместо этого «LDAP: // dc = domain, dc = com».
Работа вокруг. Вместо привязки каждого пользователя и получения свойств. Вместо этого я сохранил все свойства в первом поиске lastLogon. И вывод с использованием StreamWriter.