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

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

  • Comments 3
  • Likes
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….)

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • This works great if there are at least 2 users in the "Old" group.  If there are not, there are problems.  This is what I used to get around that issue:

    ' oGroup1 = "Old" group, oGroup2 = "New" group

    cMembers = oGroup1.Member

    ' If there are no members in the group, you will receive an error because no collection exists.

    If IsEmpty(cMembers) Then

    WScript.Echo "Group " & oGroup1.Name & " is empty."

    ' If there is only one member, it will be a string instead of a collection

    ElseIf TypeName(cMembers) = "String" Then

    oGroup2.Add "LDAP://" & oGroup1.Member

    Else

    For Each oUser In oGroup1.Member

    oGroup2.Add "LDAP://" & oUser

    Next

    End If

  • Here is a script I wrote to do this in PowerShell. Note: it doesn't handle groups with more than 1500 members. I haven't had to do such a transfer, so I never accounted for it.

    function Transfer-GroupMembership {

     Param([string]$SourceGroup,[string]$TargetGroup)

     $objADSearch = New-Object System.DirectoryServices.DirectorySearcher

     $objADSearch.PageSize = 1000

     $objADSearch.SearchScope = "Subtree"

     $objADSearch.SearchRoot = New-Object System.DirectoryServices.DirectoryEntry

     $objADSearch.Filter = "(&(objectClass=group)(cn=$SourceGroup))"

     if(!($result = $objADSearch.FindOne())) { Write-Host "ERROR: No such group [$SourceGroup] found." -ForeGroundColor Red; return }

     $members = $result.Properties["member"]

     $objADSearch.Filter = "(&(objectClass=group)(cn=$TargetGroup))"

     if(!($result = $objADSearch.FindOne())) { Write-Host "ERROR: No such group [$TargetGroup] found." -ForeGroundColor Red; return }

     $group = $result.GetDirectoryEntry()

     $group.member += $members

     $group.CommitChanges()

     Write-Host "The $($members.Count) members from $SourceGroup were successfully added to $TargetGroup."

     }

  • This fails on line 6 for me -

    Windows Script Host

    ---------------------------

    Script: \\server\share\GroupCopy.vbs

    Line: 6

    Char: 1

    Error: Unspecified error

    Code: 80004005

    Source: (null)

    ---------------------------

    OK  

    ---------------------------

    I know this is quite an old post - but any chance of an update? Trying to run this on a 2008 R2 DC.