Guy’s Scripting Ezine 124 – ‘Walking the AD Tree’ (Walk to the Child OU)

Guy’s Scripting Ezine 124 – ‘Walking the AD Tree’ (Walk to the Child OU)

 ♣

This Week’s Secret

‘Walking the AD Tree’ is a catch phrase that I invented to describe a script which would interrogate each OU in an Active Directory domain.

DA is single-handedly responsible for the improvements in this week’s script Walk to the Child OU.  While DA shies publicity, his is an interesting story.  9 months ago he stumbled across my site, got started with VBScript and now his skill level has overtaken mine.  This is precisely what I want to achieve, to get you started, to help you to reach the point where you can create your own scripts which solve your network problem.

On the subject of help, I thank Jay Armstrong and Sean Hook for sending in their ADO scripts which tackle the ‘Walk the AD Tree’ from a different angle.  I will feature ADO in a future ezine.

This Week’s Mission

It was the correct decision to split the ‘Walk the AD Tree’ into two phases.  If you remember, last week’s Ezine 123 created a brilliant script which could change any object in any OU – provided it was a top level OU.  Our first mission this week is to introduce amendments which recursively drill down into child or nested OUs.

Many IT managers don’t keep their user and computer accounts in OUs.  Instead they create all accounts in the default Users folder.  Consequently, we need to add code which forces the script to search through ‘Container’ objects as well as ‘OrganizationalUnit’ objects.  To labour this point, in Active Directory Users and Computers, pure yellow folders such as Users are not OUs; a fact you can confirm by launching ADSI Edit, it will show you that the Users folder belongs to the ‘Container’ class.

In real life, our Walk the AD Tree script would do ‘stuff’.  By ‘stuff, I mean resetting passwords, changing department names, or populating the location field.  In terms of learning progression, the idea would be to perfect the ‘stuff’ which amends Active Directory accounts in another script and only then copy and paste the code onto our script.  (See the section in the Examples called ‘Do Stuff’.)

Example 1 – Walk to the AD Containers

In addition to interrogating OrganizationalUnit, this script includes a ‘Case Statement’ for the ‘Container’ class.  This means that it looks in the User container and also the Computer container.

Pre-requisites

I strongly suggest that you master this script first.

You really do need an active directory domain for this VBScript to work.  Either create an OU called students and populate it with a few users, or else change the value of strOU to match your organization.

Instructions

  1. Copy and paste the script below into notepad or get a script editor such as OnScript.
  2. Save the file with .vbs extension e.g. WalkSelectAD.vbs
  3. Double click your script and check the message box.
  4. Logon as one of the user accounts and check the password and the fact you have to change it at first logon.

 

‘ WalkSelectAD.vbs
‘ Example VBScript to ‘Walk the Active Directory Tree
‘ Uses Select Case to get OU and Container
‘ Version 2.5 – September 2006
‘ ———————————————————‘
Option Explicit

Dim objUser, objChild, objConnection, objRootDSE
Dim strRoot, strDNSDomain, strContainer, strPassword
Dim intAccValue, intCounter, intPwdValue
Dim intOU, intContainer

‘ ———————————————————
strPassword = "F@rst0ne"
intAccValue = 544
intPwdValue = 0
intCounter = 0

Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("DefaultNamingContext")
strContainer = strContainer & strDNSDomain
set strRoot =GetObject("LDAP://" & strDNSDomain )
‘ ———————————————————–
For each objChild in strRoot
   Select Case objChild.class
   Case "organizationalUnit","container"
   Call DATree
   End Select
Next

sub DATree()
For each objUser in objChild
  If objUser.class="user" then
   ‘ In the Real World, this is where you would do more stuff
     If objUser.Description ="Year 1" then
     objUser.SetPassword strPassword
     objUser.SetInfo
     objUser.Put "pwdLastSet", intPwdValue
     objUser.SetInfo
     objUser.Put "userAccountControl", intAccValue
     objUser.SetInfo
     intCounter = intCounter +1
  End If
End if
next
End Sub

Wscript.Echo "Accounts changed = " & intCounter
Wscript.Quit

 

VBScript Learning Points

Note 1:  Select Case is such an elegant construction, not only does it save code compared with multiple ‘If …then Else… End If, but also it produces the goods when the If statement simply fails.

