Scripting Active Directory with PowerShell

Introduction to Scripting Active Directory with PowerShell

What makes scripting Active Directory tricky is that we need so many different skills.  However, if you are a beginner don’t worry, very little knowledge is assumed.  If you are experienced with PowerShell’s commands you may prefer to jump straight to Example 4.

Topics for PowerShell and Active Directory

 ♣

Skills Checklist

  • Active Directory Users and Computer (GUI)
  • LDAP – ADSI Edit
  • PowerShell’s | Where clause, Foreach loop and New-Object DirectoryServices

ADUC (Active Directory Users and Computers)

Scripters are born looking for shortcuts.  Their very first action was probably to copy and paste someone else’s script.  What I cannot understand therefore, is why scripters as a breed are so unwilling to use GUIs.  It’s as though a GUI is their enemy, or a cheat method that they dare not touch.

I take the view that examining the corresponding GUI compliments my script.  Perhaps I am addicted to using both in tandem, because every time I have a walk-through with the GUI, the menus give me ideas for a better script.  There is also the point that inspecting the object’s properties using ADUC, provides proof that the script has indeed executed as intended.  Or more likely, that the script has not worked, but observing the results helps me to troubleshoot a problem with the code.

What ADUC also alerts us to is the true domain name.  Is your domain name plain YourCompany, or does it have an extension, for example, YourCompany.com?  In passing, could I remind you that in LDAP dc= means domain context, and not domain controller.

A general inspection of a User’s property sheet will reveal dialog boxes labelled: First name, Last name and User logon name.  It is these fields (or similar) that I recommend we revisit after running the script.  The next connection to make is the relationship between say ‘Last Name’ and the object property called ‘sn’.  In fact, they are one and the same, but how did I know that?  The answer is to spend time researching, or just exploring with ADSI Edit.

LDAP – As Revealed by ADSI Edit

The ADSI Edit utility, which is found on the Server CD or here, will reveal the connection between property names, for example:

GUI – You see, User logon name: 
LDAP Property – You script: sAMAccountName

Guy Recommends:  SolarWinds’ Free Bulk Import ToolFree Download Solarwinds Bulk Import Tool

Import users from a spreadsheet.  Just provide a list of the users with their fields in the top row, and save as .csv file.  Then launch this FREE utility and match your fields with AD’s attributes, click and import the users.

Optionally, you can provide the name of the OU where the new accounts will be born. Download your FREE bulk import tool.

If you need more comprehensive application analysis software,
Download a free trial of SAM (Server & Application Monitor)

Guy’s LDAP Learning Technique

My mission, as always, is to get you started.  So here is simple technique that I employ when I am unsure of which LDAP name to include in my script.  Let us take it as read that you are practising on a test domain.  If you only have a live domain, then at least create a test OU with test users.

The secret is to change a value in the GUI and then see if you can find the very same string in ADSI Edit.  If so, then you have learned the equivalence between the GUI menu, and the LDAP property.  For example, go to the Last name of your test user, enter ‘Thomas’, now search through ADSI Edit until you find ‘Thomas’.  The conclusion is that, Last name: corresponds to ‘sn’.

PowerShell Active DirectoryPowerShell ADSI Edit LDAP

There is an alternative, and that is to get a list of LDAP properties, which you keep by your side when scripting.

PowerShell Script to Connecting to Active Directory

Pre-requisites

1) Install PowerShell (Modern systems already installed)

Instructions:
Visit Microsoft’s site and download the correct version of PowerShell for your operating system.

  • Launch PowerShell
  • Copy the lines of code below (into memory)
  • Right-click on the PowerShell symbol
  • Edit –> Paste
  • Press enter to execute the code.

2) Check Your Domain Name

To double-check that your domain is what you think it is, launch ADUC and see whether your domain is one word, or whether it has an additional, .com or .local extension.

Example 1: Simple Script to Echo the Active Directory Domain

# PowerShell Connects to Active Directory
# Connect to hard-coded root
# Author: Guy Thomas
# Version 1.3 Sept 2007 tested on PowerShell v 1.0 and RC2

