Ever found your self looking for a way to add a group of users to a team site and one or more channels in bulk? I was in that situation the other day and decided to see if there was an easy way to take care of it using PowerShell. The following script is what I came up with and is uses a yaml file as input to make it easy to use (would be a simple change to move over to json or csv if needed)
Here is an example of the input file
team: # Only name or id is needed. Note if there are multiple teams that start with the same name use the id id: name: Team Site A users: - email: user_a_email@company.com channels: - name: Channel A - name: Channel B enabled: false # Option field to enable/disable adding a user to a channel - email: user_b_email@company.com channels: - name: Channel A - name: Channel C enabled: false # Option field to enable/disable adding a user to a channel
And here is the PowerShell script that does all the magic. Note: It supports the common parameters of WhatIf, Verbose, Information, and Debug to help with testing and troubleshooting.
[CmdletBinding(SupportsShouldProcess)] param( [string] $GroupName = $null, [string] $GroupId = $null, [string] $FileName = "users.yml" ) if (-Not (Test-Path $FileName)) { Write-Error "File '$FileName' was not found. Please check and try again... " exit } if (Get-Module -ListAvailable -Name MicrosoftTeams) { Write-Verbose "Microsoft Teams Module already Installed" } else { try { Write-Verbose "Installing Microsoft Teams Module" Install-Module -Name MicrosoftTeams -AcceptLicense -AllowClobber -Confirm:$False -Force } catch [Exception] { $_.message exit } } if (Get-Module -ListAvailable -Name powershell-yaml) { Write-Verbose "ConvetFrom-Yaml already installed" } else { try { Write-Verbose "Installing ConvertFrom-Yml command" Install-Module -Name powershell-yaml } catch { $_.message exit } } Get-TeamsApp -ErrorAction SilentlyContinue -ErrorVariable errGetTeamsApp -OutVariable teamsApp | Out-Null if ($errGetTeamsApp.Count -gt 0) { Write-Verbose "Connecting to Teams" Connect-MicrosoftTeams -WhatIf:$false } else { Write-Verbose "Already Connected to Teams" } $importData = (Get-Content -Path $FileName) | ConvertFrom-Yaml if ($null -ne $importData.team) { if ($null -ne $importData.team.name) { $GroupName = $importData.team.name } if ($null -ne $importData.team.id) { $GroupId = $importData.team.id } } if ($null -eq $GroupName -and $null -eq $GroupId) { Write-Warning "Please specify either a GroupName or GroupId." exit } $team = $null if (-Not [string]::IsNullOrEmpty($GroupName) -and [string]::IsNullOrEmpty($GroupId)) { Write-Verbose "Looking for Team By Name: '$GroupName'" $team = Get-Team -DisplayName $GroupName -ErrorAction SilentlyContinue if ($team.GetType().IsArray) { Write-Warning "Multiple Groups Returned with that name. Please specify a specific Group by using the GroupId parameter." $team | Format-Table GroupId, DisplayName exit } elseif ($null -eq $team) { Write-Warning "Unable to locate team '$GroupName'. Please verify and try again." exit } else { $GroupId = $team.GroupId } } if (-Not [string]::IsNullOrEmpty($GroupId) -and $null -eq $team) { Write-Verbose "Looking for Team By ID: '$GroupId'" $team = Get-Team -GroupId $GroupId -ErrorAction SilentlyContinue if ($null -eq $team) { Write-Warning "Unable to locate team based on Group Id '$GroupId'. Please verify and try again" exit } } if ([string]::IsNullOrEmpty($GroupId) -and [string]::IsNullOrEmpty($GroupName)) { Write-Warning "Failed to find team. Please check GroupId '$GroupId' or GroupName '$GroupName' arguments and try again." exit } Write-Information "Retrieving current list of users in team '$($team.DisplayName)" $teamExistUsers = Get-TeamUser -GroupId $($team.GroupId) Write-Host "Importing Users into '$($team.DisplayName)' [ID: $($team.GroupId)]" Write-Host "----------------------------------------------------------------------------" $users = $importData.users foreach ($u in $users) { if ([string]::IsNullOrEmpty($u.role)) { $u.role = "member" } $userExists = $teamExistUsers | Where-Object { $_.User -eq $u.email } if ($null -ne $userExists) { Write-Host "User '$($u.email)' is already a member of team '$($team.DisplayName)'" } else { if ($PSCmdlet.ShouldProcess("Add-TeamUser", "Adding User '$($u.email)' to team '$($team.DisplayName)' as a '$($u.role)'")) { Write-Host "Adding User '$($u.email)' to team '$($team.DisplayName)' as a '$($u.role)'" Add-TeamUser -GroupId $($team.GroupId) -user $($u.email) -role $($u.role.ToLower()) -ErrorVariable errAddTeamuser | Out-Null if ($errAddTeamUser.Count -gt 0) { Write-Warning "`tFailed to add user to team..." } Write-Verbose "Sleeping for 30 seconds to allow changes to propogate..." Start-Sleep -Seconds 30 } } foreach ($c in $u.channels) { if ($null -ne $c.enabled -and $c.enabled -eq $false) { Write-Host "`tAdding user to channel $($c.name) has been disabled. Skipping...." Write-Debug ($c | Out-String) continue } $teamChannel = Get-TeamChannel -GroupId $($team.GroupId) | Where-Object { $_.DisplayName -eq "$($c.name)" } if ($null -ne $teamChannel) { $userExistsChannel = Get-TeamChannelUser -GroupId $($team.GroupId) -DisplayName $($c.name) | Where-Object { $_.User -eq $u.email } if ($null -ne $userExistsChannel) { Write-Host "User '$($u.email)' is already a member of channel '$($teamChannel.DisplayName)" } else { if ($PSCmdlet.ShouldProcess("Add-TeamChannelUser", "Adding User '$($u.email)' to teams channel '$($teamChannel.DisplayName)' as a '$($u.role)'")) { Write-Host "`tAdding User '$($u.email)' to teams channel '$($teamChannel.DisplayName)' as a '$($u.role)'" Add-TeamChannelUser -GroupId $($team.GroupId) -DisplayName $($teamChannel.DisplayName) -user $($u.email) -ErrorAction SilentlyContinue -ErrorVariable errAddUserTeamsChannel | Out-Null if ($errAddUserTeamsChannel.Count -gt 0) { Write-Warning "Failed to add user to teams channel: $($c.name). Please verify the channel exists" } } } } else { Write-Warning "`tFailed to find channel '$($c.name)'...." } } } Write-Host "----------------------------------------------------------------------------" write-Host "Done..."