0

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

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

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

我使用 Microsoft 的 ADExplorer 从第三台机器连接到这些服务器以检查对象。在那里,我看到一些用户的 lastLogon 日期在 中可用adserver01,但在adserver02. 例如,lastLogon 的值为 0x0 in,而对于某些用户adserver02来说它是有效的日期。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 架构、结构等看起来完全一样。

4

2 回答 2

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  
}  
于 2013-04-04T14:32:59.203 回答
1

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

于 2013-04-04T13:10:29.703 回答