Share via


Searching the Active Directory with PowerShell

Hello world

It’s time for my second post and I thought I would talk about searching the active directory. I ran a PowerShell course yesterday and the delegates were itching to find out a bit more about searching an AD. So I said I would make sure I posted something on the blog.

 

So let’s get going! To start with I`m going to introduce a script that I would be lost without: “get-dn.ps1”. This script takes a SAM account name as input and returns the objects full CN as output. We can then use this output to then connect directly to the object. Here’s the code:

 

function get-dn ($SAMName)

{

      $root = [ADSI]''

      $searcher = new-object System.DirectoryServices.DirectorySearcher($root)

$searcher.filter = "(&(objectClass=user)(sAMAccountName= $SAMName))"

$user = $searcher.findall()

     

if ($user.count -gt 1)

      {

            $count = 0

            foreach($i in $user)

            {

                  write-host $count ": " $i.path

                  $count = $count + 1

            }

            $selection = Read-Host "Please select item: "

return $user[$selection].path

      }

      else

      {

            return $user[0].path

      }

}

$Name = $args[0]

$path = get-dn $Name

"'" + $path + "'" 

 

 

So now let’s look at this code in a bit more detail.

 

The first bit of the code simply creates a function to do most of the work. We take an argument in $SAMName that will hold the name of the account we wish to search for

 

function get-dn ($SAMName)

{

 

The next bit of code creates 2 objects. $root is a standard ADSI object that connects to the domain we are in. $searcher is a DirectorySearcher object, and we pass the ADSI object $root in as a constructor. Effectively we’re saying search the domain we’re in.

 

$root = [ADSI]''

$searcher = new-object System.DirectoryServices.DirectorySearcher($root)

 

 

Now we have created a DirectorySearcher object we need to set the search criteria. To do his we use the filter property of $searcher. See the LDAP Search Strings section below for more information. Once we have the criteria, we simply use the findall() method to find all instances that match the filter in the domain and return the results to $user

 

$searcher.filter = "(&(objectClass=user)(sAMAccountName= $SAMName))"

$user = $searcher.findall()

 

$user actually contains a collection of objects that match the search criteria. If we have more than one match, the collection has more than one element. This bit of code says “If we have more than 1 result, write all the results to screen and allow the user to select which object they mean”. The shrewd among you may think, “SAMAccountName is unique, we can’t have 2 of them”. You’re right however, we could implement wildcard searching, or searching by surname which might result in multiple matches making this really useful. Finally we return the path to the object. We return the object path because it includes the “LDAP://” which we would need to connect to the object directly.

 

 

if ($user.count -gt 1)

{

      $count = 0

      foreach($i in $user)

      {

            write-host $count ": " $i.path

            $count = $count + 1

      }

      $selection = Read-Host "Please select item: "

      return $user[$selection].path

}

 

 

The last bit of the if statement simply returns the path of the 1st element, if there is only 1 element in the collection. Then we finish of the function with a }.

 

else

      {

            return $user[0].path

      }

}

 

 

 

The final section simply assigns the passed in argument to the variable $Name. We then call the get-dn function passing in $Name, and put the result in $path. At the very end we wrap the path in a ‘ and ‘ so that you can then copy and paste the returned line straight into an [ADSI] constructor. (see the previous post)

 

$Name = $args[0]

$path = get-dn $Name

"'" + $path + "'" 

 

 

This function is really useful. Once I have got a hit I can use the output to quickly connect to an object in the Active Directory. I could for example type the following in PowerShell:

 

 

PS C:\store\ps scripts> .\get-dn.ps1 administrator

'LDAP://CN=Administrator,CN=Users,DC=umpadom,DC=com'

PS C:\store\ps scripts> $user = [ADSI] 'LDAP://CN=Administrator,CN=Users,DC=umpadom,DC=com'

PS C:\store\ps scripts> $user

distinguishedName

-----------------

{CN=Administrator,CN=Users,DC=umpadom,DC=com}

 

 

 

DirectorySearcher Object

 

For more information on the DirectorySearcher object check out MSDN here:

 

https://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemDirectoryServicesDirectorySearcherMembersTopic.asp

 

Some members of DirectorySearcher that you might want to look at in more detail are:

 

PageSize – this limits the amount of results that get returned, and can be really handy when you are searching big domains.

Filter – This is the search criteria that is used to search the Active Directory. It uses LDAP search strings. See the below section for more information

 

LDAP Search String’s

 

The DirectorySearcher filter property takes LDAP search strings. These strings use their own language. More information can be found here.

 

https://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemdirectoryservicesdirectorysearcherclassfiltertopic.asp

 

Basically, these are the four things to bear in mind when creating LDAP search strings.

1. The string must be enclosed in parentheses.

2. Expressions can use the relational operators: <, <=, =, >=, and >. An example is "(objectClass=user)". Another example is "(lastName>=Davis)".

3. Compound expressions are formed with the prefix operators & (and) and | (or). An example is"(&(objectClass=user)(lastName= Davis))". Another example is "(&(objectClass=printer)(|(building=42)(building=43)))".

4. Wildcards can be used. Use * operator

 

 

As ever, here are some examples. Below are some LDAP search strings that could be assigned to the DirectorySearcher.Filter property.

 

Find all users by explicit SAMName

 

"(&(objectClass=user)(sAMAccountName= $SAMName))"

 

 

 

Find all users where SAMName begins with xyz

 

"(&(objectClass=user)(sAMAccountName= $SAMName*))"

 

 

 

Find all users where Surname begins with xyz

 

 

"(&(objectClass=user)(sn= $Name*))"

 

 

Find all computers where computer name starts with xyz

 

 

"(&(objectClass=computer)(sAMAccountName= $ComputerName*))"

 

 

 

Well ladies and gentleman, here endeth the lesson.

 

That is all

 

BenP

Comments

  • Anonymous
    January 01, 2003
    How do you search Active Directory? Here’s one way… Benp's Guide to Stuff : Searching the Active Directory

  • Anonymous
    January 01, 2003
    Ladies + Gents This week I have had the privilege of working at TechEd 2007. I’ve been on the PowerShell

  • Anonymous
    July 30, 2007
    "return $user[0].path" is great and all but it only gives me the entire path.  How would I just get their name?  Like if I sent "bdb" it would return "Bob Barker"

  • Anonymous
    May 22, 2008
    I'm doing a script, because of the introduction of a new e-mail domain we're going to use. Doing a script that needs this particular functionality, so I'm going to steal this, and modify it (I will remember to thank you when I make the script public, of course :) ). Thanks Ben, this was just what I needed :)

  • Anonymous
    May 23, 2008
    this link is dead: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemdirectoryservicesdirectorysearcherclassfiltertopic.asp A Paris Workshoper

  • Anonymous
    October 10, 2008
    Greetings, were born recently a new browser from [url=http://www.google.com/chrome/index.html?hl=en&brand=CHMI&utm_source=ru-et&utm_medium=et&utm_campaign=ru]google.com[/url] who it bear tried, how it to you?   Whether there is a intelligibility to vibrating бета the construction or not?  If who tried this origin, define please.


P.S.  acquit if to that sector has written, the seek of administrators to pass on a strut where you examine more correct :). P.P.S. On not which forums to me said, that this output apart from on some, that not so, here and has unfaltering to learn from you.

  • Anonymous
    May 28, 2009
    I want to say - thank you for this!

  • Anonymous
    June 27, 2009
    Bob, You can select the properties of an object by specifying the .properties.<propertyname> extension Example: return $user[0].properties.name   Returns the users name. Same works for any property of another object.

  • Anonymous
    March 07, 2012
    Wspaniały wpis. Benp jestes wielki.

  • Anonymous
    February 05, 2015
    We wondered what might be the fastet way to LDAP search with PowerShell and compared 3 ways.
    http://activedirectoryfaq.com/?p=1432