How Can I Add All the Users from an Existing Active Directory Group to a New Group?

Hey, Scripting Guy! Question

Hey, Scripting Guy! How can I add all the users from an existing Active Directory group to a new group?

— TG

SpacerHey, Scripting Guy! AnswerScript Center

Hey, TG. So you have a group (we’ll call it Group A) and you want to create an exact replica of that group (we’ll call it Group B). If we were talking about Text File A and Text File B this would be an easy task: all you’d have to do is make a copy of File A and name that copy File B. Unfortunately, that won’t work with an Active Directory group. Although there is such a thing as a CopyHere method in ADSI, that method isn’t supported by Active Directory; if you try using CopyHere, you’ll just get back a “Not implemented” error message. Bummer.


So if we can’t just make a copy of Group A what can we do? Let’s think about our text files for a moment. Suppose for some reason we couldn’t use the file system to make a copy of File A; how else could we replicate that file? Well, one thing we could do would be to open that file, read in the contents, and then write those contents to our new file, File B. And that’s pretty much the same approach we’re going to use to add all the users from an existing Active Directory group to a new Active Directory group.


Let’s show you the script and then explain how it works. This script grabs a list of all the members of the Finance Managers group and then adds them to a brand-new group named Finance Department:

Const ADS_GROUP_TYPE_GLOBAL_GROUP = &H2

Set objOU = GetObject(“LDAP://OU=Finance, dc=fabrikam, dc=com”)
Set objOldGroup = GetObject(“LDAP://CN=Finance Managers, ou=Finance, dc=fabrikam, dc=com”)

Set objNewGroup = objOU.Create(“Group”, “Finance Department”)
objNewGroup.sAMAccountName = “financedept”
objNewGroup.groupType = ADS_GROUP_TYPE_GLOBAL_GROUP
objNewGroup.Set Info

For Each objUser in objOldGroup.Member
objNewGroup.Add “LDAP://” & objUser
Next


So how does this work? Well, we start by defining a constant named ADS_GROUP_TYPE_GLOBAL_GROUP and setting the value to &H2; we’ll use this later on to make our new group a global security group.


Next we create object references to two different objects. Object reference objOU binds to the Finance OU in Active Directory; this is the OU that will house our new security group. Meanwhile, objOldGroup binds to the Finance Managers group in Active Directory; as we already noted, this group has the list of users we want to add to the new group.


We then take a brief detour to create a new group named Finance Department; that’s what this block of code does:

Set objNewGroup = objOU.Create(“Group”, “Finance Department”)
objNewGroup.sAMAccountName = “financedept”
objNewGroup.groupType = ADS_GROUP_TYPE_GLOBAL_GROUP
objNewGroup.SetInfo

We won’t go into the details of what we’re doing here and why; for more information, see this section of the Microsoft Windows 2000 Scripting Guide.


We now have an existing group – Finance Managers – that has lots of members, and a new group – Finance Department – that doesn’t have any members. But we can change that: all we have to do is grab the membership from Finance Managers and copy it to Finance Department. Believe it or not, that only takes three lines of code:

For Each objUser in objOldGroup.Member
objNewGroup.Add “LDAP://” & objUser
Next

As it turns out, the Member attribute of a group contains a collection of all the members of that group. We can use a simple For Each loop to loop through the value of the Member attribute and return the distinguishedName (DN) attribute for each group member.


Note. The distinguishedName attribute will look similar to this:

CN=Ken Myer, ou=Finance, dc=fabrikam, dc=com

Fortuitously enough, the only information we need in order to add a user to a group is the ADsPath for that user. The ADsPath is a combination of the ADSI provider (in this case, LDAP://) plus the user’s DN. We now have both these pieces: the ADSI provider (which has to be LDAP:// seeing as how we’re working with Active Directory) and the user DN. In this line of code, we add the user to the new group, passing as the sole parameter to the Add method a combination of the ADSI provider and the user DN:

objNewGroup.Add “LDAP://” & objUser

We then continue on our merry way, looping through all the members of the Finance Managers group, grabbing the value of their distinguishedName attribute, and using that value to add the user (or computer or group or whatever) to the Finance Department group. The net result: despite the fact that we have no Copy command we’ve managed to duplicate the membership list from one group to another. Can human cloning via VBScript be far behind? (Let’s put it this way: originally there was only one Scripting Guy….)