How Can I List All the Sites in Active Directory as well as All the Servers in Those Sites?

Hey, Scripting Guy! Question

Hey, Scripting Guy! How can I list all the sites in Active Directory as well as all the servers in those sites?

— DW

SpacerHey, Scripting Guy! AnswerScript Center

Hey, DW. You know, you’re putting us to the test here. Ask us a question about users and groups and we’re fine; we at least kind of understand what users and groups are all about. Ask about computer accounts or OUs; hey, no problem. When it comes to things like sites and site links and stuff like that, however, well, then we start to worry; after all, we’re never really convinced that we even know what those things are, let alone how you can script them.


But would the Scripting Guys ever let a total lack of knowledge and understanding stop them? Of course not. Here’s a script that lists all of the sites in Active Directory, along with the servers found in each of those sites:

On Error Resume Next

Set objRootDSE = GetObject(“LDAP://RootDSE”)
strConfigurationNC = objRootDSE.Get(“configurationNamingContext”)

strSitesContainer = “LDAP://cn=Sites,” & strConfigurationNC
Set objSitesContainer = GetObject(strSitesContainer)
objSitesContainer.Filter = Array(“site”)

For Each objSite In objSitesContainer
Wscript.Echo objSite.CN
strSiteName = objSite.Name
strServerPath = “LDAP://cn=Servers,” & strSiteName & “,cn=Sites,” & _
strConfigurationNC
Set colServers = GetObject(strServerPath)

For Each objServer In colServers
WScript.Echo vbTab & objServer.CN
Next
Wscript.Echo
Next


So what are we doing here? (Actually, that wasn’t a rhetorical question, we were hoping someone would explain it all to us!) We begin by using these two lines of code to bind to the Active Directory root and then to the Configuration container (configuringNamingContext):

Set objRootDSE = GetObject(“LDAP://RootDSE”)
strConfigurationNC = objRootDSE.Get(“configurationNamingContext”)

Why do we start out like this? Well, the Configuration container holds information about the physical structure and layout of Active Directory; that’s where we’ll find information about sites and about the servers assigned to each site. By binding to the Active Directory root (rootDSE) and then using the Get method to retrieve the configurationNamingContext we can get the Active Directory path to the Configuration container regardless of the name of our domain.







Note. What does that mean? For one thing, it means you can use this script as-is, without having to change fabrikam.com to the name of your domain; as you can see, we don’t even reference fabrikam.com (or any other domain name) anywhere in the script.



Our next step is to retrieve a collection of all the Active Directory sites. That’s what we do here:

strSitesContainer = “LDAP://cn=Sites,” & strConfigurationNC
Set objSitesContainer = GetObject(strSitesContainer)
objSitesContainer.Filter = Array(“site”)

In the first line we construct the ADsPath to the Sites container, combining LDAP://cn=Sites and the configurationNamingContext. We use the GetObject method to bind to the Container, then apply a Filter that limits items in the collection to Site objects. The net result: objSitesContainer will now contain a collection of all our Active Directory sites.


OK, so maybe this isn’t as difficult as we thought it would be. Next we set up a For Each loop to walk through the collection of sites. Inside that loop we echo the CN for the first site in the collection, then store the site Name (which will be something like CN=Default-First-Site-Name) in the variable strSiteName:

Wscript.Echo objSite.CN
strSiteName = objSite.Name

As it turns out, each Active Directory site has a Servers container, and each Servers container holds a list of the servers assigned to that site. In order to bind to that Servers container for our first site we use this line of code to construct an ADsPath, a path we store in the variable strServerPath:

strServerPath = “LDAP://cn=Servers,” & strSiteName & “,cn=Sites,” & _
strConfigurationNC

Once we have the ADsPath we can then bind to the Servers container for the first site using this line of code:

Set colServers = GetObject(strServerPath)

We’re on a roll now. Next we set up a second For Each loop that walks through the collection of items found in the Servers container. For each server in the collection we do nothing more than echo back the server CN:

For Each objServer In colServers
WScript.Echo vbTab & objServer.CN
Next

Oh, OK: we also put a tab character (vbTab) in front of the server name. You’ll see why we do that when you take a look at the sample output.


And that’s it: we’ve now echoed back the name of the first site as well as all the servers assigned to that site. We then loop around and repeat the process with the second site in the collection. This continues until we’ve worked with all the sites and echoed back the names of all the servers in those sites. When we’re all done we should have output similar to this:

Default-First-Site-Name
atl-dc-01
atl-dc-02

European-Site
lon-dc-01
lon-dc-02
par-dc-01
bru-dc-01
bru-dc-02


Not bad, huh? And just imagine what a cool script we could have written had we actually known what we were doing!