Monday, 24 September 2012

How to use PowerShell to search Active Directory

PowerShell 2.0 introduced 76 new CmdLets, including Get-ADUser which allow you to query Active Directory.
This was a great progress as the first release of PowerShell was miserably failing in providing a good interface with Active Directory which is unbelievable for a Microsoft product!
So now, Get-ADUser and many other CmdLets are available; great! Here are the details on Microsoft Website

Hang on a minute, there is a limitation to that, you need Windows 2008 R2 domain controllers...

If you can't upgrade your Windows Active Directory controllers to Windows Server 2008 R2, there is a workaround: you can install Active Directory Management Gateway Service on your Windows Server 2003 or 2008 domain controllers.

In the meantime, there are still options to query Active Directory using PowerShell via LDAP.

The script below will show you an easy way of doing it.

[string]$category = ""
[string]$name = ""
[string]$data = ""
[string]$attribute = ""
[string]$strFilter = "(&(objectCategory=" + $category + ")(" + $name + "=" + $data + "))"
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strFilter
$objSearcher.SearchScope = "Subtree"
$colResults = $objSearcher.FindAll()
$colResults | foreach {$_.Properties.Item("$attribute")}

Let's first have a look at the input variables:

  • $category is the category of object you're searching search in Active Directory (could be user, group, contact, groupPolicyContainer...)
  • $name is the name of the attribute you're using as a filter to find the object (could be displayName, sAMAccountName...)
  • $data is the value of the attibute you're using as a filter to find the object ("Joe Bloggs", ...)
  • $attribute is the attribute's value you want to read from Active Directory for all objects matching your criteria (givenName, telephoneNumber, department)

Once the parameters in place, you create a domain object ($objDomain) where the search will be conducted (no need to mention the domain, the one in use by the computer running the script will be automatically selected)
Then, you create a searcher object ($objSearcher) where you define all the settings of your search (domain where you do it, maximum number of object to return, filter to apply to your search and scope of your search)
Finally, you run the search by using the FindAll() which will return a collection of objects to $colResults.
The last line returns the result(s) of your search. The SearchResult collection will return objects with the Properties property which stores the data of your Active Directory objects. To read it, you just have to use the Item property with mentioning the attribute you want to read to get its value.

Once, you get it right, you can wrap it up in a function like:

function Get-AdsiData {
    [CmdletBinding()]
    param (
        [string]$category,
        [string]$name,
        [string]$data,
        [string]$attribute
    )
    $strFilter = "(&(objectCategory=" + $category + ")(" + $name + "=" + $data + "))"
    $objDomain = New-Object System.DirectoryServices.DirectoryEntry
    $objSearcher = New-Object System.DirectoryServices.DirectorySearcher
    $objSearcher.SearchRoot = $objDomain
    $objSearcher.PageSize = 1000
    $objSearcher.Filter = $strFilter
    $objSearcher.SearchScope = "Subtree"
    $colResults = $objSearcher.FindAll()
    return $colResults | foreach {$_.Properties.Item("$attribute")}
}

Read more on the DirectoryEntry object and the DirectorySearcher and the SearchResult objects...