Use PowerShell to Query Active Directory from the Console

Use PowerShell to Query Active Directory from the Console

  • Comments 6
  • Likes

  

Summary: Learn how to query Active Directory by using Windows PowerShell without writing a script.

 

Hey, Scripting Guy! QuestionHey, Scripting Guy! Occasionally I have to perform a quick query of Active Directory, but I do not want to write a complicated VBScript or Windows PowerShell script. Is there a way to use Windows PowerShell to query Active Directory that does not involve writing a convoluted script?

-- JW

 

Hey, Scripting Guy! AnswerHello JW, Microsoft Scripting Guy Ed Wilson here. There are in fact, several ways that you can query Active Directory Domain Services from Windows PowerShell that do not involve writing a convoluted script. For example, one tool that can be used is DSQuery. This is seen here where I list all users who have been inactive for 4 weeks.

PS C:\> dsquery user -inactive 4

 

Portions of today’s Hey, Scripting Guy! Blog post are adapted from material in my book Windows PowerShell 2.0 Best Practices that was published by Microsoft Press in December 2009.

With Windows PowerShell 1.0 if you wanted to query Active Directory, most network administrators felt they had to write a script. To a degree, this was a relic of the VBScript days, and a reliance of using the ActiveX Data Objects (ADO) technology to invoke a Lightweight Directory Access Protocol (LDAP) Dialect query against Active Directory. Although it was possible to use the System.DirectoryServices.DirectorySearcher from a Windows PowerShell line, it was not very convenient. There were third-party cmdlets and providers that did make it possible to employ command line queries against Active Directory however, many network administrators are rightfully skeptical about installing unsupported community software on production servers. With Windows PowerShell 2.0 that situation has changed somewhat. By using the techniques seen here, an IT Pro now has a supportable command line solution to the problem of performing Active Directory queries.

There are a couple of options available to you for querying Active Directory from the Windows PowerShell prompt. One is to use the [ADSISearcher] type accelerator. The [ADSISearcher] type accelerator is a shortcut to the System.DirectoryServices.DirectorySearcher class. All the [ADSISearcher] type accelerator does is save you a bit of typing. You still have to give it the appropriate constructor to create an instance of the class. If you did not use the [ADSISearcher] you would need to use the New-Object cmdlet to create the object. You 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").Find
All() | Select 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, you still need to supply it with an appropriate constructor that in many cases will be the search filter expressed in LDAP Search Filter Syntax. LDAP Search Filter Syntax is defined in RFC 2254 and is represented by Unicode strings. The search filters enable you to specify search criteria in an efficient and effective manner. Some examples of using the LDAP Search Filter Syntax are seen in Table 1.

 

Table 1 LDAP Search Filter Examples

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

 

