Hey Scripting Guy! It seems that searching Active Directory from within Windows PowerShell is rather easy. But what I do not get is the syntax for the query. In the past I used something that looked more like SQL that the examples you show. What gives?
– RH
Hi PS,
I was watching the Ninja bear on MSN Video pretty cool actually. I don’t think I would want to fight him (or her … never can tell with bears). We are finally digging out from underneath the big Charlotte, North Carolina, USA snow storm and the sun if shining, there are birds singing … more like a normal southern winter … around 60 degrees or so outside (15.5 degrees Celsius using my handy temperature conversion HTA). So I thought what is there better to do than to watch a Ninja bear and check my scripter@Microsoft.Com email. Let’s take a look at the LDAP dialect that is used to query Active Directory. Also since this is sort of a weather holiday here in Charlotte (I mean we are digging out from under a massive snow blizzard) we will not be writing a script. However, with Windows PowerShell there are lots of things that do not require scripts.
This week we are talking about searching Active Directory. The Active Directory Script Center Hub is seen here. It has links to a number of resources related to working with Active Directory. There is a good collection of scripts that illustrate searching Active Directory in this section of the Script Center Script Repository. There are several scripts in the Community Submitted Scripts Center that also illustrate searching Active Directory. The Hey Scripting Guy! active directory archive is also an excellent source of information for searching Active Directory.
There are a couple of options available to us when it comes to querying Active Directory from the PowerShell prompt. One is to use the [ADSISearcher] type accelerator that is available in Windows PowerShell 2.0 (currently in beta). The [ADSISearcher] type accelerator is a shortcut to the System.DirectoryServices.DirectorySearcher class. All the [ADSISearcher] type accelerator does is save us a little bit of typing. We still need to give it the appropriate constructor to actually create an instance of the class.
If we do not use the [ADSISearcher] we need to use the New-Object cmdlet to create the object. We can put the New-Object command inside smooth parentheses to force the creation of the object first, and then call the FindAll method from the DirectorySearcher object. The resulting collection of DirectoryEntry objects is pipelined to the Select-Object cmdlet where the Path property is returned. This is seen here.
PS C:> (New-Object DirectoryServices.DirectorySearcher “ObjectClass=user”).FindAll() |
Select-object -property path
Path
—-
LDAP://CN=Administrator,CN=Users,DC=nwtraders,DC=com
LDAP://CN=Guest,CN=Users,DC=nwtraders,DC=com
LDAP://CN=BERLIN,OU=Domain Controllers,DC=nwtraders,DC=com
LDAP://CN=krbtgt,CN=Users,DC=nwtraders,DC=com
LDAP://CN=VISTA,CN=Computers,DC=nwtraders,DC=com
LDAP://CN=VistaAdmin,OU=Students,DC=nwtraders,DC=com
List Truncated –
To use the [ADSISearcher] type accelerator, we still need to supply it with an appropriate constructor, which in many cases will be the search filter expressed in LDAP Search Filter Syntax. LDAP Search Filter Syntax is defined in the Internet Request For Comment RFC 2254 and is represented by Unicode strings. The search filters allow us to specify search criteria in an efficient and effective manner. Some examples of using the LDAP Search Filter Syntax are seen in Table 1.
LDAP Search Filter Examples Table 1
Search Filter |
Description |
ObjectClass=Computer |
All computer objects |
ObjectClass=OrganizationalUnit |
All Organizational Unit objects |
ObjectClass=User |
All user objects as well as all computer objects |
ObjectCategory=User |
All User objects |
(&(ObjectCategory=User)(ObjectClass=Person)) |
All User objects |
L=Berlin |
All objects with the location of Berlin |
Name=*Berlin* |
All objects with a name that contains Berlin |
(&(L=berlin)(ObjectCategory=OrganizationalUnit)) |
All Organizational Units with the location of Berlin |
(&(ObjectCategory=OrganizationalUnit)(Name=*Berlin*)) |
All Organizational Units with a name that contains Berlin |
(&(ObjectCategory=OrganizationalUnit)(Name=*Berlin*)(!L=Berlin)) |
All Organizational Units with a name that contains Berlin, but do not have a location of Berlin |
(&(ObjectCategory=OrganizationalUnit)(Name=*Berlin*)(!L=*)) |
All Organizational Units with a name that contains Berlin, but do not have any location specified |
(&(ObjectCategory=OrganizationalUnit)(|(L=Berlin)(L=Charlotte))) |
All Organizational Units with a location of either Berlin or Charlotte |
As seen in the examples in Table 1 there are two ways in which the search filter can be specified. The first method is a straight forward assignment filter. The attribute, the operator, and the value make up the filter. This is seen here.
PS C:> ([ADSISearcher]”Name=Charlotte”).FindAll() | Select Path
Path
—-
LDAP://OU=Charlotte,DC=nwtraders,DC=com
If we were going to do the same thing without using the [ADSISearcher] the code we would need to use would first need to create the DirectoryServices.DirectorySearcher object and store it in a variable. We will call the variable $adsiSearcher. We then assign our filter to the filter property and call then we call the FindAll method. It would look like the following:
PS C:> $adsiSearcher = New-Object DirectoryServices.DirectorySearcher
PS C:> $adsiSearcher.Filter = “Name=Charlotte”
PS C:> $adsiSearcher.FindAll() | Select path
Path
—-
0 comments