【问题标题】:Active Directory seems to return cached informationActive Directory 似乎返回缓存信息
【发布时间】:2014-02-25 19:28:50
【问题描述】:

我们有一个内部 Windows 控制台应用程序,用于更新我们的 Active Directory。这个应用已经成功运行了好几年了。

最近我的任务是添加代码以禁用超过 90 天未登录系统的用户。

代码似乎运行正常,只是每次应用运行时都会出现一些用户。

这里是搜索代码:

public SearchResultCollection SearchAD(string szSearchOU, string szSearchArg, string szObjectClass)
{
        if (szSearchOU == "")
        {
            ds.SearchRoot = c_DirectoryEntry;
        }
        else
        {
            if (!szSearchOU.StartsWith("LDAP://"))
            {
                szSearchOU = "LDAP://" + szSearchOU;
            }
            ds.SearchRoot = new DirectoryEntry(szSearchOU);
        }

        string szFilter = "";
        if (szObjectClass == "")
            szFilter = "(objectClass=user)";
        else
            szFilter = "(objectClass=" + szObjectClass + ")";
        if (szSearchArg != "")
        {
            if (szSearchArg.Substring(0, 3) != "CN=")
                szSearchArg = "CN=" + szSearchArg;
            szFilter = "(&" + szFilter + "(" + szSearchArg + "))";
        }
        else
            ds.PageSize = 1001;
        ds.Filter = szFilter;
        SearchResultCollection results = ds.FindAll();
        return results;
 }

此方法在整个应用程序中都使用,因此我有理由确定它可以正常工作。

这是调用搜索并处理它的存根:

