Summary: Learn how to use Windows PowerShell to query Microsoft Active Directory without having to write a script.

 

Hey, Scripting Guy! QuestionHey, Scripting Guy! I would like to use cmdlets to work with Active Directory. Are there any Windows PowerShell cmdlets in Windows Server 2008 R2 that can be used?

 -- BW

  

Hey, Scripting Guy! AnswerHello BW, Microsoft Scripting Guy Ed Wilson here. As a matter of a fact there are Windows PowerShell cmdlets that will enable you to work with Active Directory Domain Services (AD DS).

  

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.

The Active Directory cmdlets are included with Windows Server 2008 R2. They are contained in a module, and must first be loaded by using the Import-Module cmdlet. You can, of course, select the Active Directory PowerShell icon which starts Windows PowerShell with the Active Directory cmdlets already loaded. The nice thing about the Active Directory cmdlets being contained in a module is that you can use the Import-Module cmdlet to add them into a Windows PowerShell session from a remote computer which does not have the cmdlets. To do this, you have to follow these steps.

  • Establish a remote session to the server that is running Windows 2008 R2
  • Import the Active Directory cmdlets by using the Import-Module cmdlet
  • Perform the Active Directory query
  • Disconnect from the remote session
  • Remove the remote session

One thing to remember when using the Remove-PSSession cmdlet with the id parameter, you may not always know what the session id number actually is. The first session is 1, and the second session is 2. It keeps a running tally of all the sessions. However, you may not be aware of which session id number that you are up to. As a best practice, I always use the Get-PsSession cmdlet to obtain a listing of the all the PsSessions on the computer. I also make it a habit of removing disconnected sessions I do not think I will be going back to within the near future. This frees the resources consumed by the session.

This technique is shown here.

PS C:\> $ps = New-PSSession -ComputerName Sydney.WoodBridgeBank.Com -Credential administrator@WoodBridgeBank.Com
PS C:\> Enter-PSSession $ps
[sydney.woodbridgebank.com]: PS C:\> Import-Module ActiveDirectory
[sydney.woodbridgebank.com]: PS C:\> Get-ADOrganizationalUnit -Filter "L -eq 'Berlin'"


Name              : Berlin Bank
Country           : DE
PostalCode        :
City              : Berlin
ManagedBy         :
StreetAddress     :
State             : Berlin
ObjectGUID        : dde90f41-128c-4568-9822-00de5a4c96cc
ObjectClass       : organizationalUnit
DistinguishedName : OU=Berlin Bank,DC=woodbridgebank,DC=com
[sydney.woodbridgebank.com]: PS C:\> Exit-PSSession
PS C:\> Get-PSSession

       Id Name            ComputerName    State    Configuration
       -- ----            ------------    -----    -------------
        1 Session1        sydney.woodb... Broken   Microsoft.PowerShell
PS C:\> Remove-PSSession -Id 1

 

In addition to using the AD Filter syntax which uses Windows PowerShell operators and supports rich type conversions, you can also use the LDAP filter syntax discussed in yesterday's Hey, Scripting Guy! Blog post.

To do this, you use the LDAPFilter parameter instead of the Filter parameter, and supply the LDAP Search Filter expression inside a set of quotation marks. This is seen here.

PS C:\> Get-ADOrganizationalUnit -LDAPFilter '(L=Berlin)'


Name              : Berlin Bank
Country           : DE
PostalCode        :
City              : Berlin
ManagedBy         :
StreetAddress     :
State             : Berlin
ObjectGUID        : dde90f41-128c-4568-9822-00de5a4c96cc
ObjectClass       : organizationalUnit
DistinguishedName : OU=Berlin Bank,DC=woodbridgebank,DC=com

 

Many powerful commands can be done directly from the command line by using legacy command line utilities. There is nothing wrong with using these commands, and these commands are fully supported in Windows PowerShell. The fact that you can use the Get-Command cmdlet to easily search for legacy command line utilities should be an indicator that Windows PowerShell supports using these commands. To use the Get-Command cmdlet to search for executables, you can use wildcard characters if you are not familiar with the exact name of the program. This is seen here.

PS C:\> Get-Command ds*