$Dom = ‘LDAP://DC=cp;DC=mosel’
$Root = New-Object DirectoryServices.DirectoryEntry $Dom
Write-host "PowerShell connects to domain: $Dom"

Learning Points

Note 1:  ‘LDAP://DC=cp;DC=mosel’.  Rather than using the traditional .local namespace for non-Internet domains, I prefer .Mosel merely because it happens to be the road where I live!  Naturally you changed the value for this $Dom variable in your live script?  Didn’t you?

Note 2:  New-Object is such an insignificant command, yet it is vital for creating objects, which we can use for connecting connect to Active Directory.

Note 3:  DirectoryServices.DirectoryEntry is one of the key commands to connect to Active Directory.  I think of this as a pipeline to the root of my domain’s namespace.

Note 4:  I realize that Example 1 is short.  Also from a design point of view it does not achieve much.  If you are familiar with PowerShell jump to Example 4.  Else, stick with my master plan to build up gradually and go to Example 2.

Example 2: To Count the Objects in Your Active Directory

Pre-requisite.  Once again, change $Dom to reflect your domain, and not mine.

# PowerShell Counts objects in Active Directory
# Connect to hard-coded root
# Author: Guy Thomas
# Version 1.5 Sept 2007 tested on PowerShell v 1.0 and RC2

$Dom = ‘LDAP://DC=cp;DC=mosel’
$Root = New-Object DirectoryServices.DirectoryEntry $Dom

# Create a selector and start searching from the Root of AD
$selector = New-Object DirectoryServices.DirectorySearcher
$selector.SearchRoot = $root
$adobj= $selector.findall()
"There are $($adobj.count) objects in the $($root.name) domain"

Learning Points

Note 1:   If you get a result greater than zero, then your script is working.  If the number is blank, then check for a typo in your $Dom domain name.  The following result, would mean an error with $Dom:
There are objects in the domain.  Whereas,  ‘There are  173  objects in the domain’.  Means you edited $DOM to reflect YOUR domain name.

Challenge: One of the best ways of learning is to see if you can alter the script, and still get a meaningful result.  My challenge is to amend the script to count only the objects in the Users container.  Thus amend, or redefine $DOM to include CN=Users;. 
$Dom = ‘LDAP://CN=Users;DC=cp;DC=mosel’

If you examine ADUC, the yellow Users folder does not have the tiny OU icon / motif, thus is a container object and not actually an Organizational Unit. Hence we use CN=User and not OU=User.

Guy Recommends:  A Free Trial of the Network Performance Monitor (NPM)Review of Orion NPM v11.5 v11.5

SolarWinds’ Network Performance Monitor will help you discover what’s happening on your network.  This utility will also guide you through troubleshooting; the dashboard will indicate whether the root cause is a broken link, faulty equipment or resource overload.

What I like best is the way NPM suggests solutions to network problems.  Its also has the ability to monitor the health of individual VMware virtual machines.  If you are interested in troubleshooting, and creating network maps, then I recommend that you try NPM now.

Download a free trial of Solarwinds’ Network Performance Monitor

Example 3: Adding a Where Clause

Pre-requisites

  • Practice with this clause: | Where{$_.xyz} until you understand its syntax.
  • Research LDAP properties with ADSI Edit.  In particular, research the possible values for objectCategory.

