Office 365 Groups, or “Unified Groups” to their friends, have been a confusing Office 365 feature from an administrative perspective for as long as they’ve been around. Users can create them all willy-nilly (unless you disable that), the SharePoint sites they create don’t show up in the SharePoint Admin Center (until you use the new one), the list goes on and on. Another frustrating part of Groups is that you can’t do any nesting, of any kind. You can’t put a Unified Group in an Azure AD Security Group, or vice versa. You can’t put a SharePoint Group in a Unified Group either. Because of these limitations it’s very tough to reuse group membership. You can’t create an HR Azure AD Security Group and drop it into the HR Benefits Unified Group or the HR Hiring Unified Group. Now, the obvious question is, “If these two Unified Groups have the same membership why are they two groups instead of one?” Good question, fair reader. Sometimes it just works out that way. Sometimes the AD Security Group would only be a subset of the users in the Unified Group in question. Regardless, this question came up on a customer call and I was challenged to find a way to ease the administrative burden of manually adding the same users to multiple Unified Groups. What was my answer, “Of course I can do it, with PowerShell!” Sometimes I answer without thinking first.
I had used the PnP PowerShell in the past to get a list of all of the Unified Groups in a tenant, so I was pretty sure it could be done. I whipped out Get-Command and listed all the cmdlets that contained the noun “UnifiedGroup.”
Get-Command -Noun *unifiedgroup*
That exposed two cmdlets I’d need: Get-PnPUnifiedGroupOwners and Get-PnPUnifiedGroupMembers. That’s good. But there were no corresponding “Set” cmdlets. That’s bad. Normally this is where I’d panic. Instead, I took a deep breath and instead of panicking, I typed Get-Command -ParameterName members. Low and behold, Get-Command blessed me with New-PnPUnifiedGroup and Set-PnPUnifiedGroup. We retrieve the list of Members with Get-PnPUnifiedGroupMembers but we set them with Set-PnPUnifiedGroup –Members. Not totally consistent, but I can work with that.
From past experience I knew I had to be connected to the Microsoft Graph to use the Unified Group cmdlets, so I authenticated against the Graph so I could start poking around.
Connect-PnPOnline –Graph
If you haven’t connected to the Graph before, hold onto your hats. It’s different than what you’re used to. You’ll be given a code to register with the Graph that allows the PnP to query it. It feels weird, but everything is working correctly.
Once I was connected to the Graph I ran Get-PnPUnifiedGroupMembers to see what the output looked like. It gave me back a collection of objects that corresponded to the users that were members of that Unified Group. Fair enough.
We can store them in a variable for use later. Now, how do we assign membership? help Set-PnPUnifiedGroup –Examples didn’t provide a lot of help. It only showed adding a single Owner. But it did show me that the cmdlet was expecting the parameter to be a string, and that string needed to be the UPN of the user I wanted to add. I can work with that too.
The mechanics of saving out the list of users and owners and assigning them to another group was a little tricky, but not bad. I walked through the output of Get- and wrote the UPNs of each object to a new collection that I would then pass on to Set-. It looks like this:
$members = Get-PnPUnifiedGroupMembers -Identity $source
$members | ForEach-Object -begin {$memberlist = @() } -process {$memberlist += $($_.UserPrincipalName) }
Set-PnPUnifiedGroup -Identity $destination -Members $memberlist -Owners $ownerlist
The only sticking point was that doing it that way would overwrite whatever Members or Owners the Destination Group already had. To handle that I created a boolean variable, $mergeusers, that I could set to $true or $false depending on whether I wanted to clobber the existing users or not. If I did not want to clobber them I used the following code to merge the current Members of Destination with the Members of Source:
$membersDest = Get-PnPUnifiedGroupMembers -Identity $destination
$members = $members + $membersDest
Then later when I write the users in $members to the Destination Group it has both sets of Members.
I added some very, very simple error handling so that another human has a chance of running it. This is what I ended up with:
# Set some values
# use Get-PnPUnifiedGroup to get Unified Group names
# Name of Unified Group whose owners and membership we want to copy
$source = "Regulations"
# Name of Unified Group whose owners and membership we want to populate
$destination = "Empty"
# Whether to overwrite Destination membership or merge them
$mergeusers = $false
# Check to see if PnP Module is loaded
$pnploaded = Get-Module SharePointPnPPowerShellOnline
if ($pnploaded -eq $false) {
Write-Host "Please load the PnP PowerShell and run again"
Write-Host "install-module SharePointPnPPowerShellOnline"
break
}
# PnP Module is loaded
# Check to see if user is connected to Microsoft Graph
try
{
$owners = Get-PnPUnifiedGroupOwners -Identity $source
}
catch [System.InvalidOperationException]
{
Write-Host "No connection to Microsoft Graph found" -BackgroundColor Black -ForegroundColor Red
Write-Host "No Azure AD connection, please connect first with Connect-PnPOnline -Graph" -BackgroundColor Black -ForegroundColor Red
break
}
catch [System.ArgumentNullException]
{
Write-Host "Group not found" -BackgroundColor Black -ForegroundColor Red
Write-Host "Verify connection to Azure AD with Connect-PnPOnline -Graph" -BackgroundColor Black -ForegroundColor Red
Write-Host "Use Get-PnPUnifiedGroup to get Unified Group names" -BackgroundColor Black -ForegroundColor Red
break
}
catch
{
Write-Host "Some other error" -BackgroundColor Black -ForegroundColor Red
break
}
$members = Get-PnPUnifiedGroupMembers -Identity $source
if ($mergeusers -eq $true) {
# Get existing owners and members of Destination so that we can combine them
$ownersDest = Get-PnPUnifiedGroupOwners -Identity $destination
$membersDest = Get-PnPUnifiedGroupMembers -Identity $destination
# Add the two lists together so we don't overwrite any existing owners or members in Destination
$owners = $owners + $ownersDest
$members = $members + $membersDest
}
# Set the owners and members of Destination
$owners | ForEach-Object -begin {$ownerlist = @() } -process {$ownerlist += $($_.UserPrincipalName) }
$members | ForEach-Object -begin {$memberlist = @() } -process {$memberlist += $($_.UserPrincipalName) }
Set-PnPUnifiedGroup -Identity $destination -Members $memberlist -Owners $ownerlist
Feel free to pick through that for any nuggets that might help you.
Happy copying.
tk
ShortURL: https://www.toddklindt.com/PoshCopyO365GroupMembers