Note 2: Hopefully, you will have familiarized yourself with the scripts in ezine 123, the new development here is that the script looks in both OUs and Container objects.  The significance is that many administrators store their accounts in the Users or the Computers folders, which are members of the class=container.  (Not the class=organizationalUnit).  Observe how DA solves the problem with : Case "organizationalUnit","container" 

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 software, download a free trial of SAM (Server & Application Monitor)

Example 2 ‘Walking the AD Tree’  – Recursive VBScript Controlled by Function

As poker players would say, ‘This is the nuts’.  Meaning here is the ultimate script for searching through both ‘Container’ and OrganizationalUnit’ objects.  Moreover, it drills down through any number of child or nested OUs.

‘ WalkSelectRecursive.vbs
‘ Example VBScript to ‘Walk to the Child OU
‘ Version 2.9 – September 2006
‘ ——————————————————
Option Explicit
Dim objUser, objChild, objConnection, objRootDSE
Dim strRoot, strDNSDomain, strContainer, strPassword
Dim intAccValue, intCounter, intPwdValue
‘ ——————————————————
‘ Section to connect to the root of Active Directory
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("DefaultNamingContext")
Set strRoot = GetObject("LDAP://" & strDNSDomain )
Call DATree(strDNSDomain)
Wscript.Echo "Changes = " & intCounter
Wscript.Quit
‘ ——————————————————
‘ This function counts each object in the OU and then
‘ Calls itself recursively if there are any child OU’s.
‘ Solves the problem of "Container" with Select Case
Function DATree(strDNSDomain)
Set objConnection = GetObject("LDAP://" & strDNSDomain)
For each objChild In objConnection
   Select Case objChild.class
   Case "user"
   ‘ —————————————————
   ‘ In the Real World, this is where you would do stuff
   If objChild.Description = "Year 1" Then
   intCounter = intCounter +1
   End If
   Case "organizationalUnit","container"
   ‘ —————————————————
   ‘ If there are any child OU’s
   ‘ Call the function again and point to the child OU
   Call DATree(objChild.Name & "," & strDNSDomain)
   End Select
Next
End Function

 

Learning Points

Note 1:  Observe that this script uses a function rather than a sub routine.  Also, see how it passes arguments or parameters strDNSDomain to the function, for example: Function DATree(strDNSDomain)

Note 2:  Firstly, confession time. I am not an expert of VBScript functions.  However, it seems to me that one benefit of a function is that it can call itself recursively and it is that property that we need for this script.  Another difference between ‘Sub’ and ‘Function’ is that you can use Function on the right side of the expression.

Guy Recommends: Tools4ever’s UMRAUMRA The User Management Resource Administrator

Tired of writing scripts? The User Management Resource Administrator solution by Tools4ever offers an alternative to time-consuming manual processes.

It features 100% auto provisioning, Helpdesk Delegation, Connectors to more than 130 systems/applications, Workflow Management, Self Service and many other benefits. Click on the link for more information onUMRA.

Guy’s Challenges

Challenge 1:  Research the Select Case statement.  Try to create simple examples of your own.

Challenge 2:  Find the sections which ‘Do Stuff’ and then incorporate some of your real life tasks into the script.

Challenge 3: Experiment with writing a Function() of your own.

Summary of ‘Walking the AD Tree’

This is my best script to date.  When I started on the quest, I did not think that it would be possible to ‘Walk the AD Tree’.  Half way through came the agony that the VBScript would not deal with nested OUs; finally came the ecstasy of the recursive function.  Until DA showed the way I did not believe that a function could call itself without going into an endless loop.  Thankfully the script works properly and exits gracefully once it has visited all the nested OUs.  Example 2 is ‘The Nuts’ for search every OU and container in your Active Directory domain.

See More Active Directory VBScripts featuring Active Directory

• Create Users  •PB 55 CSVDE  • Ezine 56 OU  • Ezine 123 Ad Tree  •Ezine 124 Ad Tree  •IPAM 3 Review

Ezine 23 enable accounts  •UserAccountControl Values  •Ezine 27 Move Computers  • Ezine 42 LDAP

Ezine 44 CSVDE  • Ezines  • PowerShell Add Computer  • LDAP Properties  • Free CSVDE Importer