Tab completing LDAP attribute names inside Advanced Filters

In my previous post about Advanced filters I showed how to use Powershell variables to represent values inside filters. Example:

 PS D:\> $JohnSmith = Get-ADUser JohnSmith

PS D:\> Get-ADUser -Filter { manager -eq $JohnSmith.DistinguishedName }

## Gets all the user accounts whose manager is JohnSmith

What I didn’t tell you was Powershell variables could also be used to represent property names. Example:

 PS D:\> $SamAccountNameProperty = "SamAccountName"

PS D:\> Get-ADUser -Filter { $SamAccountNameProperty -eq "JohnSmith" }
 ## Gets a user whose samAccountName is JohnSmith

You may ask: what is so interesting about this feature?

Now imagine if you had a Powershell variable that has all the LDAP attribute names and AD Powershell object property names exposed as .NET properties, then you could use such a variable inside this filter. When you are interactively typing a filter string in a Powershell console, you would get tab completion support for these properties. What this means is you do not have to memorize the spelling of your favorite LDAP attributes anymore!

Say, for example, if you wrote a simple .NET class like the following:

 public class ADObjectProp

{

 public string ObjectGuid { get { return "objectGuid"; } }

 public string Name { get { return "name"; } }

 public string DistinguishedName { get { return "DistinguishedName"; } }

 public string ObjectClass { get { return "ObjectClass"; } }

}

Then you would be able to use a variable of type ADObjectProp inside the advanced filter. I call such variables: “query variables” .

 PS D:\> $queryADObject = new-object –type ADObjectProp

PS D:\> Get-ADObject -Filter { $queryADObject.Name -eq "JohnSmith" }

In the above example, if you hit <TAB> after “$queryAODbject.” then Powershell would cycle through all the properties. You can also use partial property name and names with wild card and Powershell would cycle through the best matches.

This is a great feature, especially for people who find it difficult to memorize all the LDAP attribute names and/or learn new property names exposed in AD Powershell object model. Now, the question is how to best create such .NET classes that would contain all the LDAP attributes defined in your schema? For this, we can leverage the Get-PossibleLdapAttributes function available in Active Directory Extensions and the Add-Type cmdlet available in core Powershell.

In Powershell you can dynamically create your own .NET class using the Add-Type cmdlet. Here is the Powershell command to create the ADObjectProp class (shown above):

 PS D:\> Add-Type -Name ADObjectProp -NameSpace "Microsoft.ActiveDirectoryExtensions" -MemberDefinition ' public string ObjectGuid { get { return "objectGuid"; } } public string Name { get { return "name"; } } public string DistinguishedName { get { return "DistinguishedName"; } } public string ObjectClass { get { return "ObjectClass"; } }' -PassThru

And you can initialize an object of the above class by typing:

 PS D:\> $xADObject = new-object –type Microsoft.ActiveDirectoryExtensions .ADObjectProp

I have modified the ActiveDirectoryExtensions script to create a bunch of query variables. The script adds all the extended properties for the given object type and then gets a list of possible LDAP attributes for the corresponding object class and populates the query variables.

To get a list of query variables created type:

 PS C:\> import-module ActiveDirectory

PS C:\> C:\ActiveDirectoryExtension.ps1
PS D:\> dir variable:xad*

Name Value

---- -----

xADObject Microsoft.ActiveDirectoryExtensions.ADObjectProp

xADPrincipal Microsoft.ActiveDirectoryExtensions.ADPrincipalProp

..

Here is a table that lists all the query variables created by the ActiveDirectoryExtensions script and a short description for each one of them:

$xADObject

Contains all extended properties of ADObject and LDAP attributes for top

$xADPrincipal

Contains all extended properties of ADPrincipal and LDAP attributes for top

$xADAccount

Contains all extended properties of ADAccount and LDAP attributes for top

$xADGroup

Contains all extended properties of ADGroup and LDAP attributes for group

$xADUser

Contains all extended properties of ADUser and LDAP attributes for user

$xADComputer

Contains all extended properties of ADComputer and LDAP attributes for computer

$xADOrganizationalUnit

Contains all extended properties of ADOrganizationalUnit and LDAP attributes for organizationalUnit

$xADFineGrainedPasswordPolicy

Contains all extended properties of ADFineGrainedPasswordPolicy and LDAP attributes for msDS-PasswordSettings

$xADServiceAccount

Contains all extended properties of ADServiceAccount and LDAP attributes for msDS-ManagedServiceAccount

$xADDomainController

Contains all extended properties of ADDomainController

Since the script now reads the schema when you load it, it will be a little slower.

Here are examples of how to use the query variables in your Powershell console:

 Get-ADObject -Filter { $xADUser.SamAccountName -eq "Administrator" }

## You can hit $xADUser.Sam<TAB> to tab-complete into $xADUser.SamAccountName

## Or $xADUser.*Account*<TAB> and cycle through the values to find SamAccountName

Get-ADObject -Filter { $xADUser.displayName -like "*Policy*" }

Get-ADObject -Filter { $xADObject.Name -eq "Administrator" }

There is one small caveat when using query variables to provide tab completion:

- Many LDAP attribute names defined in AD schema have a hyphen ‘-’ in them. Since .NET property names cannot have a hyphen, I have modified the script to convert hypens ‘-’into underscores ‘_’. Thus, for writing a filter using attribute “msDS-LastKnownRDN”, you would have to use $xADUser.msDS_LastKnownRDN.

Get-ADObject -filter { $xADObject.msDS_LastKnownRDN -like "*" } -IncludeDeletedObjects

Enjoy!

Swami

--

Swaminathan Pattabiraman

Developer – Active Directory Powershell Team

ActiveDirectoryExtension.ps1.txt