The below two scripts can be used to create custom commands for copying group members from one group to another. One of the commands can be executed on an AD group to copy its members. The other one can be executed on another group to paste the copied members.
For more information on creating custom commands, see Create a Custom Command. Both the commands must be configured for the Group object type.
To add scripts to custom commands, use the Run a program or PowerShell script action.
To pass group members between the groups, the 1st custom command saves GUIDs of members of the source group to the CustomAttributeBinary1 property of the user who invokes the custom command. The 2nd command reads the GIUDs from the same property and adds the objects whose GUIDs are specified to the destination group. Each GUID is represented as an array of 16 bytes (Byte[]), and the property will store an array of arrays of bytes.
CustomAttributeBinary1 is one of Adaxes virtual properties for binary data. Such properties are not stored in Active Directory, but you can use them the same as any other properties of AD objects.
Script for copying group members:
# Get GUIDs of direct members of the group
try
{
$sourceMemberGuids = $Context.TargetObject.GetEx("adm-DirectMembersGuid")
}
catch
{
$Context.LogMessage("The target group does not have members. Nothing to copy.", "Warning")
return
}
# Build a single-dimension array of member GUIDs
$totalBytes = $sourceMemberGuids.Count * 16
$result = New-Object 'System.Collections.Generic.List[System.Byte]' $totalBytes
foreach ($memberGuidBytes in $sourceMemberGuids)
{
$result.AddRange($memberGuidBytes)
}
# Save the GUIDs to the adm-CustomAttributeBinary1 virtual property user who invokes the script
$Context.Initiator.UserAdsObject.Put("adm-CustomAttributeBinary1", $result.ToArray())
$Context.Initiator.UserAdsObject.SetInfo()
Script for pasting group members:
# Get an array of member GUIDs
try
{
$sourceMemberGuids = $Context.Initiator.UserAdsObject.Get("adm-CustomAttributeBinary1")
}
catch
{
$Context.Cancel("Failed to get member GUIDs.")
return
}
# Calculate the number of GUIDs
$totalBytes = $sourceMemberGuids.Length
# Make sure that the total number of bytes is a divisible of 16
$remainder = 0
[System.Math]::DivRem($totalBytes, 16, [ref] $remainder)
if ($remainder -ne 0)
{
$Context.Cancel("Unexpected data length! Exiting.")
return
}
$membersToAdd = New-Object "System.Collections.Generic.HashSet[System.Guid]"
for ($i = 0; $i -lt ($totalBytes / 16); $i++)
{
$bytes = [System.Guid]::Empty.ToByteArray()
[System.Array]::Copy($sourceMemberGuids, $i * 16, $bytes, 0, 16)
$guid = New-Object "System.Guid" (,$bytes)
$membersToAdd.Add($guid)
}
# Get GUIDs of the current group members
try
{
$memberGuids = $Context.TargetObject.GetEx("adm-DirectMembersGuid")
}
catch
{
$memberGuids = @()
}
# Adjust the list of members that will be added to the target group
foreach($memberGuidBytes in $memberGuids)
{
$guid = New-Object "System.Guid" (,$memberGuidBytes)
if (-not($membersToAdd.Contains($guid)))
{
continue
}
$membersToAdd.Remove($guid) # already a member of the group
}
# Add new members to the group
foreach($memberGuid in $membersToAdd)
{
$memberGuid = $memberGuid.ToString("B")
$memberPath = "Adaxes://<GUID=$memberGuid>"
try
{
$Context.TargetObject.Add($memberPath)
}
catch
{
if ($_.Exception.InnerException.ErrorCode -eq -2147019886)
{
continue
}
$Context.LogMessage($_.Exception.Message, "Error")
}
}
$Context.LogMessage("Finished copying members to the group.", "Information")
We opened a support ticket to help you with the script. An email was sent to the address of your account.