在多个域服务器中搜索用户的lastLogon属性

本文关键字:用户 lastLogon 属性 搜索 服务器 | 更新日期: 2023-09-27 18:07:04

首先,请原谅我没有使用正确的术语。在我用错术语的地方纠正我。

目标是以编程方式检索给定用户名的lastLogon日期。

我们有我认为是森林的地方;两台AD服务器,如- adserver01.aa.mycompany.comadserver02.aa.mycompany.com

我用微软的浏览器从第三台机器连接到这些服务器来检查对象。在那里,我看到一些用户在adserver01中有lastLogon日期,但在adserver02中没有。例如,在adserver02中lastLogon的值是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架构,结构等,在两个服务器上看起来完全一样。

在多个域服务器中搜索用户的lastLogon属性

查看这篇文章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  
}  

是否有更简单的方法?实际上还有另一个属性lastLogonTimestamp,我认为与2003域级别一起添加,它试图在最后一次登录的域中保持单个一致的值。唉,它有一个奇怪的复制时间模式,可能会过期两周。