Guy's Scripting Ezine 123 - 'Walking the AD Tree'
♣
If you create your own scripts then you will know that euphoric feeling when you make a breakthrough and the script performs its magic. Could this
feeling of discovery have been more intense for Einstein or Archimedes? I doubt it. That said, I would the first to point out that my humble script is not within a light year of their awesome achievements.
But what I would say to you is this: 'Keep on scripting, success is a powerful drug'.
I would like to thank DA and Sean Hook for their support in developing this week's script. This was true role reversal, instead of me helping others get started, it was they who showed me the way to fulfil my
mission and create a script which 'Walks the Active Directory tree'. Briefly, here is the mission: We have an existing script that modifies the value of users properties. For example, it resets the password for all
those user accounts whose LDAP property 'Description' = "Year 1". Jolly good, so what's the problem then? The problem is that the script writes to objects in just
one named container object. In plain English, the script only works in one OU. Now what our mission requires is code that will 'Walk the AD Tree' and thus work for all users in all OUs. The eureka moment came
to me when DA sent a script with this command:
strRoot.Filter = Array("OrganizationalUnit") The significance of this one command is that I now have all the OUs in my grasp. As usual, I will start gradually; in Example 1 we will
merely count the OUs and not make any changes. Once this works, we move to Example 2 where we add code which does LDAP 'stuff'. Stuff like changing passwords, adding values for a Location, or a search and replace on the value held in the
LDAP 'Department'
property. To control this LDAP stuff centrally, I will indulge my passion for the Sub Routine. You really do need an active directory domain for this VBScript to work. I am also assuming that you are not one of those people who don't create any OUs
in their Active Directory. In any case, after you run the script once you could add another OU and run the script again.
Instructions
- Copy and paste the script below into notepad or get a script editor such as OnScript.
- Save the file with .vbs extension e.g. WalkADBas.vbs
- Double click your script and check the message box to see how many OUs you have in Active Directory.
' WalkADBas.vbs ' Example VBScript to 'Walk the Active Directory Tree ' And echo the number of OUs ' Version 1.4 - September 2006 '
--------------------------------------------------------' Option Explicit
Dim objChild, objRootDSE Dim strRoot, strDNSDomain, intCounter intCounter = 0
Set objRootDSE =
GetObject("LDAP://RootDSE") strDNSDomain = objRootDSE.Get("DefaultNamingContext") set strRoot =GetObject("LDAP://" & strDNSDomain ) ' --------------------------------------------------------
' Here is the crucial line: strRoot.Filter = Array("OrganizationalUnit") for each objChild in strRoot intCounter = intCounter +1 next WScript.Echo "Number of OUs = " &
intCounter
Wscript.Quit
VBScript Learning PointsNote 1: The crucial line is strRoot.Filter = Array("OrganizationalUnit"). Short, simple, but so powerful, what it does is extract all the OUs from the
other Active Directory objects. Thereafter the script employs a standard VBScript loop: for each.... next. Note 2: Lines 12-14 (count spaces and 'Remarks) employ my standard technique to connect
to the root of any Active Directory namespace. There is no need in most of my scripts to type names such as dc=xyz,dc.com, because these three lines find the appropriate names automatically. Note
3: I stress, that to build up gradually, this script just counts the OUs. My reasoning is that I want to put the microscope on the command: strRoot.Filter = Array("OrganizationalUnit").
Then you can use this as a skeleton for your scripts not just mine. Let us go on to Example 2 where we perform some useful Active Directory tasks. The point of this script is to reset passwords. However, to avoid annoying most of your users, it only changes those accounts whose description is Year 1.
Description is an LDAP field that you can see in any user property sheet in Active Directory Users and Computers. Pre-requisites I almost always prefer scripts that perform a real job and I almost always avoid 'Hello World' examples. The only problem of
learning my way is that you have to keep alert for where you should change values, and where you must leave them as the original. In this instance either change "Year 1" to some other phrase, or else
deliberately add Year 1 to the description of some of your users. By all means create a special test OU just to test this script. I strongly suggest that you master this script first
' WalkAD.vbs ' Example VBScript to 'Walk the Active Directory Tree ' And then change a user's password ' Version 2.3 - August 2006 ' ---------------------------------------------------------'
Option Explicit
Dim objUser, objChild, objConnection, objRootDSE Dim strRoot, strDNSDomain, strContainer, strPassword Dim intAccValue, intCounter, intPwdValue
'
--------------------------------------------------------- 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 ) '
-----------------------------------------------------------
strRoot.Filter = Array("OrganizationalUnit") for each objChild in strRoot Call DATree() next
sub DATree() For each objUser
in objChild If objUser.class="user" then 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
Learning PointsNote 1: There are two main changes compared with example 1. At the bottom of the script is a sub routine. Once my example works, it would give me great
satisfaction if you amended the code to suit your Active Directory tasks. The other change is the Call statement : Call DATree(). Note 2: It's confession time. This script has a
terrible flaw, it only works for one level of OU. It won't drill down to nested OUs. Good news DA, not only spotted the fault, but also provided the code to correct the problem. It's a bit mean I
know, but you will have to wait for next week to get the extra code. Meanwhile, I challenge you to use my script as a test bed for trying out your ideas.
If you are looking for handy network utilities, try some of the free downloads at
Tools4Ever
Challenge 1: Add more users with "Year 2" in
their descriptions. See if you can change the script to reset their passwords. Challenge 2: Select different LDAP fields, for example DisplayName or sn, but be careful, don't get
too carried away. Challenge 3: Instead of resetting passwords, make the script alter the Description, for example change all 'Year 1' to 'Year 2'. Summary of Walking the Active Directory Tree
Getting a script to read not just one but all OUs was immensely satisfying, more so because of the help that I got from DA and Sean. Confession
time, this 'Walking the Active Directory Tree' script has a fatal flaw, it only looks at top level OUs. However, next week thanks to DA we will improve on the script, and thus enable it to check all OUs no matter how deep the nesting.
Their topics and material are ideal for getting you started with VBScript. The
videos are easy to follow and you can control the pace. Try their free demo material and then see if you want to buy the full package.
See more about VB Script Training CD.
|