SearchResultCollection src = SearchADUsers(szOU, "");
clsDisableLog.WriteLog("Processing: " + src.Count.ToString());
foreach (SearchResult r in src)
{
    DirectoryEntry deUser = r.GetDirectoryEntry();
    if (c_Debug)
        clsDisableLog.WriteLog("Processing: " + deUser.Name + " Path: " + deUser.Path.ToString());
    PropertyCollection userAttribs = deUser.Properties;
    int flags = (int)deUser.Properties["userAccountControl"].Value;
    if (!Convert.ToBoolean((flags & UF_DISABLED) == UF_DISABLED))
    {
        bool bDisableAccount = false;
        DateTime dLastLogon = GetLastLogon(deUser);
        if (dLastLogon != DateTime.MinValue)
        {
            TimeSpan diff = DateTime.Now - dLastLogon;
            int iDaysSince = diff.Days;
            if (iDaysSince > iDays)
            {
                clsDisableLog.WriteLog("\t" + deUser.Name);
                clsDisableLog.WriteLog("\t\t" + "Has not logged in for " + iDaysSince.ToString() + " days.");
                clsDisableLog.WriteLog("\t\t" + "Last logon date: " + dLastLogon.ToLongDateString() + " " + dLastLogon.ToLongTimeString());
                clsDisableLog.WriteLog("\t\t" + deUser.Path.ToString());
                bDisableAccount = true;
            }
        }
        else
        {
            clsDisableLog.WriteLog("\t" + deUser.Name);
            clsDisableLog.WriteLog("\t\t" + "Has never logged into domain.");
            clsDisableLog.WriteLog("\t\t" + "Created: " + deUser.Properties["whenCreated"].Value.ToString());
            clsDisableLog.WriteLog("\t\t" + deUser.Path.ToString());
            iAccountsNoLogin++;
        }
        if (bDisableAccount)
        {
            if (deUser.Path.Contains("UtilityAccounts"))
            {
                bDisableAccount = false;
                clsDisableLog.WriteLog("\t\t" + "NOT Disabling Utility Account: " + deUser.Name);
            }
            else
            {
                if (UpdateUserFlag(deUser, UF_DISABLED, true))
                {
                    clsDisableLog.WriteLog("\t\t" + "Disabled");
                    iAccountsDisabled++;
                }
                else
                    clsDisableLog.WriteLog("Error disabling " + deUser.Name);
                if (deUser.Path.ToString().ToLower() != deInactiveOU.Path.ToLower())
                {
                    if (MoveUser(deUser, deInactiveOU))
                    {
                        clsDisableLog.WriteLog("\t\t" + "Moved to: " + deInactiveOU.Name);
                        iAccountsMoved++;
                    }
                    else
                        clsDisableLog.WriteLog("Error moving " + deUser.Name + " to " + deInactiveOU.Name);
                }
            }
        }
    }

应用程序每次运行时都会处理大约 14 个帐户。

例子:

    2/25/2014 12:56:27 PM:  CN=XXXXXXXX
    2/25/2014 12:56:27 PM:      Has not logged in for 252 days.
    2/25/2014 12:56:27 PM:      Last logon date: Tuesday, June 18, 2013 10:14:45 AM
    2/25/2014 12:56:27 PM:      LDAP://CN=XXXXXXXX,OU=XXXX User Accounts,DC=XXXXXXXX,DC=LOCAL
    2/25/2014 12:56:27 PM:      Disabled
    2/25/2014 12:56:27 PM:      Moved to: OU=Inactive

应用程序运行后,此帐户 IS IN OU=Inactive 并已禁用;但是,如果我重新运行应用程序,用户会再次出现,就像这里一样!

有什么建议吗?

我已设置 DS.CacheResults = false 但是如果我这样做,循环将永远不会执行。

谢谢, 约翰

    public bool UpdateUserFlag(DirectoryEntry deUser, int iFlag, Boolean bSet)
    {
        bool bReturn = false;
        int flags = (int)deUser.Properties["userAccountControl"].Value;
        try
        {
            if (bSet)
                deUser.Properties["userAccountControl"].Value = flags ^ iFlag;
            else
                deUser.Properties["userAccountControl"].Value = flags & ~iFlag;
            deUser.CommitChanges();
            deUser.RefreshCache();
            bReturn = true;
        }
        catch (Exception ex)
        {
            clsLog.WriteLog("Error updating user flag: " + deUser.Name);
            clsLog.Write(ex.Message);
            clsLog.WriteLog("");
        }
        return bReturn;
    }
    public bool MoveUser(DirectoryEntry deUser, DirectoryEntry deOU)
    {
        bool bReturn = false;
        try
        {
            deUser.MoveTo(deOU);
            deUser.CommitChanges();
            deUser.RefreshCache();
            bReturn = true;
        }
        catch (Exception ex)
        {
            clsLog.WriteLog("Error moving: " + deUser.Name.ToString() + " to: " + deOU.Path);
            clsLog.WriteLog(ex.Message);
        }

        return bReturn;

    }
    public bool MoveUser(DirectoryEntry deUser, string szOU)
    {
        bool bReturn = false;
        try
        {
            deUser.MoveTo(new DirectoryEntry(szOU));
            deUser.CommitChanges();
            deUser.RefreshCache();
            bReturn = true;
        }
        catch (Exception ex)
        {
            clsLog.WriteLog("Error moving: " + deUser.Name.ToString() + " to: " + szOU);
            clsLog.WriteLog(ex.Message);
        }

        return bReturn;
    }

    public DateTime GetLastLogon(DirectoryEntry deUser)
    {
        DateTime dtLL = DateTime.MinValue;
        try
        {
            if (deUser.Properties["lastLogonTimeStamp"].Count != 0)
                dtLL = GetDateTimeFromLargeInteger((IADsLargeInteger)deUser.Properties["lastLogonTimeStamp"][0]);
        }
        catch (Exception ex)
        {
            clsLog.WriteLog("Error Retrieving Last Logon Time Stamp for: " + deUser.Name.ToString());
            clsLog.Write(ex.Message);
            clsLog.WriteLog("");
        }
        return dtLL;
    }

根据一个答案,我已经发布了存根中调用的方法的代码 - 尽管它们与问题无关,因为我已经确认它们在必要时起作用。帐户被禁用,它们被移动到相关的 OU。

问题不是代码没有做它应该做的事情 - 而是 AD 发现用户帐户没有被禁用并且不在 OU 中,即使我可以确认使用 Active Directory 用户和计算机。

约翰

【问题讨论】:

    标签: c# active-directory


    【解决方案1】:

    为什么要这样做?

    if (!Convert.ToBoolean((flags & UF_DISABLED) == UF_DISABLED))
    

    这已经是一个布尔值了:

    (flags & UF_DISABLED) == UF_DISABLED
    

    除此之外很难说,因为您的存根所做的只是调用您尚未发布代码的方法。

    您可能遇到的问题还与 lastlogin 活动目录属性是特定于域控制器的事实有关,它不会被复制,因此您必须检查域中的每个域控制器以查看上次登录日期是什么.

    【讨论】:

    • @John 不用客气,LastLogonTimeStamp 更糟糕的是,如果您使用默认域配置读取实时信息,它会滞后 9-14 天。见blogs.technet.com/b/askds/archive/2009/04/15/…
    • @John 检查UF_DISABLED 的值(应该是0x2)和int flags = (int)deUser.Properties["userAccountControl"].Value; 返回正确的值,因为给定您的输出结果,问题一定存在。
    • const int UF_DISABLED = 0x0002;根据blogs.technet.com/b/askds/archive/2009/04/15/… 的用途是: 预期用途 请注意,lastLogontimeStamp 属性的预期用途是帮助识别非活动计算机和用户帐户。 lastLogon 属性并非旨在提供实时登录信息。使用默认设置,lastLogontimeStamp 将比当前日期晚 9-14 天。 - 这就是我们尝试使用它的目的。
    • 另外,问题不在于帐户没有被删除或移动——这两种情况都在发生。此外,我们有超过 1600 个 AD 帐户,其中只有 14 个出现此症状。
    • 致投票给我的人:为什么。这是一个合法的问题,我反复用谷歌搜索它,结果为零。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-28
    相关资源
    最近更新 更多