The second way to use the LDAP Search Filter is to combine multiple filters. The operator goes first. You will have the operator, then filter A followed by filter B. You can combine multiple filters and operators as seen in the syntax examples in Table 1. An example of a compound filter is seen here. (This is a single line command that I have broken to two lines to allow it to be displayed correctly on the blog. The backtick (or grave) character “`” is used for line continuation. You will not need the backtick character if you type the command on a single line. I have added it, in case you cut and paste it from the blog.)

PS C:\> ([ADSISearcher]"(|(Name=Charlotte)(Name=Atlanta))").FindAll() | `

Select Path

Path
----
LDAP://OU=Atlanta,DC=nwtraders,DC=com
LDAP://OU=Charlotte,DC=nwtraders,DC=com

 

The operators that you can use for either straight forward assignment filters, or compound search filters are listed in Table 2.

 

Table 2 LDAP Search Filter Logic Operators

Logical operator

Description

=

Equal to

~=

Approximately equal to

<=

Lexicographically less than or equal to

>=

Lexicographically greater than or equal to

&

AND

|

OR

!

NOT

 

Table 3 lists special characters. If any of these special characters must appear in a search filter as a literal character, it must be replaced by the escape sequence.

 

Table 3 LDAP Search Filter Special Characters

ASCII character

Escape sequence substitute

*

\2a

(

\28

)

\29

\

\5c

NUL

 \00

/

\2f

 

As seen in the following figure, special characters are allowed in organizational unit names in Active Directory. 

 

 

As seen in the figure, there is an organizational unit with the name *Atlanta. To retrieve this particular organizational unit, you would have to use the \2a character as seen here.

PS C:\> ([ADSISearcher]"name=\2aAtlanta").FindAll() | Select Path

Path
----
LDAP://OU=*Atlanta,DC=nwtraders,DC=com

 

To retrieve the organizational unit named (Berlin) you have to use the \28 and the \29 escape sequences as documented in Table 3. This is seen here.

PS C:\> ([ADSISearcher]"name=\28Berlin\29").FindAll() | Select Path

Path
----
LDAP://OU=(Berlin),DC=nwtraders,DC=com

 

There is also an organizational unit named /Charlotte\. The escape sequence substitute for the forward slash is \2f. The escape sequence substitute for the backward slash is \5c. To retrieve the organizational unit named /Charlotte\ using the LDAP Search Filter and the [ADSISearcher] type accelerator, you can use a query that looks like the following.

PS C:\> ([ADSISearcher]"name=\2fCharlotte\5c").FindAll() | Select Path

Path
----
LDAP://OU=\/Charlotte\\,DC=nwtraders,DC=com

 

I generally try to avoid using special characters in organizational unit names, user names, group names, computer names and the like. One reason is that I suspect not all applications know how to handle special characters, and I am always afraid that one might not work. Another reason is that, although you can escape the characters in searches, the process is never intuitive, and it costs time trying to figure out how to escape the special character. When you add in the fact the problem will usually occur at 2:00 AM on Saturday Morning (all network problems seem to occur at 2:00 AM on Saturday Morning) when you are likely to forget about escaping the special character, you have a recipe ripe for disaster. Just because something is permitted, does not mean that it is advisable.

The LDAP Search Filter Special Characters and their associated escape sequence substitutes are documented in Table 3 that was seen earlier.

By using the Invoke-Command cmdlet, the [ADSISearcher] can easily be used to query the Active Directory of an un-trusted forest or domain. When doing this, it is frequently important to provide the fully qualified domain name of the computer, because it is possible you may not have complete name resolution using only the NetBios name of the server. It is also best to submit the credentials in a user principal name (UPN) manner as well. When the command is run, the credential dialog box will appear and prompt for the password which must be typed in. The command is seen here (note this is a single line command that I split using the backtick character).

PS C:\> Invoke-Command -ComputerName Sydney.WoodBridgeBank.Com `

-Credential administrator@WoodBridgeBank.com `

-ScriptBlock {([ADSISearcher]"L=Berlin").Findall()}

 

PSComputerName     : sydney.woodbridgebank.com

RunspaceId         : 112f974a-00aa-417c-8a13-9033a49354bd

PSShowComputerName : True

Path               : LDAP://OU=Berlin Bank,DC=woodbridgebank,DC=com

Properties         : {ou, dscorepropagationdata, whencreated, name...}

 

JW, that is all there is to using Windows PowerShell to query Active Directory from the console. To Script or Not to Script week will continue tomorrow when I will talk more about Active Directory.

I invite you to follow me on Twitter or Facebook. If you have any questions, send email to me at scripter@microsoft.com or post them on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

 

Ed Wilson, Microsoft Scripting Guy

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Hmmm, how does this compare to the Quest commandlets? FRankly, get-qaduser is about as simple as it gets, is there anything here that has a greater benefit, apart from being the official way?

  • @Richard I agree the Quest AD cmdlets are simple to use. For that matter, so are the Microsoft AD cmdlets that come with Windows Server 2008 R2. In many environments, there are restrictions against installing software and the techniques I show here are always available. In addition, the LDAP syntax is used by many tools and other cmdlets and is therefore good to learn.

  • Whether it be Quest cmdlets or the native AD cmdlets, I think this is a great point.  Where I have seen people ignore Powershell is because they just see it as a replacement for vbscript, so they just see it as a scripting language.  It is fun to show them how I can accomplish normal tasks right from the command line with a One-liner.

  • @jkavanagh58 It is amazing what can be done with a single line of code and I agree it is fun to show it off. You are right Windows PowerShell is not just another scripting language. In fact you often do not have to write a script at all.

  • You rock! i'm definately recommending your blog.

  • requiered know count of user, group and contacts