Mr. Script

Tap the LDAP Provider to Plumb Active Directory

This month, Chris takes a final dive into the depths of ADSI and shows how it works with LDAP to make Active Directory information easily accessible.

Whenever possible, I like to SCUBA dive. I particularly like to go to the Caribbean during winter — there’s nothing quite like coming home to freezing temperatures with a sunburn and mosquito bites. On a recent excursion to the Bahamas, my dive buddy had a bit of difficulty downloading the dives from his dive computer to his Windows dive log software. It seemed that the new version of the software didn’t like communicating directly with his computer’s serial port. It wanted another piece of hardware called a “memo mouse.” Dives can then be transferred from the memo mouse to the dive log.

In true geek fashion, this got me thinking about my series on ADSI and how it solved a similar problem that had heretofore plagued NT administrators: NT always needed a “go-between” for scripting many of its administrative tasks, and this could be a real pain in the neck! Thanks to ADSI, this is no longer the case.

To finish up our series on ADSI (for now), we’re going to look at the LDAP provider and some of the functionality it provides.

Anybody Got a Light?
Rather than monopolize my limited space explaining all the ins and outs of LDAP and Active Directory (which are better explained in countless articles in previous issues of this fine publication. See “Additional Information.”), I thought I’d provide a brief overview and then “dive” right into explaining how we use LDAP to access information in our ADs — explaining the sticky points along the way.

LDAP stands for Lightweight Directory Access Protocol and it’s an industry standard for storing user, organization and application information. This information can then be accessed via any LDAP-enabled client.

Now, LDAP is not ADSI. It’s simply the protocol used to access AD and query and modify its contents. Using ADSI and the LDAP provider, we can access Microsoft Exchange information for creating mailboxes and managing distribution lists, use ActiveX Data Objects (ADO) to query the LDAP directory, and much more. In fact, the list is nearly endless. But because we don’t have that kind of time, let’s start with a bit of user management.

Thank Goodness for Small Favors
The good news is that once you’ve bound to AD using the LDAP provider, the procedures for adding, removing and modifying users and groups are similar to the methods previously discussed using the WinNT provider.

'AddADSIUser.vbs
Dim objContainer, clsUser
Set objContainer=GetObject("LDAP://MyDomain.com")
Set clsUser=objContainer.Create("user","CN=chrisb")
clsUser.Put "samAccountName","chrisb"
clsUser.SetInfo
clsUser.AccountDisabled=False
clsUser.SetInfo

Looks familiar, doesn’t it? However, there are a few differences that bear explaining. First, you’ll notice that I bound to a domain rather than a specific Domain Controller. Remember that with AD, there are no PDCs and BDCs — only DCs. If you try to bind to a particular computer and it happens to be off line, the bind operation will fail and your script will abort. If you perform a “serverless” binding to a domain, you’ll always succeed as long as at least one Domain Controller is on line (and if you don’t have at least one Domain Controller on line, you don’t really have a domain, do you?). Another issue worth noting is that we wouldn’t usually add a user to the “root” of a domain. Rather, we’d put him in an OU (Organizational Unit) — more on this below. You’ll also note that in line 5 of the script, I created an entry for “samAccountName.” This allows the user to be “seen” by down-level NT domains. Finally, we “activate” the account by telling AD that the account is not disabled (kind of backward, isn’t it?). The first “SetInfo” method creates the account. The second one “enables” it. Both are required.

We can also bind to a particular user and manipulate any or all of its properties.

'SetADSIUserProps.vbs
Dim objUser
Set objUser=
GetObject("LDAP://CN=chrisb,DC=MyDomain,DC=com")
objUser.FullName="Chris Brooke"
objUser.AccountDisabled=True
Wscript.Echo objUser.LastLogin
etc.

Now, this part should look really familiar! Once ADSI has bound to an object, manipulating it is (usually) simple. There are some properties that are unique to NT domains that the LDAP provider can’t “see,” but — for the most part — the scripts I wrote when I discussed the WinNT provider can be substituted here, with only the GetObject operation being different.