# PowerShell Counts Person Objects in Active Directory
# Author: Guy Thomas
# Version 2.3 Sept 2007 tested on PowerShell v 1.0 (RC2)
$Dom = ‘LDAP://DC=cp;DC=mosel’
$Root = New-Object DirectoryServices.DirectoryEntry $Dom
# Create a selector and start searching from the Root of AD
$selector = New-Object DirectoryServices.DirectorySearcher
$selector.SearchRoot = $root
$adobj= $selector.findall() |`
where {$_.properties.objectcategory -Match "CN=Person"}
"There are $($adobj.count) objects in the $($root.name) domain"

Learning Points

Note 1:  The key parameter, or switch, is -Match.  Again, to truly understand how it works, try substituting -Like for -Match.  What you find is that with -Like you need to add the wildcard *, for example, "CN=Person*".

Note 2:  To see why I choose ‘Person’ and not ‘User’, try a simple substitution, "CN=User"

Challenge: To learn more about LDAP properties try this:
where {$_.properties.objectclass -Match "User"}.

See more on PowerShell’s $_. place-holder.

My point is that objectClass is different from objectCategory.  Bizarrely, ‘User’ includes Computers as well as User accounts.  Furthermore, I truly believe that learning PowerShell will teach you more about Active Directory.

SolarWinds Response Time Viewer for WiresharkGuy Recommends: Response Time Viewer for Wireshark

Here is a free tool to troubleshoot network connection and latency problems.  Key concept: this is a free tool from SolarWinds that analyzes network packets captured by Wireshark (also a free tool).

When you inspect the data in the Response Time Dashboard, if you hover over an application such as Teredo or TCP, then you get an orange box showing a breakdown of network and application response times, note the 'Peak value' in addition to the 'Average'.

Download your free trial of SolarWinds Response Time Viewer for Wireshark

Example 4: Adding a Foreach Loop

Pre-requisites

  • Experiment with the foreach loop in isolation so that you understand its mechanism.
  • Research more LDAP properties.  For example the relationship between, GivenName and (First name), and between SN and (Surname), also CN and (Full name).

# PowerShell Displays Firstname and surname of Users
# Author: Guy Thomas
# Version 4.3 Aug 2007 tested on PowerShell 1.0
$Dom = ‘LDAP://DC=cp;DC=mosel’
$Root = New-Object DirectoryServices.DirectoryEntry $Dom
$i=0
# Create a selector and start searching from the Root of AD
$selector = New-Object DirectoryServices.DirectorySearcher
$selector.SearchRoot = $root
$adobj= $selector.findall() |`
where {$_.properties.objectcategory -Match "CN=Person"}
foreach ($person in $adobj){
$prop=$person.properties
$i++
Write-host "First name: $($prop.givenname) " `
"Surname: $($prop.sn) User: $($prop.cn)"
}
"Total $i"

Learning Points

Note 1:  Let us examine what is inside the foreach loop.  Firstly, we create a new variable called $prop to hold the object’s properties.  Next we Write-host, the properties that we are interested in starting with givenName.

Note 2:  I added a loop counter, $i.  At the top of the script I set the value to zero, then I increment with $i++.

Challenge:  Part of the reason that I added to the $i loop counter is to compare different scripts.  For instance, if you add an ‘if’ filter this should drastically reduce the number of objects.  Here is my challenge, add this code after the $prop and before $i++
if ($prop.sn -ne $Null){

Important: Add a balancing closing bracket }.  Placing a second bracket before the existing } will do nicely.

See here for the answer / result of Guy’s Challenge

Tim de Vries Has an Improvement

Tim has written kindly pointing out that while the above script is ok for a small number of users, for a large domain you need to declare a larger pagesize, for example:

Tim suggests this modification:

——
# Create a selector and start searching from the Root of AD
$selector = New-Object DirectoryServices.DirectorySearcher
$selector.SearchRoot = $root
$Selector.pagesize = 1000

Thank you Tim, and also Thomas for proof reading.

Summary of PowerShell and Active Directory

It was with much relief that I discovered that PowerShell supplied a mechanism to query Active Directory.  The secret is starting with new-object, then choosing the specific Com objects, DirectoryServices.DirectoryEntry and DirectoryServices.DirectorySearcher.  How easy you find the rest of my script depends on your experience of pure PowerShell techniques, for example foreach loops, and ‘Where’ clauses.

If you like this page then please share it with your friends

 


See more PowerShell QAD Scripts

PowerShell Home   • Quest QAD   • QADUser   • QADGroup   • QADComputer

Export-CSV   • Import CSV   • QAD Password   • Add-PSSnapin   • Free Import User CSVDE Tool

Get-AdUser -filter   • Windows PowerShell   • Windows PowerShell .Net

Please email me if you have a better example script. Also please report any factual mistakes, grammatical errors or broken links, I will be happy to correct the fault.