CommandType     Name                            Definition
-----------     ----                            ----------
Application     ds16gt.dLL                      C:\Windows\system32\ds16gt.dLL
Application     ds32gt.dll                      C:\Windows\system32\ds32gt.dll
Application     dsa.msc                         C:\Windows\system32\dsa.msc
Application     dsacls.exe                      C:\Windows\system32\dsacls.exe
Application     dsadd.exe                       C:\Windows\system32\dsadd.exe
Application     dsadmin.dll                     C:\Windows\system32\dsadmin.dll
Application     dsauth.dll                      C:\Windows\system32\dsauth.dll
Application     dsdbutil.exe                    C:\Windows\system32\dsdbutil...
Application     dsdmo.dll                       C:\Windows\system32\dsdmo.dll
Application     dsget.exe                       C:\Windows\system32\dsget.exe
Application     dskquota.dll                    C:\Windows\system32\dskquota...
Application     dskquoui.dll                    C:\Windows\system32\dskquoui...
Application     dsmgmt.exe                      C:\Windows\system32\dsmgmt.exe
Application     dsmod.exe                       C:\Windows\system32\dsmod.exe
Application     dsmove.exe                      C:\Windows\system32\dsmove.exe
Application     dsound.dll                      C:\Windows\system32\dsound.dll
Application     dsprop.dll                      C:\Windows\system32\dsprop.dll
Application     dsprov.dll                      C:\Windows\System32\Wbem\dsp...
Application     dsprov.mof                      C:\Windows\System32\Wbem\dsp...
Application     dsquery.dll                     C:\Windows\system32\dsquery.dll
Application     dsquery.exe                     C:\Windows\system32\dsquery.exe
Application     dsrm.exe                        C:\Windows\system32\dsrm.exe
Application     dssec.dat                       C:\Windows\system32\dssec.dat
Application     dssec.dll                       C:\Windows\system32\dssec.dll
Application     dssenh.dll                      C:\Windows\system32\dssenh.dll
Application     dssite.msc                      C:\Windows\system32\dssite.msc
Application     dsuiext.dll                     C:\Windows\system32\dsuiext.dll
Application     dsuiwiz.dll                     C:\Windows\system32\dsuiwiz.dll
Application     dswave.dll                      C:\Windows\system32\dswave.dll

 

The previous command would return any valid Windows PowerShell command including functions, cmdlets, and executable files. If you are specifically searching for command line utilities, you should use the commandtype parameter as seen here where I retrieve only applications.

PS C:\> Get-Command -Name ds* -CommandType application

CommandType     Name                            Definition
-----------     ----                            ----------
Application     ds16gt.dLL                      C:\Windows\system32\ds16gt.dLL
Application     ds32gt.dll                      C:\Windows\system32\ds32gt.dll
Application     dsa.msc                         C:\Windows\system32\dsa.msc
Application     dsacls.exe                      C:\Windows\system32\dsacls.exe
Application     dsadd.exe                       C:\Windows\system32\dsadd.exe
Application     dsadmin.dll                     C:\Windows\system32\dsadmin.dll
Application     dsauth.dll                      C:\Windows\system32\dsauth.dll
Application     dsdbutil.exe                    C:\Windows\system32\dsdbutil...
Application     dsdmo.dll                       C:\Windows\system32\dsdmo.dll
Application     dsget.exe                       C:\Windows\system32\dsget.exe
Application     dskquota.dll                    C:\Windows\system32\dskquota...
Application     dskquoui.dll                    C:\Windows\system32\dskquoui...
Application     dsmgmt.exe                      C:\Windows\system32\dsmgmt.exe
Application     dsmod.exe                       C:\Windows\system32\dsmod.exe
Application     dsmove.exe                      C:\Windows\system32\dsmove.exe
Application     dsound.dll                      C:\Windows\system32\dsound.dll
Application     dsprop.dll                      C:\Windows\system32\dsprop.dll
Application     dsprov.dll                      C:\Windows\System32\Wbem\dsp...
Application     dsprov.mof                      C:\Windows\System32\Wbem\dsp...
Application     dsquery.dll                     C:\Windows\system32\dsquery.dll
Application     dsquery.exe                     C:\Windows\system32\dsquery.exe
Application     dsrm.exe                        C:\Windows\system32\dsrm.exe
Application     dssec.dat                       C:\Windows\system32\dssec.dat
Application     dssec.dll                       C:\Windows\system32\dssec.dll
Application     dssenh.dll                      C:\Windows\system32\dssenh.dll
Application     dssite.msc                      C:\Windows\system32\dssite.msc
Application     dsuiext.dll                     C:\Windows\system32\dsuiext.dll
Application     dsuiwiz.dll                     C:\Windows\system32\dsuiwiz.dll
Application     dswave.dll                      C:\Windows\system32\dswave.dll

 

