首先,如果我没有使用正确的术语,请原谅我。无论我在哪里使用错误的术语,都要纠正我。
目标是以编程方式检索给定用户名的lastLogon
日期。
我相信是一片森林;两个AD服务器,如 - adserver01.aa.mycompany.com
和adserver02.aa.mycompany.com
我使用Microsoft的ADExplorer从第三台计算机连接到这些服务器以检查对象。我在adserver01
看到一些用户有上次登录日期,但adserver02
没有。例如,lastLogon的值在adserver02
中为0x0,而对于某些用户来说,它是adserver01
中的有效日期。
到目前为止,我开发的代码是Windows窗体应用程序,如果只涉及一个AD服务器,则可以正常工作。对于lastLogon日期属性,如何检查两个服务器并返回非零值(如果可用)?
private static string GetLastActivityDate(string UserName)
{
string domainAndUserName = String.Format(@"LDAP://aa.mycompany.com/CN={0},OU=CLIENT_PROD,OU=clients.mycompany.com,DC=aa,DC=mycompany,DC=com", UserName);
string OUAdminUserName = "abc";
string OUAdminPassword = "xyz";
AuthenticationTypes at = AuthenticationTypes.Secure;
DateTime lastActivityDate;
string returnvalue;
long lastLogonDateAsLong;
using (DirectoryEntry entryUser = new DirectoryEntry(domainAndUserName, OUAdminUserName, OUAdminPassword, at))
using (DirectorySearcher mysearcher = new DirectorySearcher(entryUser))
try
{
using (SearchResultCollection results = mysearcher.FindAll())
{
if (results.Count >= 1)
{
DirectoryEntry de = results[0].GetDirectoryEntry();
lastLogonDateAsLong = GetInt64(de, "lastLogon");
try
{
if (lastLogonDateAsLong != -1)
{
lastActivityDate = DateTime.FromFileTime(lastLogonDateAsLong);
returnvalue = lastActivityDate.ToString();
}
else
{
returnvalue = "-Not available-";
}
}
catch (System.ArgumentOutOfRangeException aore)
{
returnvalue = "Not available";
}
}
else
{
returnvalue = string.Empty;
}
}
}
catch (System.DirectoryServices.DirectoryServicesCOMException dsce)
{
returnvalue = "- Not available -";
}
return returnvalue;
}
谢谢。
编辑:
private static Int64 GetInt64(DirectoryEntry entry, string attr)
{
DirectorySearcher ds = new DirectorySearcher(
entry,
String.Format("({0}=*)", attr),
new string[] { attr },
SearchScope.Base
);
SearchResult sr = ds.FindOne();
if (sr != null)
{
if (sr.Properties.Contains(attr))
{
return (Int64)sr.Properties[attr][0];
}
}
return -1;
}
忘记提及,AD模式,结构等在两个服务器中看起来完全相同。
答案 0 :(得分:3)
查看此帖子 http://www.codeproject.com/Articles/19181/Find-LastLogon-Across-All-Windows-Domain-Controlle
我有同样的问题,但只针对一个域名, 我通过使用以下代码解决了它,但我正在检查所有用户的lastLogin
public static Dictionary<string, DateTime> UsersLastLogOnDate()
{
var lastLogins = new Dictionary<string, DateTime>();
DomainControllerCollection domains = Domain.GetCurrentDomain().DomainControllers;
foreach (DomainController controller in domains)
{
try
{
using (var directoryEntry = new DirectoryEntry(string.Format("LDAP://{0}", controller.Name)))
{
using (var searcher = new DirectorySearcher(directoryEntry))
{
searcher.PageSize = 1000;
searcher.Filter = "(&(objectClass=user)(!objectClass=computer))";
searcher.PropertiesToLoad.AddRange(new[] { "distinguishedName", "lastLogon" });
foreach (SearchResult searchResult in searcher.FindAll())
{
if (searchResult.Properties.Contains("lastLogon"))
{
var lastLogOn = DateTime.FromFileTime((long)searchResult.Properties["lastLogon"][0]);
var username = Parser.ParseLdapAttrValue(searchResult.Properties["distinguishedName"][0].ToString());
if (lastLogins.ContainsKey(username))
{
if (DateTime.Compare(lastLogOn, lastLogins[username]) > 0)
{
lastLogins[username] = lastLogOn;
}
}
else
{
lastLogins.Add(username, lastLogOn);
}
}
}
}
}
}
catch (System.Runtime.InteropServices.COMException comException)
{
// Domain controller is down or not responding
Log.DebugFormat("Domain controller {0} is not responding.",controller.Name);
Log.Error("Error in one of the domain controllers.", comException);
continue;
}
}
return lastLogins;
}
在代码之上,您可以使用以下内容获取林中的所有域。
Forest currentForest = Forest.GetCurrentForest();
DomainCollection domains = currentForest.Domains;
foreach(Domain domain in domains)
{
// check code above
}
答案 1 :(得分:1)
可能有一种更简单的方法?实际上有另一个属性lastLogonTimestamp,我认为它添加了2003域级别,试图在最后一次登录的域中保持单个一致的值。唉,它有一个奇怪的复制时间模式,可能会有两个星期过时。