如何确定用户账户是否已启用或禁用

77
我正在编写一个快速的 C# Windows Forms 应用程序来帮助解决重复的文书工作。
我已经在 AD 中搜索了所有用户帐户,并将它们添加到带有复选框的列表视图中。
我希望将 listviewitems 的默认检查状态设置为取决于帐户的启用/禁用状态。
string path = "LDAP://dc=example,dc=local";
DirectoryEntry directoryRoot = new DirectoryEntry(path);
DirectorySearcher searcher = new DirectorySearcher(directoryRoot,
    "(&(objectClass=User)(objectCategory=Person))");
SearchResultCollection results = searcher.FindAll();
foreach (SearchResult result in results)
{
    DirectoryEntry de = result.GetDirectoryEntry();
    ListViewItem lvi = new ListViewItem(
        (string)de.Properties["SAMAccountName"][0]);
    // lvi.Checked = (bool) de.Properties["AccountEnabled"]
    lvwUsers.Items.Add(lvi);
}

我正在努力寻找正确的属性来解析DirectoryEntry对象中帐户的状态。我已经搜索了AD用户属性,但没有找到有用的内容。

有人能提供任何指针吗?

5个回答

137

这段代码应该可以运行...

private bool IsActive(DirectoryEntry de)
{
  if (de.NativeGuid == null) return false;

  int flags = (int)de.Properties["userAccountControl"].Value;

  return !Convert.ToBoolean(flags & 0x0002);
}

27
你真快,但这里有一个关于所有标志含义的链接:http://msdn.microsoft.com/en-us/library/ms680832.aspx。 - Oliver
5
也许这个链接会补充奥利弗的“Flags”文章。 - Joze
2
如果 flags 为零,则会返回 true,这是不正确的 - 只是一个提示来处理这种情况。 - A_L
如果我返回的flags | 0x0002 == flags是true,那么表示禁用标志被设置。 - Sangman
我需要知道哪些账户已被禁用,以及是谁禁用了这些账户。 - Kiquenet
显示剩余3条评论

14

使用 System.DirectoryServices.AccountManagement:domainName 和 username 必须是域和用户名的字符串值。

using (var domainContext = new PrincipalContext(ContextType.Domain, domainName))
{
    using (var foundUser = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, username)) 
    {
        if (foundUser.Enabled.HasValue) 
        {
            return (bool)foundUser.Enabled;
        }
        else
        {
            return true; //or false depending what result you want in the case of Enabled being NULL
        }
    }
}

3
对我来说有效的是 ((UserPrincipal)foundUser).Enabled == true - Nathan Goings

12

虽然没有人询问,但这里提供一份Java版本的代码(因为我也在这里寻找过)。空值检查留给读者自行练习。

private Boolean isActive(SearchResult searchResult) {
    Attribute userAccountControlAttr = searchResult.getAttributes().get("UserAccountControl");
    Integer userAccountControlInt = new Integer((String) userAccoutControlAttr.get());
    Boolean disabled = BooleanUtils.toBooleanObject(userAccountControlInt & 0x0002);
    return !disabled;
}

点赞,因为你花时间分享了这个内容,因为标题不是特定的语言,这可能真的会帮助到某些人。 - allen1

3
你可以使用类似这样的代码:
    ADUserAccountControl flags;
    Enum.TryParse(de.Properties["userAccountControl"].Value.ToString(), out flags);

    if(flags.HasFlag(ADUserAccountControl.ACCOUNTDISABLE)
    {
        // account is disabled
    }

这是所有可能的标志的完整列表:
    /// <summary>
    /// Source: https://learn.microsoft.com/en-us/troubleshoot/windows-server/identity/useraccountcontrol-manipulate-account-properties
    /// </summary>
    public enum ADUserAccountControl : long
    {
        SCRIPT = 0x0001,
        ACCOUNTDISABLE = 0x0002,
        HOMEDIR_REQUIRED = 0x0008,
        LOCKOUT = 0x0010,
        PASSWD_NOTREQD = 0x0020,
        PASSWD_CANT_CHANGE = 0x0040,
        ENCRYPTED_TEXT_PWD_ALLOWED = 0x0080,
        TEMP_DUPLICATE_ACCOUNT = 0x0100,
        NORMAL_ACCOUNT = 0x0200,
        INTERDOMAIN_TRUST_ACCOUNT = 0x0800,
        WORKSTATION_TRUST_ACCOUNT = 0x1000,
        SERVER_TRUST_ACCOUNT = 0x2000,
        DONT_EXPIRE_PASSWORD = 0x10000,
        MNS_LOGON_ACCOUNT = 0x20000,
        SMARTCARD_REQUIRED = 0x40000,
        TRUSTED_FOR_DELEGATION = 0x80000,
        NOT_DELEGATED = 0x100000,
        USE_DES_KEY_ONLY = 0x200000,
        DONT_REQ_PREAUTH = 0x400000,
        PASSWORD_EXPIRED = 0x800000,
        TRUSTED_TO_AUTH_FOR_DELEGATION = 0x1000000,
        PARTIAL_SECRETS_ACCOUNT = 0x04000000,
    }

1
我建议使用FlagsAttribute来装饰枚举:[Flags] public enum ADUserAccountControl - undefined
你说得对,谢谢!已经进行了修改。 - undefined

-1

我来到这里寻找答案,但它只适用于DirectoryEntry。因此,这里有一个可以用于SearchResult/SearchResultCollection的代码,供那些遇到同样问题的人使用:

private bool checkIfActive(SearchResult sr)
{
    var vaPropertiy = sr.Properties["userAccountControl"];

    if (vaPropertiy.Count > 0) 
    {
        if (vaPropertiy[0].ToString() == "512" || vaPropertiy[0].ToString() == "66048") 
        {
            return true;
        } 
        
        return false;
    }

    return false;
}

不是每种情况都适用。还有很多其他标志可以同时设置。您必须使用“HasFlag(..)”检查标志。 - marsh-wiggle
作为信息,SearchResult具有GetDirectoryEntry()方法。 - Qben

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接