none
Help with Get-Aduser Properties with useraccountcontrol

    Question

  • Hello All,

    I'm trying to get specific ad values from a list of users. Everything works except for the useraccountcontrol. Does anyone know how I can convert useraccountcontrol  to the flags instead of the numbers?

    The code I have below

    Get-ADUser $users -Properties * | Select-Object employeeid, name, displayname, samaccountname, mail, PasswordExpired, @{N = "AccountExpires"; E = {[DateTime]::FromFileTime($_.AccountExpires)}}, useraccountcontrol | Export-CSV -Path C:\users\users\desktop\users.csv -NoTypeInformation

    Thanks in advance!


    • Edited by zv825 Tuesday, December 12, 2017 6:55 PM edit title
    Tuesday, December 12, 2017 6:55 PM

Answers

  • Finish populating the table with the values, then this should parse the hash table.

    $flags = @{
        1 = "SCRIPT"
        2 = "ACCOUNTDISABLE"
        8 = "HOMEDIR_REQUIRED"
        16 = "LOCKOUT"
        32 = "PASSWD_NOTREQD"
        64 = "PASSWD_CANT_CHANGE"
        128 = "ENCRYPTED_TEXT_PWD_ALLOWED"
    }
    
    Get-ADUser $users -Properties * | 
        Select-Object employeeid, name, displayname, samaccountname, mail, PasswordExpired, @{N = "AccountExpires"; E = {[DateTime]::FromFileTime($_.AccountExpires)}}, @{N = "UserAccountControl";E = {$flags.Get_Item($_.UserAccountControl)}} | 
        Export-CSV -Path C:\users\users\desktop\users.csv -NoTypeInformation



    Jeremy Corbello | https://www.jeremycorbello.com

    • Marked as answer by zv825 Tuesday, December 12, 2017 10:36 PM
    Tuesday, December 12, 2017 9:10 PM
  • Does anyone know how I can query the table of flags?

    Thanks!

    Why?  Richard has shown you how to get the flags with Get-AdUser.  What flags are you not seeing?

    Here is how to get the flags you are looking for:

    $props = 'employeeid', 'name', 'Enabled', 'displayname', 'samaccountname', 'mail', 'PasswordExpired', 'AccountExpirationDate'
    Get-ADUser jsmith -Properties $props | 
        Select-Object $props

    Which produces this output:

    employeeid            : 12345
    name                  : jsmith
    Enabled               : False
    displayname           : johnny Smith
    samaccountname        : JSmith
    mail                  : John Smith<jsmith@kahlnet.local>
    PasswordExpired       : False
    AccountExpirationDate : 10/2/2017 12:00:00 AM
    


    \_(ツ)_/


    • Edited by jrvModerator Tuesday, December 12, 2017 9:15 PM
    • Marked as answer by jrvModerator Tuesday, December 12, 2017 10:38 PM
    Tuesday, December 12, 2017 9:15 PM
    Moderator

