Hey, Scripting Guy! Question

Hey, Scripting Guy! How can I remove all the members of a group unless that member is another group? I need a group that has only other groups as members, no individual users, computers, contacts, etc.

-- TH

SpacerHey, Scripting Guy! AnswerScript Center

Hey, TH. You’ll have to be patient with us this morning; after all, we’re sending this column over the Internet and, well, you know how long that can take.

What’s that? Well, to be honest, we were also under the mistaken impression that things transmitted over the Internet arrive almost instantly. Yesterday, however, the Scripting Guy who writes this column had to arrange for the Scripting Son’s SAT scores (which, while good, were nowhere near as good as his Dad’s SAT scores) to be sent to the University of Idaho. After filling out the online form, he was given a choice of shipping options: Regular Shipping, or Over the Internet. What the heck, he thought. Let’s send the scores over the Internet and get this wrapped up as quickly as possible.

You’d think that, by now, the Scripting Guy who writes this column would be used to being wrong. Nevertheless, he was still surprised by the estimated delivery time to send SAT scores over the Internet: 1 to 2 weeks. Of course, for $26.50 he could request Rush Shipping; in that case, the scores would be sent by courier within two business days.

In other words, it’s way faster to print out SAT scores, have a courier pick them up, have those scores flown across the country to Idaho, and then have another courier hand-deliver the scores to the University of Idaho than it is to simply send those scores electronically over the Internet.

Hey, who said, “The SAT people must be using Microsoft software”? Come on, be nice; as hard as it might be to remember, the Scripting Guys do work for Microsoft, you know.

Speaking of which, we probably should actually do a little work for Microsoft rather than spend all day trying to send SAT scores over the Internet. In other words, we should probably see if we can figure out how to write a script that removes everyone except other groups from an Active Directory group. And, hopefully, take less than 1 to 2 weeks to figure it out.

Never mind; turns out it only took 1 to 2 minutes to figure that out:

Set objGroup = GetObject _
    ("LDAP://CN=Finance Department,OU=Finance,DC=fabrikam,DC=com")

For Each strUser in objGroup.Member
    Set objMember = GetObject("LDAP://" & strUser)
    If objMember.Class <> "group" Then
        objGroup.Remove(objMember.ADsPath)
    End If
Next

We hope you weren’t expecting a really complicated script, TH; as you can see, this is actually a pretty simple little task to achieve. For example, to kick things off all we have to do is bind to the group in question; in this case, that’s a group named Finance Department that’s located in the Finance OU of fabrikam.com:

Set objGroup = GetObject _
    ("LDAP://CN=Finance Department,OU=Finance,DC=fabrikam,DC=com")

As you probably know, it’s a simple enough matter to enumerate all the members of an Active Directory group; all you have to do is bind to the group (which we just did) and then loop through all the values stored in the Member attribute. And yes, that attribute really should be named Members, with an s on the end; after all, groups typically have more than one member. But for some reason, it’s the Member attribute (no s on the end) instead. Go figure.

Regardless, we can enumerate all the members of our group simply by setting up a For Each loop that looks like this:

For Each strUser in objGroup.Member

Now it gets just a little bit tricky. As we noted, all the members of a group are stored in the Member attribute; to be more specific, the distinguished name of each group member is stored in the Member attribute. In other words, the values stored in the Member attribute look something like this:

CN=Ken Myer,OU=Finance,DC=fabrikam,DC=com 
CN=Jonathan Haas,OU=Finance,DC=fabrikam,DC=com
CN=Pilar Ackerman,OU=Human Resources,DC=fabrikam,DC=com

Is that a problem? Well, for us it is; needless to say, it can be pretty tough (especially for a script) to just look at a distinguished name and determine whether or not we’re dealing with a user, a computer, a group, or whatever. That’s why the first thing we do inside our For Each loop is this:

Set objMember = GetObject("LDAP://" & strUser)

What we’re doing here is using the GetObject function and the user’s distinguished name (which is stored in the variable strUser) to bind to the Active Directory account for the first member in the group. Why do we want to do that? Well, as it turns out, all Active Directory objects have a Class attribute that indicates the class the object belongs to: a user account has a Class attribute equal to user, a computer account has a Class attribute equal to computer, and so on. How do we know if a particular group member is (or isn’t) another group? By using this line of code:

If objMember.Class <> "group" Then

Suppose the Class attribute is equal to group. Well, that’s no big deal; in that case we simply zip back to the top of the loop and repeat this process with the next group member.

Now, suppose that the Class attribute is not equal to group (that is, we’re dealing with a user or computer or whatever). That can mean only one thing: this member needs to be removed from the group. (Remember, we’re deleting everyone and everything that isn’t another group.) Therefore, we simply grab the ADsPath property for this particular object and pass the value to the Remove method:

objGroup.Remove(objMember.ADsPath)

Just like that, the member will be removed from the group. And then we once again zip back around to the top of the loop and try this all over again with the next group member. When all is said and done, the only members left in our group will be other groups.

Which is just exactly what we wanted to happen.

By the way, we have a postscript to today’s column. After entering his credit card number (yes, it costs money to have scores electronically sent over the Internet) the Scripting Guy hit the Submit button and asked that the scores be sent. At that point it wasn’t clear what happened, if anything. The process seemed to work, but the University of Idaho did not appear in the list of schools that the Scripting Son’s SAT scores had been sent to. The Scripting Guy who writes this column wasn’t sure what to make of that; after all, if it takes up to 2 weeks to send scores over the Internet who knows how long it might take to update a Web page.

Nevertheless, the Scripting Guy who writes this column decided to contact the help desk and ask about that. Once again he filled out the online form and clicked Submit. Here’s the message he got back:

Thank you!
Your information has been successfully submitted.

Forms which have not been completed in their entirety cannot be processed. Please allow 2—4 weeks for requests to be processed.

If we’re reading that correctly, in a month or so he can expect to get a reply to his question.

Isn’t technology a wonderful thing? Imagine how long this process would take if we had to do what our ancestors did and pick up the phone and ask a real person a question?

Oh, well. Tune in tomorrow – er, tune in next summer and we’ll let you know how this all turned out.