I Add ’em, You Delete ’em
Let’s assume we’ve got another “chrisb” in the domain, and he’s a real troublemaker. We want to go ahead and delete this guy. Since AD is hierarchical in nature, let’s make sure we’re deleting the right “chrisb” by including his OU.

'KillTheUser.vbs
Dim objContainer
Set objContainer=
GetObject(
"LDAP://OU=troublemakers,DC=MyDomain,DC=com")
objContainer.Delete "user","CN=chrisb"

Simple, yet effective. But what if you need to delete an entire “branch” of your AD “tree”? Why would you need to do this? Well, maybe when you built the domain schema, you expected to have a sales department in both the Atlanta and Oklahoma City offices. Before you could even start hiring for these positions, management came down and declared that all sales would be handled out of Oklahoma City. Good housekeeping requires that we remove the Atlanta “sales” OU.

'KillAtlantaSales.vbs
Dim objContainer
Set objContainer=
GetObject(
"LDAP://OU=sales,DC=Atlanta,DC=MyDomain,DC=com")
ObjContainer.DeleteObject (0)

All gone.
As with the other ADSI providers, I’ve only scratched the surface of what you can accomplish using the LDAP provider. Perhaps one day I’ll revisit this topic and go into further detail.

Until then, be sure to breathe continuously, maintain proper buoyancy and always control your ascent rate. Oh, wait, those are the SCUBA rules. I must have been daydreaming. Come to think of it, do we even have rules for NT administration? Hmm… Oh yeah! Keep ’em secure, keep ’em running, and don’t touch the boss’ Dilbert calendar.

How’s that for a credo?

About the Author

Chris Brooke, MCSE, is a contributing editor for Redmond magazine and director of enterprise technology for ComponentSource. He specializes in development, integration services and network/Internet administration. Send questions or your favorite scripts to chrisb@componentsource.com.

comments powered by Disqus

Reader Comments:

Mon, Jun 13, 2005 Anonymous Anonymous

Fine Overview!

Fri, May 14, 2004 Jonathan Swartz

With this article I was able to build an entire VB .NET tool that aids in maintaining "stale" accounts or accounts that have been disabled for more than 14 days.

However, I have run into one problem. If I use this tool to disable an account, - and then, for whatever reason enable the same account from the AD Users and Computers Console - the computer is no longer able to log into the domain. - Error indicates that the computer cannot locate a valid account on the domain. - Which forces us to "rejoin" the computer to the domain. - Very strange.

Dim StrNode
Dim retval
Dim User
Dim Container
Dim ObjRootDSE
Dim StrDNSDomain
Dim objtrans
Dim strNetBIOSDomain
Dim strcomputerDN
Dim Objcomputer

StrNode = Microsoft.VisualBasic.Right(Navigator2.SelectedNode.Text, Len(Navigator2.SelectedNode.Text) - 3)
ObjRootDSE = GetObject("LDAP://RootDSE")
StrDNSDomain = ObjRootDSE.Get("defaultNamingContext")
objtrans = CreateObject("NameTranslate")
objtrans.Init(3, StrDNSDomain)
objtrans.Set(1, StrDNSDomain)
strNetBIOSDomain = objtrans.Get(3)
strNetBIOSDomain = Microsoft.VisualBasic.Left(strNetBIOSDomain, Len(strNetBIOSDomain) - 1)
objtrans.Init(1, strNetBIOSDomain)
objtrans.Set(3, strNetBIOSDomain & "\" & StrNode & "$") 'strcomputername)
strcomputerDN = objtrans.Get(1)
Objcomputer = GetObject("LDAP://" & strcomputerDN)
Objcomputer.AccountDisabled = True
Objcomputer.SetInfo()

At first, I thought it may be a replication issue. - but verified that all the local "DC"s indicated that the account was enabled.

Wed, Jan 28, 2004 Anonymous Anonymous

Your code examples don't work in script debugger which means they are worthless to someone like me who is trying to learn scripting code.

Add Your Comment Now:

Your Name:(optional)
Your Email:(optional)
Your Location:(optional)
Comment:
Please type the letters/numbers you see above

Redmond Tech Watch

Sign up for our newsletter.

I agree to this site's Privacy Policy.