All replies

  • You'll need to populate a table with the the values of the flags, then query your users against that table:

    $flags = @{
        1 = "SCRIPT"
        2 = "ACCOUNTDISABLE"
        8 = "HOMEDIR_REQUIRED"
        16 = "LOCKOUT"
        32 = "PASSWD_NOTREQD"
        64 = "PASSWD_CANT_CHANGE"
        128 = "ENCRYPTED_TEXT_PWD_ALLOWED"
    }
    I only populated up to 128, just keep going from this article: https://support.microsoft.com/en-us/help/305144/how-to-use-the-useraccountcontrol-flags-to-manipulate-user-account-pro


    Jeremy Corbello | https://www.jeremycorbello.com

    Tuesday, December 12, 2017 7:04 PM
  • Isthere a way to have it populate when its exported to a CSV instead of querying it? How do I query it within the command I made?

    Thanks!


    • Edited by zv825 Tuesday, December 12, 2017 7:21 PM edit
    Tuesday, December 12, 2017 7:08 PM
  • Just about all the flags defined by the userAccountControl attribute for users are retrieved using properties exposed by the Get-ADUser cmdlet. For example, the Enabled property tests whether or not bit 2 of the integer value of userAccountControl is set, indicating whether or not the account is enabled. See this documentation of the properties exposed by Get-ADUser, and how PowerShell determines the value:

    https://social.technet.microsoft.com/wiki/contents/articles/12037.active-directory-get-aduser-default-and-extended-properties.aspx

    For example the Enabled property is based on userAccountControl and the bit mask 2. Other properties based on userAccountControl are AllowReversiblePasswordEncryption, AccountNotDelegated, DoesNotRequirePreAuth, HomedirRequired, MNSLogonAccount, PasswordNeverExpires, PasswordNotRequired, SmartcardLogonRequired, TrustedForDelegation, TrustedToAuthForDelegation, and UseDESKeyOnly.

    Edit: These properties are actually documented in the help for Set-ADUser, not in the help for Get-ADUser.


    Richard Mueller - MVP Enterprise Mobility (Identity and Access)



    Tuesday, December 12, 2017 7:44 PM
  • Does anyone know how I can query the table of flags?

    Thanks!

    Tuesday, December 12, 2017 9:05 PM
  • Finish populating the table with the values, then this should parse the hash table.

    $flags = @{
        1 = "SCRIPT"
        2 = "ACCOUNTDISABLE"
        8 = "HOMEDIR_REQUIRED"
        16 = "LOCKOUT"
        32 = "PASSWD_NOTREQD"
        64 = "PASSWD_CANT_CHANGE"
        128 = "ENCRYPTED_TEXT_PWD_ALLOWED"
    }
    
    Get-ADUser $users -Properties * | 
        Select-Object employeeid, name, displayname, samaccountname, mail, PasswordExpired, @{N = "AccountExpires"; E = {[DateTime]::FromFileTime($_.AccountExpires)}}, @{N = "UserAccountControl";E = {$flags.Get_Item($_.UserAccountControl)}} | 
        Export-CSV -Path C:\users\users\desktop\users.csv -NoTypeInformation



    Jeremy Corbello | https://www.jeremycorbello.com

    • Marked as answer by zv825 Tuesday, December 12, 2017 10:36 PM
    Tuesday, December 12, 2017 9:10 PM
  • Does anyone know how I can query the table of flags?

    Thanks!

    Why?  Richard has shown you how to get the flags with Get-AdUser.  What flags are you not seeing?

    Here is how to get the flags you are looking for:

    $props = 'employeeid', 'name', 'Enabled', 'displayname', 'samaccountname', 'mail', 'PasswordExpired', 'AccountExpirationDate'
    Get-ADUser jsmith -Properties $props | 
        Select-Object $props

    Which produces this output:

    employeeid            : 12345
    name                  : jsmith
    Enabled               : False
    displayname           : johnny Smith
    samaccountname        : JSmith
    mail                  : John Smith<jsmith@kahlnet.local>
    PasswordExpired       : False
    AccountExpirationDate : 10/2/2017 12:00:00 AM
    


    \_(ツ)_/


    • Edited by jrvModerator Tuesday, December 12, 2017 9:15 PM
    • Marked as answer by jrvModerator Tuesday, December 12, 2017 10:38 PM
    Tuesday, December 12, 2017 9:15 PM
    Moderator
  • Finish populating the table with the values, then this should parse the hash table.

    $flags = @{
        1 = "SCRIPT"
        2 = "ACCOUNTDISABLE"
        8 = "HOMEDIR_REQUIRED"
        16 = "LOCKOUT"
        32 = "PASSWD_NOTREQD"
        64 = "PASSWD_CANT_CHANGE"
        128 = "ENCRYPTED_TEXT_PWD_ALLOWED"
    }
    
    Get-ADUser $users -Properties * | 
        Select-Object employeeid, name, displayname, samaccountname, mail, PasswordExpired, @{N = "AccountExpires"; E = {[DateTime]::FromFileTime($_.AccountExpires)}}, @{N = "UserAccountControl";E = {$flags.Get_Item($_.UserAccountControl)}} | 
        Export-CSV -Path C:\users\users\desktop\users.csv -NoTypeInformation



    Jeremy Corbello | https://www.jeremycorbello.com

    Unfortunately, as well as being unnecessary, that won't work as it can only get a simple vale and Userflags is a bitfield.


    \_(ツ)_/

    Tuesday, December 12, 2017 9:51 PM
    Moderator
  • You're absolutely correct, that will not work. Richard gave the proper answer.

    Jeremy Corbello | https://www.jeremycorbello.com

    Tuesday, December 12, 2017 9:56 PM
  • Thank you all. What I was looking for was this

    {$flags.Get_Item($_.UserAccountControl)}}

    Thanks Jeremy!

    Tuesday, December 12, 2017 10:37 PM
  • Thank you all. What I was looking for was this

    {$flags.Get_Item($_.UserAccountControl)}}

    Thanks Jeremy!

    Except that it doesn't work.  That cannot correctly decode UAC bitfields.


    \_(ツ)_/

    Tuesday, December 12, 2017 10:39 PM
    Moderator
  • Yeah, that's not going to work properly. Use Richard's post, mine was incorrect and will only work of 1 of the properties are set at a time - which won't be the case in most cases. 

    Get-ADUser has all of the properties given already, so do what jrv showed above:

    $props = 'employeeid', 'name', 'Enabled', 'displayname', 'samaccountname', 'mail', 'PasswordExpired', 'AccountExpirationDate'
    Get-ADUser jsmith -Properties $props | 
        Select-Object $props


    Jeremy Corbello | https://www.jeremycorbello.com

    Tuesday, December 12, 2017 10:53 PM
  • Here is one of the most common flag fields for user accounts -  514.  If you run this compound field you will get nothing.

    $flags = @{
        1 = "SCRIPT"
        2 = "ACCOUNTDISABLE"
        8 = "HOMEDIR_REQUIRED"
        16 = "LOCKOUT"
        32 = "PASSWD_NOTREQD"
        64 = "PASSWD_CANT_CHANGE"
        128 = "ENCRYPTED_TEXT_PWD_ALLOWED"
    }
    $flags.Get_item(514)

    Try it.

    It is a compound field made up or 512 and 2 which is "NormalAccount" and "AccountDisabled".  With Get-AdUser this is "Enabled = $false"  and all user accounts are 512 as a base.

    To test flags we can only use "-band" to isolate the bit and see if it is set,

    [bool](514 -band 2)

    This will return true if the bit is set. This is the only way to test bits.  Using flags would never return this value as it can be hidden in almost any bitfield.

    2 + 8 + 16 + 512

    The "2" bit is set but it cannot be matched with the $flags method.

    Also we don't need "get-Item".

    $flags[2]

    or

    [bool]$flags[2]

    We cannot use $_.useraccountcontrol.


    \_(ツ)_/

    Tuesday, December 12, 2017 10:53 PM
    Moderator
  • It's working how I need it to work. Most of the accounts come back with 512 and 514.

    When I export it and open it in Excel its showing up with the correct flags instead of the hexadecimal number.

    Thanks again!

    Tuesday, December 12, 2017 10:54 PM
  • Ok, as long as you understand that the solution is very limited in scope and is not an actual answer for most of the users out there.

    Jeremy Corbello | https://www.jeremycorbello.com

    Tuesday, December 12, 2017 10:56 PM
  • Why do you refuse to use the provided "Enabled" flag.  It will always be right. You method may be right one but can change at any time.  There are many flags that get set and unset dynamically.  Any one will cause your choice to fail.

    Why do new non-technical users always get so stubborn about doing things the technically wrong way?


    \_(ツ)_/

    Tuesday, December 12, 2017 10:58 PM
    Moderator
  • Thank you for all your help. If I need to run this command more than once, I will go ahead and use the 'Enabled' flag.

    Wednesday, December 13, 2017 12:40 AM
  • This will decode an arbitrary code using the flags table defined in table as above.

    $user_uac= 530

    $flags.GetEnumerator() | ForEach-Object {
        if ([bool]([int]($_.key) -band $user_uac)) { $_ }
    }

    Name                           Value                                                           
    ----                           -----                                                           
    16                             LOCKOUT                                                         
    512                            NORMAL_ACCOUNT                                                  
    2                              ACCOUNTDISABLE      

    Thursday, July 12, 2018 7:57 PM
  • Easiest way to create a "Flags" enum which can decode a bitfield in one line:

    $code = @'
    using System;
    /// <summary>
    /// Flags that control the behavior of the user account.
    /// </summary>
    [Flags()]
    public enum UserAccountControl : int
    {
        /// <summary>
        /// The logon script is executed. 
        ///</summary>
        SCRIPT = 0x00000001,
    
        /// <summary>
        /// The user account is disabled. 
        ///</summary>
        ACCOUNTDISABLE = 0x00000002,
    
        /// <summary>
        /// The home directory is required. 
        ///</summary>
        HOMEDIR_REQUIRED = 0x00000008,
    
        /// <summary>
        /// The account is currently locked out. 
        ///</summary>
        LOCKOUT = 0x00000010,
    
        /// <summary>
        /// No password is required. 
        ///</summary>
        PASSWD_NOTREQD = 0x00000020,
    
        /// <summary>
        /// The user cannot change the password. 
        ///</summary>
        /// <remarks>
        /// Note:  You cannot assign the permission settings of PASSWD_CANT_CHANGE by directly modifying the UserAccountControl attribute. 
        /// For more information and a code example that shows how to prevent a user from changing the password, see User Cannot Change Password.
        // </remarks>
        PASSWD_CANT_CHANGE = 0x00000040,
    
        /// <summary>
        /// The user can send an encrypted password. 
        ///</summary>
        ENCRYPTED_TEXT_PASSWORD_ALLOWED = 0x00000080,
    
        /// <summary>
        /// This is an account for users whose primary account is in another domain. This account provides user access to this domain, but not 
        /// to any domain that trusts this domain. Also known as a local user account. 
        ///</summary>
        TEMP_DUPLICATE_ACCOUNT = 0x00000100,
    
        /// <summary>
        /// This is a default account type that represents a typical user. 
        ///</summary>
        NORMAL_ACCOUNT = 0x00000200,
    
        /// <summary>
        /// This is a permit to trust account for a system domain that trusts other domains. 
        ///</summary>
        INTERDOMAIN_TRUST_ACCOUNT = 0x00000800,
    
        /// <summary>
        /// This is a computer account for a computer that is a member of this domain. 
        ///</summary>
        WORKSTATION_TRUST_ACCOUNT = 0x00001000,
    
        /// <summary>
        /// This is a computer account for a system backup domain controller that is a member of this domain. 
        ///</summary>
        SERVER_TRUST_ACCOUNT = 0x00002000,
    
        /// <summary>
        /// Not used. 
        ///</summary>
        Unused1 = 0x00004000,
    
        /// <summary>
        /// Not used. 
        ///</summary>
        Unused2 = 0x00008000,
    
        /// <summary>
        /// The password for this account will never expire. 
        ///</summary>
        DONT_EXPIRE_PASSWD = 0x00010000,
    
        /// <summary>
        /// This is an MNS logon account. 
        ///</summary>
        MNS_LOGON_ACCOUNT = 0x00020000,
    
        /// <summary>
        /// The user must log on using a smart card. 
        ///</summary>
        SMARTCARD_REQUIRED = 0x00040000,
    
        /// <summary>
        /// The service account (user or computer account), under which a service runs, is trusted for Kerberos delegation. Any such service 
        /// can impersonate a client requesting the service. 
        ///</summary>
        TRUSTED_FOR_DELEGATION = 0x00080000,
    
        /// <summary>
        /// The security context of the user will not be delegated to a service even if the service account is set as trusted for Kerberos delegation. 
        ///</summary>
        NOT_DELEGATED = 0x00100000,
    
        /// <summary>
        /// Restrict this principal to use only Data Encryption Standard (DES) encryption types for keys. 
        ///</summary>
        USE_DES_KEY_ONLY = 0x00200000,
    
        /// <summary>
        /// This account does not require Kerberos pre-authentication for logon. 
        ///</summary>
        DONT_REQUIRE_PREAUTH = 0x00400000,
    
        /// <summary>
        /// The user password has expired. This flag is created by the system using data from the Pwd-Last-Set attribute and the domain policy. 
        ///</summary>
        PASSWORD_EXPIRED = 0x00800000,
    
        /// <summary>
        /// The account is enabled for delegation. This is a security-sensitive setting; accounts with this option enabled should be strictly 
        /// controlled. This setting enables a service running under the account to assume a client identity and authenticate as that user to 
        /// other remote servers on the network.
        ///</summary>
        TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 0x01000000,
    
        /// <summary>
        /// 
        /// </summary>
        PARTIAL_SECRETS_ACCOUNT = 0x04000000,
    
        /// <summary>
        /// 
        /// </summary>
        USE_AES_KEYS = 0x08000000
    }
    '@
    Add-Type $code
    #decode a UAC bitfield
    [UserAccountControl]512+2

    Example:

    PS D:\scripts> [UserAccountControl]530
    ACCOUNTDISABLE, LOCKOUT, NORMAL_ACCOUNT
    PS D:\scripts>

    Testing for a flag in the enume:

    PS D:\scripts> [UserAccountControl]530 -match [useraccountcontrol]::ACCOUNTDISABLE
    True
    PS D:\scripts>

    Short form:

    PS D:\scripts> [UserAccountControl]530 -match 'ACCOUNTDISABLE'
    True
    PS D:\scripts>


    \_(ツ)_/




    Thursday, July 12, 2018 8:23 PM
    Moderator