The ease of use and the flexibility of Windows PowerShell have created resurgence in the interest of command line programs. An example is the use of DsQuery.exe which lets the user quickly issue a query against Active Directory. With the inclusion of the [ADSISearcher] type accelerator, and the various Active Directory cmdlets in Windows Server 2008 R2 you may be wondering why you might still want to use the DsQuery.exe utility. Here is the syntax to obtain a listing of the organizational units in your domain using DsQuery.exe.

PS C:\> dsquery ou
"OU=Domain Controllers,DC=nwtraders,DC=com"
"OU=Students,DC=nwtraders,DC=com"
"OU=ManagedComputers,DC=nwtraders,DC=com"
"OU=TestOU,DC=nwtraders,DC=com"

 

This is the syntax to retrieve a listing of the OrganizationalUnits in your domain by using the [ADSISearcher] type accelerator.

PS C:\> ([ADSISearcher]"objectClass=OrganizationalUnit").findall() | select-Object -property path

Path
----
LDAP://OU=Domain Controllers,DC=nwtraders,DC=com
LDAP://OU=Students,DC=nwtraders,DC=com
LDAP://OU=ManagedComputers,DC=nwtraders,DC=com
LDAP://OU=TestOU,DC=nwtraders,DC=com

 

The syntax to obtain a listing of OrganizationalUnits by using the Get-ADOrganizationalUnit cmdlet which is included in the Active Directory module on Windows 2008 Server R2 is a bit easier to use. When you work from the Windows PowerShell prompt, you do not always have to specify parameter names. You can also use the alias name (Select for Select-Object) if you want to. This makes the syntax shorter, but could lead to problems when it comes time to modify the command. The use of the Get-ADOrganizationalUnit cmdlet is seen here.

PS C:\> Get-ADOrganizationalUnit -Filter "name -like '*'" | Select DistinguishedName

DistinguishedName
-----------------
OU=Domain Controllers,DC=woodbridgebank,DC=com
OU=Test1,DC=woodbridgebank,DC=com

 

If your only consideration is shortness of syntax, obviously DSQuery wins. There could, of course, be other considerations that would come into play. For one thing, DSQuery returns a string, whereas the [ADSISearcher] type accelerator returns a DirectoryEntry object. The Get-ADOrganizationalUnit command returns a Microsoft.ActiveDirectory.Management.ADOrganizationalUnit object. Depending on what you are trying to do, one kind of object may be preferable over the other kind of object. Beyond the return type issue, there are other problems with DSQuery also. DSQuery sacrifices power for simplicity. This means there are only a few attributes that you can use as your search query. If you want to find all the Organizational Units in Active Directory that contain the name Berlin in them, you can use the following syntax.

dsquery ou -name *berlin*

 

If on the other hand, you want to find all the organizational units in Active Directory that have a location attribute specified as actually being in Berlin, you will have to resort to using either the AD cmdlets or the [ADSISearcher] type accelerator. As long as you have a good feel for what you can use DSQuery to do, there is no problem at all with availing yourself to this easy-to-use tool. You can even pipeline the results from DSQuery into other utilities such as DSMove which will move the object to another location in Active Directory, DSMod which will enable you to change attribute values, and DSrm which will enable you to delete objects from Active Directory.

An example of how to use DSQuery to find a specific user who has a name like testuser, and then pipelining the results to DSMove to rename the user to testuser2 is seen here. By using the Windows PowerShell transcript, all actions that are taken are logged. This is seen here.

Transcript started, output file is c:\trans\Monday_21_PM.txt

PS C:\> dsquery user -name testuser*

"CN=testuser3,OU=testou,DC=NWTraders,DC=Com"

PS C:\>  dsquery user -name testuser* | dsmove -newname testuser2

dsmove succeeded:CN=testuser3,OU=testou,DC=NWTraders,DC=Com

PS C:\> dsquery user -name testuser*

"CN=testuser2,OU=testou,DC=NWTraders,DC=Com"

PS C:\> Stop-Transcript

Transcript stopped, output file is C:\trans\Monday_21_PM.txt

PS C:\>

 

The complete transcript of the previous action is seen in the following figure.

 

 

BW, that is all there is to using Windows PowerShell and the Active Directory cmdlets. This also concludes To Script or Not to Script week. Join me tomorrow for Quick Hits Friday.

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