Get-Member for Get-ADUser does not always return all properties (PowerShell ISE)

I had an issue where I was missing a column in Out-Gridview from a Get-ADUser set.

After examining the problem it turns out that when you do a Get-ADUser and pipe the results to Get-Member or Out-GridView, only the first record will be examined to find the properties.

This means that if the first record does not have a mail address, which means no mail property, the Out-GridView/GM will not show this column. This goes for any property!!!

There was an item about this in the forum, but with no clear answer: https://powershell.org/forums/topic/get-aduser-all-properties-issue-lockedout-property-is-missing/

In our organization the first records in AD are service account and do not contain a mail address, so when you look at the result, you will see the column mail is missing in the Get-Member list even though I request it explicitly.

PS H:\> $Empty = Get-ADUser -Filter * -Properties mail | Select-Object -First 50

PS H:\> $Empty | Get-Member

TypeName: Microsoft.ActiveDirectory.Management.ADUser

Name MemberType Definition 
---- ---------- ---------- 
Contains Method bool Contains(string propertyName) 
Equals Method bool Equals(System.Object obj) 
GetEnumerator Method System.Collections.IDictionaryEnumerator GetEnumerator() 
GetHashCode Method int GetHashCode() 
GetType Method type GetType() 
ToString Method string ToString() 
Item ParameterizedProperty Microsoft.ActiveDirectory.Management.ADPropertyValueCollection Item(string propertyName) {get;} 
DistinguishedName Property System.String DistinguishedName {get;set;} 
Enabled Property System.Boolean Enabled {get;set;} 
GivenName Property System.String GivenName {get;set;} 
Name Property System.String Name {get;} 
ObjectClass Property System.String ObjectClass {get;set;} 
ObjectGUID Property System.Nullable----------
SamAccountName Property System.String SamAccountName {get;set;} 
SID Property System.Security.Principal.SecurityIdentifier SID {get;set;} 
Surname Property System.String Surname {get;set;} 
UserPrincipalName Property System.String UserPrincipalName {get;set;}

Now for the best part: When I “remind” the $Empty set that is does contain a property mail, it will remember.

Just doing a reference to the property is enough.

PS H:\> $Empty.Mail
.
.
.

Now we do the Get-Member again et voila, there is the mail property!!!

PS H:\> $Empty | Get-Member

TypeName: Microsoft.ActiveDirectory.Management.ADUser

Name MemberType Definition 
---- ---------- ---------- 
Contains Method bool Contains(string propertyName) 
Equals Method bool Equals(System.Object obj) 
GetEnumerator Method System.Collections.IDictionaryEnumerator GetEnumerator() 
GetHashCode Method int GetHashCode() 
GetType Method type GetType() 
ToString Method string ToString() 
Item ParameterizedProperty Microsoft.ActiveDirectory.Management.ADPropertyValueCollection Item(string propertyName) {get;} 
DistinguishedName Property System.String DistinguishedName {get;set;} 
Enabled Property System.Boolean Enabled {get;set;} 
GivenName Property System.String GivenName {get;set;} 
Mail Property System.String Mail {get;set;} 
Name Property System.String Name {get;} 
ObjectClass Property System.String ObjectClass {get;set;} 
ObjectGUID Property System.Nullable----------
SamAccountName Property System.String SamAccountName {get;set;} 
SID Property System.Security.Principal.SecurityIdentifier SID {get;set;} 
Surname Property System.String Surname {get;set;} 
UserPrincipalName Property System.String UserPrincipalName {get;set;}

I think this should be classified as a bug or at least undocumented feature…

In PowerShell this time with extensionattribute9, because that is empty, most of the time:

PS H:\> $Empty2 = Get-ADUser -Filter * -Properties extensionattribute9 | Select-Object -First 50
PS H:\> $empty2 | gm


TypeName: Microsoft.ActiveDirectory.Management.ADUser

Name MemberType Definition
---- ---------- ----------
Contains Method bool Contains(string propertyName)
Equals Method bool Equals(System.Object obj)
GetEnumerator Method System.Collections.IDictionaryEnumerator GetEnumerator()
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Item ParameterizedProperty Microsoft.ActiveDirectory.Management.ADPropertyValueCollection Item(string p...
DistinguishedName Property System.String DistinguishedName {get;set;}
Enabled Property System.Boolean Enabled {get;set;}
GivenName Property System.String GivenName {get;set;}
Name Property System.String Name {get;}
ObjectClass Property System.String ObjectClass {get;set;}
ObjectGUID Property System.Nullable`1[[System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, ...
SamAccountName Property System.String SamAccountName {get;set;}
SID Property System.Security.Principal.SecurityIdentifier SID {get;set;}
Surname Property System.String Surname {get;set;}
UserPrincipalName Property System.String UserPrincipalName {get;set;}


PS H:\> $empty2.extensionattribute9
PS H:\> $empty2 | gm


TypeName: Microsoft.ActiveDirectory.Management.ADUser

Name MemberType Definition
---- ---------- ----------
Contains Method bool Contains(string propertyName)
Equals Method bool Equals(System.Object obj)
GetEnumerator Method System.Collections.IDictionaryEnumerator GetEnumerator()
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Item ParameterizedProperty Microsoft.ActiveDirectory.Management.ADPropertyValueCollection Item(string...
DistinguishedName Property System.String DistinguishedName {get;set;}
Enabled Property System.Boolean Enabled {get;set;}
extensionattribute9 Property System.String extensionattribute9 {get;set;}
GivenName Property System.String GivenName {get;set;}
Name Property System.String Name {get;}
ObjectClass Property System.String ObjectClass {get;set;}
ObjectGUID Property System.Nullable`1[[System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral...
SamAccountName Property System.String SamAccountName {get;set;}
SID Property System.Security.Principal.SecurityIdentifier SID {get;set;}
Surname Property System.String Surname {get;set;}
UserPrincipalName Property System.String UserPrincipalName {get;set;}

The cmdlet Get-ADUser returns only a small subset of all possible attributes by default (please read the help for clarification). If you need more than that you have to specify the desired attributes with the parameter -Properties.

Edit:
If you want to make sure the output has a certain format you should use a Select-Object before the Out-GridView and specify what attributes you want to return.