Hey, Scripting Guy! How Can I Copy Group Memberships from One Computer Account to Another in Active Directory Domain Services?

Hey, Scripting Guy! How Can I Copy Group Memberships from One Computer Account to Another in Active Directory Domain Services?

  • Comments 4
  • Likes

 

Hey, Scripting Guy! Question

Hey, Scripting Guy! I want to be able to copy the group memberships from one computer account in Active Directory Domain Services (AD DS) to another computer account in AD DS by using Windows PowerShell 2.0 and Active Directory cmdlets. It would be great if the script would also prompt me before copying each group to the targeted computer object. In this way, I could simply spin up a new computer account, clone group memberships, and be done with the operation. It would be way faster than manually typing in all the group memberships.

As it is now, I have to find a computer account, click to see the group memberships, flip over to the new computer, and then switch back to the original computer—and do this several dozen times until I have completed provisioning the new computer object. After I am done, I have to go through the entire operation a second time to ensure I got it right. If I get disturbed with a phone call, I have to start over again. Needless to say, it sometimes takes nearly an entire hour to complete the process, and I still sometimes mess it up. Help! We have reduced staff, and I am afraid to complain about not having enough time to complete my work. I will be your friend for life if you can show me how to do this quicker.

-- KB

 

Hey, Scripting Guy! Answer

Hello KB,

Microsoft Scripting Guy Ed Wilson here. Today is going to be an awesome day! I helped a network administrator in Florida solve a problem with his Outlook automation script that quit working when they migrated from Outlook 2003 to Outlook 2010 (it was a change to the object model). The script, unfortunately, was one that was used to tally absentee reports from an extremely large school, and so he was having to do things manually until the script was repaired. Craig and I have a meeting with our managers to wrap up the results from the 2010 Scripting Games (the 2010 Scripting Games were extremely successful so the meeting should be pleasant), and now I am about to make a new friend for life! WOOHOO!!! What an awesome way to start out the day. (Would you consider naming your first child after me? Think it over.)

KB, your idea sounds as if it would be a useful thing to do, so I decided to write a script called Copy-GroupMembersForComputer.ps1. The Copy-GroupMembersForComputer.ps1 script relies on the ActiveDirectory module, and therefore uses the Get-MyModule function to ensure the module is available. It then uses the Get-GroupsToMigrate function to copy groups from the reference computer. (This function will not be discussed in today’s article.) Each group is presented, which allows you to choose to copy the group or not. After you have cycled through the groups from the reference computer, the groups are added to the target computer. The complete Copy-GroupMembersForComputer.ps1 script is shown here.

Copy-GroupMembersForComputer.ps1

Param(
$identity="WinXP",
$target = "Win7-pc"
)
Function Get-MyModule
{
Param([string]$name)
if(-not(Get-Module -name $name)) 
{ 
if(Get-Module -ListAvailable | 
Where-Object { $_.name -eq $name })
{ 
Import-Module -Name $name 
$true
} #end if module available then import
else { $false } #module not available
} # end if not module
else { $true } #module already loaded
} #end function get-MyModule 
Function Get-GroupsToMigrate
{
Param($identity)
$array = @()
$groups = Get-AdComputer -Identity $identity -property "MemberOf" 
Foreach($group in $groups.memberOf)
{
$reply = Read-Host -Prompt "add group $($group) `r`ny / n"
if($reply -match "y") {$array +=$group}
} #end foreach
Return $array
} #end Get-GroupsToMigrate
# *** ENTRY POINT TO SCRIPT ***
If(-not (Get-MyModule -name "ActiveDirectory")) { exit }
$array = Get-GroupsToMigrate -identity $identity
Get-ADComputer -Identity $target | Add-ADPrincipalGroupMembership -MemberOf $array

To view and modify a computer’s group membership, you can use the Active Directory Users and Computers MMC. Right-clicking a computer and selecting the Member Of tab displays the computer’s group membership information, as shown in the following image.

Image of computer's group membership information

Once the ActiveDirectory module has been loaded, the Get-GroupsToMigrate function is called. The reference computer is passed via the –identity parameter. An array will be used to hold the groups that are to be migrated to the target computer. The Get-ADComputer cmdlet is used to retrieve the groups stored in the MemberOf Active Directory attribute. Because the MemberOf property is not automatically retrieved, it must be specifically requested via the –property parameter. This is the same behavior as the Get-ADUser cmdlet that was looked at yesterday.

The groups that the computer object is a member of are stored in the $groups variable. This section of the Get-GroupsToMigrate function is shown here:

 

