2

How can I get these properties for a user via ADSI LDAP, these are the properties from Get-ADUser, I need the equivalent for ADSI.

  • Enabled
  • PasswordNeverExpires
  • PasswordExpired
  • Name
  • SamAccountName
  • Mail
  • PasswordLastSet

My objective is to query the entire domain for all users and get these attributes.

I tried with the Get-ADUser cmdlet and it timed out when querying for the users.

Get-ADUser -Filter * -Properties enabled,PasswordNeverExpires,passwordexpired,Name,SamAccountName,mail,passwordla‌​stset -server sc |
   where {$_.Enabled -eq "True"} |
   where { $_.PasswordNeverExpires -eq $false } |
   where { $_.passwordexpired -eq $false } |
   Select Name,SamAccountName,mail,
          @{l='PasswordExpires';e={$_.passwordlastset+(Get-ADDefa‌​ultDomainPasswordPolicy).MaxPasswordAge}},
          @{l='DaystoExpire';e={(New-TimeSpan -Start (get-date) -end ($_.passwordlastset+(Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge)).days}}

The above command works on a couple of users but if I query a large set of users it gives invalid enumeration context.

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
PowerShell
  • 1,991
  • 8
  • 35
  • 57

2 Answers2

8

The properties SamAccountName, Name, and Mail correspond to AD attributes of the same name. PasswordLastSet is derived from the attribute pwdLastSet. The other 3 properties (Enabled, PasswordNeverExpires, and PasswordExpired) are flags in the userAccountControl attribute.

Use an adsisearcher object with an LDAP query to search AD for user objects, then build custom objects with the desired properties:

$ACCOUNTDISABLE       = 0x000002
$DONT_EXPIRE_PASSWORD = 0x010000
$PASSWORD_EXPIRED     = 0x800000

$searcher = [adsisearcher]"(&(objectClass=user)(objectCategory=person))"
$searcher.FindAll() | % {
  $user = [adsi]$_.Properties.adspath[0]
  New-Object -Type PSCustomObject -Property @{
    SamAccountName       = $user.sAMAccountName[0]
    Name                 = $user.name[0]
    Mail                 = $user.mail[0]
    PasswordLastSet      = [DateTime]::FromFileTime($_.Properties.pwdlastset[0])
    Enabled              = -not [bool]($user.userAccountControl[0] -band
                           $ACCOUNTDISABLE)
    PasswordNeverExpires = [bool]($user.userAccountControl[0] -band
                           $DONT_EXPIRE_PASSWORD)
    PasswordExpired      = [bool]($user.userAccountControl[0] -band
                           $PASSWORD_EXPIRED)
  }
}

With that said, why do you want to go to all this trouble instead of simply using Get-ADUser to the same end?

Import-Module ActiveDirectory

$attributes = 'SamAccountName', 'Name', 'Mail', 'PasswordLastSet', 'Enabled',
              'PasswordNeverExpires', 'PasswordExpired'

Get-ADUser -Filter * -Properties $attributes | select $attributes
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
2

You can use Get-Item over the AD:\ Powershell drive, this cmdlet accepts the -properties argument to retrieve the designated list of properties. Using an asterisk causes the cmdlet to retrieve all properties. An example:

get-aduser -filter "sAMAccountName -like '*'" | % { get-item "AD:\$($_.distinguishedName)" -properties enabled,PasswordNeverExpires,passwordexpired,Name,SamAccountName,mail,passwordlastset }

EDIT: For calculated properties, including "Enabled", "Password never expires" etc, Get-ADUser can also accept -properties argument, so the code is just this:

get-aduser -filter "sAMAccountName -like '*'" -properties enabled,PasswordNeverExpires,passwordexpired,Name,SamAccountName,mail,passwordlastset

An asterisk also works fine.

Vesper
  • 18,599
  • 6
  • 39
  • 61
  • i am actually getting this error "Get-ADUser : The server has returned the following error: invalid enumeration context." as i have more than 20k users to query – PowerShell Jun 08 '15 at 13:51
  • 1
    Pretty sure you at least need to provide a `-filter` for `Get-ADUser` – Matt Jun 08 '15 at 13:56
  • Get-Aduser -filter * -properties enabled,PasswordNeverExpires,passwordexpired,Name,SamAccountName,mail,passwordlastset -server sc | where {$_.Enabled -eq "True"} | where { $_.PasswordNeverExpires -eq $false } | where { $_.passwordexpired -eq $false } | Select Name,SamAccountName,mail,@{l='PasswordExpires';e={$_.passwordlastset+(Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge}},@{l='DaystoExpire';e={(New-TimeSpan -Start (get-date) -end ($_.passwordlastset+(Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge)).days}} – PowerShell Jun 08 '15 at 13:57
  • this is what i tried, it works on a couple of users but if i query a large set of users it gives invalid enumeration context – PowerShell Jun 08 '15 at 13:58
  • @PowerShell Weird, while there is about 5k users in here, there was no error and the default page size is 1000, less than both these values. Check updated post though. – Vesper Jun 08 '15 at 14:09
  • 1
    @PowerShell You can use `-filter "PasswordNeverExpires -eq 'false' -and Enabled -eq 'True'"` as a filter to reduce the number of where-filtering at the very least. Also, you're calling `Get-ADDefa‌​ultDomainPasswordPolicy` once (EDIT: TWICE!) per user, you should cache this output prior to running such a query. – Vesper Jun 08 '15 at 14:10
  • you rock!! @vesper this thing "Get-Aduser -filter "PasswordNeverExpires -eq 'false' -and Enabled -eq 'True' -and passwordexpired -eq 'false'" -ResultPageSize 1000 -properties enabled,PasswordNeverExpires,passwordexpired,Name,SamAccountName,mail,passwordlastset -server sc | Select Name,SamAccountName,mail,@{l='PasswordExpires';e={$_.passwordlastset+$dpp}},@{l='DaystoExpire';e={(New-TimeSpan -Start (get-date) -end ($_.passwordlastset+$dpp)).days}}" ran in seconds :) – PowerShell Jun 08 '15 at 14:26
  • ok one more thing, how can i find ones with blank employee numbers ?? – PowerShell Jun 08 '15 at 14:35
  • This depends on what is the attribute with "employee numbers". Is it plain `phone` or `otherTelephone`, or is it located elsewhere? You can query a single-valued attribute against `-ne ''`, with multivalued attributes it's a tad more difficult. – Vesper Jun 08 '15 at 14:39
  • Hi Vesper, how can we get properties for a given list of specific users? (may be in a .txt file) – Satheesh Panduga Jul 14 '16 at 15:43
  • @SathishPanduga Load the txt into an array, and filter by `{$array -contains $user.samaccountname}`, should do. – Vesper Jul 15 '16 at 04:17