77

I am throwing together a quick C# win forms app to help resolve a repetitive clerical job.

I have performed a search in AD for all user accounts and am adding them to a list view with check boxes.

I would like to default the listviewitems' default check state to depend upon the enabled/disabled state of the account.

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);
}

I'm struggling to find the right attribute to parse to get the state of the account from the DirectoryEntry object. I've searched for AD User attributes, but not found anything useful.

Can anyone offer any pointers?

Bryan
  • 3,224
  • 9
  • 41
  • 58

5 Answers5

136

this code here should work...

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

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

  return !Convert.ToBoolean(flags & 0x0002);
}
musefan
  • 47,875
  • 21
  • 135
  • 185
Dimi Takis
  • 4,924
  • 3
  • 29
  • 41
  • 27
    Damn, you're faster, but here is a link about what all the flags are meaning: http://msdn.microsoft.com/en-us/library/ms680832.aspx – Oliver Jan 05 '10 at 11:47
  • 5
    Maybe this link will complement Oliver's **[Flags](http://support.microsoft.com/kb/305144/en-us)** – Jose Luis Feb 01 '12 at 07:30
  • 2
    If flags is zero then this will return true which is incorrect - just a note to handle this case. – A_L Aug 17 '15 at 11:22
  • the convert.toboolean is not very readable. better use return (flags & 2) = 0 – Bernhard Nov 21 '16 at 13:23
  • I did return flags | 0x0002 == flags. If this returns true then the disabled flag is set. – Sangman Oct 10 '19 at 12:49
  • I need to know when have certain accounts been disabled And who disables the account. – Kiquenet Mar 31 '21 at 12:55
  • what is the name of the `userAccountControl` attribute for OpenLDAP? – Varsh Apr 13 '23 at 03:30
  • @Varsh `userAccountControl` is a property bound to a directory entry which normally belongs to `objectClass=user` => so you would use a filter on the DirectorySearcher like `(&(objectClass=user)(sAMAccountName=some_NAME))` – Dimi Takis Apr 18 '23 at 14:51
14

Using System.DirectoryServices.AccountManagement: domainName and username must be the string values of the domain and 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
        }
    }
}
Michelle
  • 161
  • 1
  • 6
12

Not that anyone asked, but here's a java version (since I ended up here looking for one). Null checking is left as an exercise for the reader.

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;
}
user3006472
  • 121
  • 1
  • 4
  • Upvote for taking the time to share because the title isn't language specific and this might really help someone. – allen1 Jun 26 '15 at 17:54
2

You can use something like this:

    ADUserAccountControl flags;
    Enum.TryParse(de.Properties["userAccountControl"].Value.ToString(), out flags);

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

Here is a complete list of all possible flags:

    /// <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,
    }
marsh-wiggle
  • 2,508
  • 3
  • 35
  • 52
-1

I came here looking for an answer, but it was only for DirectoryEntry. So here is a code that works for SearchResult / SearchResultCollection, for people who had the same problem:

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;
}
Anouar
  • 2,050
  • 1
  • 15
  • 25