Recipe15.24.Script: Displaying the Structure of a Forest


Recipe 15.24. Script: Displaying the Structure of a Forest

Do you know the structure of your Active Directory forest? You could use a tool such as ADSI Edit and expand all of the OUs and containers in each domain, but if you have a lot of OUs, this would be very time consuming.

With a pretty simple script, you can enumerate all the domains, OUs, and containers in a forest. And you don't need any type of privileged rights to do it. Here is the script:

' This code prints out the forest tree hierarchy     ' BEGIN SECTION 1 set objRootDSE = GetObject("LDAP://RootDSE") strBase    =  "<LDAP://cn=Partitions," & _               objRootDSE.Get("ConfigurationNamingContext") & ">;" strFilter  = "(&(objectcategory=crossRef)(systemFlags=3));" strAttrs   = "name,trustParent,nCName,dnsRoot,distinguishedName;" strScope   = "onelevel" set objConn = CreateObject("ADODB.Connection") objConn.Provider = "ADsDSOObject" objConn.Open "Active Directory Provider" set objRS = objConn.Execute(strBase & strFilter & strAttrs & strScope) objRS.MoveFirst ' END SECTION 1     ' BEGIN SECTION 2 set dicSubDomainTrue = CreateObject("Scripting.Dictionary") set dicDomainHierarchy = CreateObject("Scripting.Dictionary") set dicDomainRoot = CreateObject("Scripting.Dictionary") ' END SECTION 2     ' BEGIN SECTION 3 while not objRS.EOF     dicDomainRoot.Add objRS.Fields("name").Value, objRS.Fields("nCName").Value    if objRS.Fields("trustParent").Value <> "" then       dicSubDomainTrue.Add objRS.Fields("name").Value, 0       set objDomainParent = GetObject("LDAP://" & _                             objRS.Fields("trustParent").Value)       dicDomainHierarchy.Add objRS.Fields("name").Value, _                              objDomainParent.Get("name")    else        dicSubDomainTrue.Add objRS.Fields("name").Value, 1    end if    objRS.MoveNext wend ' END SECTION 3     ' BEGIN SECTION 4 for each strDomain in dicSubDomainTrue   if dicSubDomainTrue(strDomain) = 1 then       DisplayDomains strDomain, "", dicDomainHierarchy, dicDomainRoot   end if  next     Function DisplayDomains ( strDomain, strSpaces, dicDomainHierachy, dicDomainRoot)    WScript.Echo strSpaces & strDomain    DisplayObjects "LDAP://" & dicDomainRoot(strDomain), "  " & strSpaces    for each strD in dicDomainHierarchy       if dicDomainHierarchy(strD) = strDomain then          DisplayDomains strD, "  " & strSpaces, dicDomainHierarchy, _                         dicDomainRoot       end if    next End Function     ' DisplayObjects takes the ADsPath of the object to display  ' child objects for and the number of spaces (indention) to ' use when printing the first parameter Function DisplayObjects( strADsPath, strSpace)    set objObject = GetObject(strADsPath)    Wscript.Echo strSpace & objObject.Name    objObject.Filter = Array("container","organizationalUnit")    for each objChildObject in objObject       DisplayObjects objChildObject.ADsPath, strSpace & " "    next  End Function     ' END SECTION 4

This script is a little more complicated than most of the scripts in this book, but you should be able to handle it. Let's walk through it.

In SECTION 1, I set up an ADO query to find all domains in a forest. This is a little trickier than you might imagine. Domains are represented in the Configuration naming context as crossRef objects; but since LDAP referrals can also be created as crossRef objects, I have to look for a specific type of crossRef object, ones that have a systemFlags attribute equal to 3. This signifies Active Directory domains.

In SECTION 2, I set up three dictionary objects that I'll use throughout the script. Here is a brief overview of each dictionary object:


dicSubDomainTrue

This is used to identify whether domains contain subdomains. The keys will be domain names and values will be 0 if the domain has no subdomains or 1 if it does. This dictionary will be used later to enumerate the domain hierarchy.


dicDomainHierarchy

This is used to store the parent domain of a subdomain. The keys will be the domain names and the values will be each domain's parent domain name.


dicDomainRoot

This is used to store the default naming context for each domain. The keys will be the domain names and the values will be the DN of each domain's root.

In SECTION 3, I enumerate over each of the values returned by the ADO query started in SECTION 1. I first set the domain root in the dicDomainRoot dictionary. Next, I evaluate if the trustParent attribute contains a value. If it does, then I know the domain I'm currently on has a parent domain. If TRustParent does not contain a value, I know that it is the root domain of the forest or domain tree. If it does have a parent, I set an entry for the domain in dicSubDomainTrue to 0 to signify that I haven't found a subdomain for this domain yet. I then set an entry in dicDomainHierarchy to contain the domain and parent domain as key value pairs.

At this point, I've set up all the data structures I need to start printing out the structure of a forest. In SECTION 4, I start iterating over each domain in the forest. I'll enter only the domains that are roots of their forests. Then I call the DisplayDomains function. DisplayDomains prints the name of the current domain and calls DisplayObjects to print each container and organizationalUnit object in the domain. This effectively prints the structure of that domain. After it is done with that, it starts to loop over the keys in dicDomainHierarchy to find all child domains that have the current domain set as their parent. If it finds a subdomain of the current domain, it calls DisplayDomains (recursively) on that domain and the process repeats.



Windows Server Cookbook
Windows Server Cookbook for Windows Server 2003 and Windows 2000
ISBN: 0596006330
EAN: 2147483647
Year: 2006
Pages: 380
Authors: Robbie Allen

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net