Function Get-GroupsToMigrate

{

Param($identity)

$array = @()

$groups = Get-AdComputer -Identity $identity -property "MemberOf"

To display each of the groups, the Foreach statement is used to walk through the collection of groups. The Read-Host cmdlet is used to prompt the user to keep or discard the group. The reply to the prompt is stored in the $reply variable. If the reply contains the letter “y,” the group is added to the array stored in the $array variable. After all of the groups have been processed, the array containing selected group names is returned to the calling code. This section of the script is shown here:

 

Foreach($group in $groups.memberOf)

{

$reply = Read-Host -Prompt "add group $($group) `r`ny / n"

if($reply -match "y") {$array +=$group}

} #end foreach

Return $array

} #end Get-GroupsToMigrate

 

When the script is run inside the Windows PowerShell ISE, the Read-Host cmdlet produces a popup dialog box, which is shown in the following image.

Image of dialog box produced by Read-Host cmdlet

If the script is run inside the Windows PowerShell console, the Read-Host cmdlet will pause the script execution, as shown in the following image.

Image of paused script execution

The calling code stores the returned array of groups in the $array variable:

 

$array = Get-GroupsToMigrate -identity $identity

After the groups have been selected and stored in the $array variable, the Get-ADComputer cmdlet is used to retrieve the target computer. The resulting computer object is piped to the Add-ADPrincipalGroupMembership cmdlet, which is passed the array of groups. This section of the script is shown here:


Get-ADComputer -Identity $target | Add-ADPrincipalGroupMembership -MemberOf $array

In processing the groups, I decided I did not want to select the appB group. The resulting groups are shown in the following image.

Image of resulting groups

KB, that is all there is to using Active Directory cmdlets to migrate group memberships. Active Directory Week will continue tomorrow when we will talk about finding groups that are unused.

We would love you to follow us on Twitter or Facebook. If you have any questions, send email to us at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

 

Ed Wilson and Craig Liebendorfer, Scripting Guys, Active Directory, groups


Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Hey Scripting Guys, i am looking for a vbscript which will copy the group membership from one system to another & also it should run from a system which is not on domain, i tried the below option but its not working getting error "The specified domain either does not exist or could not be contacted", any suggestions please. Thanks

    strComputer1 = "WINXP"

    strComputer2 = "WIN7"

    'Bind to clone user object.

    Set objClone = GetObject("LDAP://AD.TEST.COM" & strComputer1)

    ' Bind to new user object.

    Set objComputer = GetObject("LDAP://AD.TEST.COM" & strComputer2)

    ' Enumerate direct group memberships of clone user.

    For Each objGroup in objClone.Groups

    ' Check if new user already a member.

    If (objGroup.IsMember(objComputer.AdsPath) = False) Then

    ' Add new user to the group.

    objGroup.Add(objComputer.AdsPath)

    End If

    Next

  • @Harish

    As was posted in the forums.  You cannot generally migrate group membership between stand alone workstations (workgroup) as the SIDs will not match.  A SID is dependent on the domain it is defined in.  Each workgroup machine is in a separate domain.  That is one major difference between a workgroup and an NT domain. AN NT domain paces all workstations and server domains into a single domain trust where domain SIDS are recognized by every host.  Note that the local SIDs (local users and groups) are still not fully trusted by the domain or by other hosts.  They are only trusted within the domain context where they are defined.

    Part of each SID is a domain specific number or "authority"

    technet.microsoft.com/.../cc962011.aspx

    Here is a workgroup/workstation SID:

    S-1-5-21-1343024091-329068152-1801674531-1027

    Here is a SID from another workstation in the same workgroup.

    S-1-5-21-57989841-2147137141-725345543-1027

    Note that the last four digits are the enumerated account ID starting at 1000 for local accounts.  The numbers below 1000 are reserved for system accounts like the administrator account.

    The second SID has the same last four digits because I chose it that way to make a point.  The middle digits after the common S-1-5-21 are different.  They are the sub authority portion of the SID.  The workstation will only allow SIDs from its own domain or, if it is in a domain, it will allow SIDs from any trusted domain.  By default the local domain is always trusted.  Joining a domain means creating a trust between the machine and the domain.  The trust is created by trading security tokens and other info.

    So - no - you cannot copy group membership from local group to another between machines.  You can only copy locally.

  • Wont this forget the Primary group? I believe memberof does not return the primary group of a computer

    Although in your exampke (and normally) the primary group will be Domain Computers (or Domain Controllers) which of course will already be present on the destination computer account

  • thanks