查询来自特定AD DC的用户数据

时间:2015-05-19 07:33:31

标签: c# active-directory domaincontroller

我想查询AD中的某些用户属性,但是在C#中的特定DC上查询。 我们有几十个DC,我怀疑它们之间存在一些复制问题。我想清理未使用的帐户,我想使用上次登录时间属性,我想在所有DC上逐个查询(我知道这有点像暴力强迫,但我并不打算经常做这样的事情)所以我可以看看最近的价值是否是最新的。 我有代码来查询所有DC:

            Domain TestDomain = Domain.GetCurrentDomain();
            Console.WriteLine("Number of found DCs in the domain {0}", TestDomain.DomainControllers.Count);
            foreach (DomainController dc in TestDomain.DomainControllers)
            {
                Console.WriteLine("Name: " + dc.Name);
                ///DO STUFF
            }

我还找到了帮助构建可以从AD查询用户的代码:

    PrincipalContext context = new PrincipalContext(ContextType.Domain, "test.domain.com");
            string userName = "testusername";
            UserPrincipal user = UserPrincipal.FindByIdentity(context, userName);
            Console.WriteLine(user.LastLogon.Value.ToString());                
            Console.ReadKey();

在这里我卡住了。现在我想从所有DC获取用户的上次登录时间戳。 在过去,我已经删除了似乎很长时间未使用的意外帐户(只检查一个DC),结果用户每天都使用它,因此来自DC的信息未同步。 我知道最合理的行动是检查导致这种不正确的同步现象的原因,但是在我目前的状态可能需要很长时间而且可能在没有任何发现的情况下结束...... 提前感谢任何建设性的回应/评论!

2 个答案:

答案 0 :(得分:1)

虽然接受的答案是朝正确方向发展的好方法,但我发现它最终不会产生预期的结果:正如答案中所暗示的,“ lastLogon”未在控制器之间复制,而属性“ lastLogonTimeStamp” 被复制(但是,另一方面,它不能保证误入14天以上,参见this answer)。

现在,令人困惑的是,UserPrincipal.LastLogon不是指未复制但精确的“ lastLogon”,而是指复制但不精确的“ lastLogonTimeStamp”,我发现通过运行接受的答案中的代码,所有代码都产生{{ 1}}是对错。

相反,受this answer的启发,我发现为了找到具有给定sAMAccountName(可以轻松扩展以搜索所有用户)的用户的最新登录日期,我必须类似于以下内容:

DateTime

答案 1 :(得分:0)

编辑:重新阅读你的问题后,我意识到问题实际上是什么。您认为您有复制问题,因为用户的上次登录属性在所有域控制器上都不匹配?这是设计的!该属性是域控制器特定的,并且不是REPLICATED。要检查用户的真实上次登录时间,您必须始终查询每个域控制器以查找最新时间!

你快到了,试试这个:

public static List<UserPrincipal> GetInactiveUsers(TimeSpan inactivityTime)
{
    List<UserPrincipal> users = new List<UserPrincipal>();

    using (Domain domain = Domain.GetCurrentDomain())
    {
        foreach (DomainController domainController in domain.DomainControllers)
        {
            using (PrincipalContext context = new PrincipalContext(ContextType.Domain, domainController.Name))
            using (UserPrincipal userPrincipal = new UserPrincipal(context))
            using (PrincipalSearcher searcher = new PrincipalSearcher(userPrincipal))
            using (PrincipalSearchResult<Principal> results = searcher.FindAll())
            {
                users.AddRange(results.OfType<UserPrincipal>().Where(u => u.LastLogon.HasValue));
            }
        }
    }

    return users.Where(u1 => !users.Any(u2 => u2.UserPrincipalName == u1.UserPrincipalName && u2.LastLogon > u1.LastLogon))
        .Where(u => (DateTime.Now - u.LastLogon) >= inactivityTime).ToList();
}

它不会显示从未登录过的人。如果你需要,你可以搞清楚。