Фильтр DirectorySearcher, как ограничить на основе последних 30 дней
Я ищу Active Directory для пользователей в определенном подразделении. Я получаю только пользователей, которые вошли в систему за последние 30 дней.
Мой поисковый фильтр Query:
string query = "(&(objectCategory=person)(objectClass=user)((lastLogon<=" + new DateTime(DateTime.Now.AddDays(-30).Ticks) + ")(mail=*))";
Я получаю фильтр поиска недействительным, я использовал:
string query = "(&(objectCategory=person)(objectClass=user)((lastLogon=*)(mail=*))";
Без ошибок
Я изменил последний вход в систему следующим образом:
(lastLogon<=1)
Я вызываю метод, который делает это
public static DataTable GetADusers() {
try {
string ou = "OU";
using(PrincipalContext ctx = new PrincipalContext(ContextType.Domain, Environment.UserDomainName, ou)) {
UserPrincipal user = new UserPrincipal(ctx);
using(PrincipalSearcher ps = new PrincipalSearcher(user)) {
DataTable results = new DataTable();
results.Columns.Add("DisplayName ");
results.Columns.Add("FirstName");
results.Columns.Add("Initial");
results.Columns.Add("LastName");
results.Columns.Add("mail");
results.Columns.Add("SamAccountName");
results.Columns.Add("DistinguishedName");
results.Columns.Add("lastLogon");
int count = 0;
int ctNull = 0;
foreach(Principal p in ps.FindAll()) {
UserPrincipal u = p as UserPrincipal;
if (u != null) {
DirectoryEntry entry = (DirectoryEntry) p.GetUnderlyingObject();
DirectorySearcher search = new DirectorySearcher(entry);
string query = "(&(objectCategory=person)(objectClass=user)((lastLogon<=" + new DateTime(DateTime.Now.AddDays( - 30).Ticks) + ")(mail=*))";
search.Filter = query;
search.PropertiesToLoad.Add("DisplayName");
search.PropertiesToLoad.Add("GivenName");
search.PropertiesToLoad.Add("Initials");
search.PropertiesToLoad.Add("sn");
search.PropertiesToLoad.Add("mail");
search.PropertiesToLoad.Add("SamAccountName");
search.PropertiesToLoad.Add("DistinguishedName");
search.PropertiesToLoad.Add("lastLogon");
SearchResultCollection mySearchResultColl = search.FindAll();
foreach(SearchResult sr in mySearchResultColl) {
DataRow dr = results.NewRow();
DirectoryEntry de = sr.GetDirectoryEntry();
dr["EmployeeID"] = de.Properties["EmployeeID"].Value;
dr["DisplayName "] = de.Properties["DisplayName"].Value;
dr["FirstName"] = de.Properties["GivenName"].Value;
dr["Initial"] = de.Properties["Initials"].Value;
dr["LastName"] = de.Properties["sn"].Value;
dr["mail"] = de.Properties["mail"].Value;
dr["SamAccountName"] = de.Properties["SamAccountName"].Value;
dr["DistinguishedName"] = de.Properties["DistinguishedName"].Value;
//prepare for last logon
if (de.Properties["lastLogon"] != null && de.Properties["lastLogon"].Count > 0) {
Int64 lastLogonThisServer = new Int64();
IADsLargeInteger lgInt = (IADsLargeInteger) de.Properties["lastLogon"].Value;
lastLogonThisServer = ((long) lgInt.HighPart << 32) + lgInt.LowPart;
dr["lastLogon"] = DateTime.FromFileTime(lastLogonThisServer).ToString();
}
else {
dr["lastLogon"] = DateTime.MinValue.ToString();
ctNull++;
}
results.Rows.Add(dr);
count++;
}
}
}
Console.WriteLine(count);
Console.WriteLine("Null");
Console.WriteLine(ctNull);
return results;
}
}
}
catch(NullReferenceException ex) {
Console.WriteLine("data error" + ex);
DataTable dt = new DataTable();
return dt;
}
}
Вышеуказанная функция работает хорошо! Должен быть способ проверить, не старше ли последнего входа в систему более 30 дней. Буду признателен за любую помощь. Благодарю вас!
Ответ ниже правильный
Мне пришлось добавить следующий код, чтобы поместить данные в базу данных:
if (de.Properties["LastLogonTimestamp"] != null && de.Properties["LastLogonTimestamp"].Count > 0)
{
Int64 lastLogonDateThisServer = new Int64();
IADsLargeInteger lgInt = (IADsLargeInteger)de.Properties["LastLogonTimestamp"].Value;
lastLogonDateThisServer = ((long)lgInt.HighPart << 32) + lgInt.LowPart;
dr["LastLogonTimestamp"] = DateTime.FromFileTime(lastLogonDateThisServer).ToString();
}
else
{
dr["LastLogonTimestamp"] = DateTime.MinValue.ToString();
ctNull++;
}
Я поместил его под lastLogon. Для фильтра запросов: мне пришлось повернуть знак <, чтобы получить данные с этого 30-дневного значения.
string query = "(&(objectCategory=person)(objectClass=user)(!userAccountControl:1.2.840.113556.1.4.803:=2)(!userAccountControl:1.2.840.113556.1.4.803:=65536)(userAccountControl:1.2.840.113556.1.4.803:=262144)(userPrincipalName=1*@mil)(lastlogon>=" + DateTime.Now.AddDays(-90).ToFileTime() + ")(lastLogonTimestamp>=" + DateTime.Now.AddDays(-90).ToFileTime() + ")(mail=*))";
1 ответ
В вашем запросе у вас есть две скобки перед lastLogon
когда они вам не нужны:
((lastLogon<=...
Вот почему вы получаете сообщение об ошибке "фильтр поиска недействителен". Которые должны быть:
(lastLogon<=...
Но вы также неправильно рассчитываете стоимость. У вас есть это:
new DateTime(DateTime.Now.AddDays( - 30).Ticks)
Но lastLogon
не использует клещей
Позже в вашем коде вы используете FromFileTime
зачитать lastLogon
, Точно так же вы можете использовать ToFileTime
преобразовать дату в формат, который вы можете использовать в запросе. Как это:
DateTime.Now.AddDays(-30).ToFileTime()
Но имейте в виду, что lastLogon
не реплицируется - он точен только на последнем контроллере домена, с которым аутентифицировался пользователь. Поэтому, если в вашем домене имеется более одного контроллера домена, вы не получите точное значение для большинства учетных записей.
lastLogonTimestamp
атрибут был создан именно по этой причине. Он повторяется по крайней мере каждые 2 недели, поэтому вы знаете, что значение является точным в течение 2 недель. Вы можете использовать тот же формат для этого:
string query = "(&(objectCategory=person)(objectClass=user)(lastLogonTimestamp<="
+ DateTime.Now.AddDays(-30).ToFileTime() + ")(mail=*))";
Вы можете прочитать больше о lastLogonTimestamp
атрибут здесь: https://blogs.technet.microsoft.com/askds/2009/04/15/the-lastlogontimestamp-attribute-what-it-was-designed-for-and-how-it-works/