Sharing this PowerShell Spell that will assist you in bulk migrating the users to Teams Only mode.
Below are the requirements from our customer:
- Script should read userprincipalname from text file.
- Enable these users to Teams Only Mode.
- Option to Disable as well so that they can be changed back to ISlands mode if required.
- Report and Log of success and failures.
- ADD users to the AD group on Enable operation.
- Remove users to the AD group on Disable operation.
Download the Script from below link and execute it.
https://github.com/VikasSukhija/Downloads/blob/master/BulkProcessingTeamsOnlyMode.ps1
It will ask for Userlist which will have userprincipalnames for example:
user1@labtest.com
user2@labtest.com
user3@labtest.com
user4@labtest.com
You need to enter the operation: Enable for upgrading the user to Teams Only Mode and Disable for changing back users to ISlands mode.
Enter the onmicrosoft domain for example: labtest.onmicrosoft.com.
AD group name so that when enable operation is selected, user is added as member to that group and if Disable operation is selected, user is removed from membership (This is customer specific requirement, you can modify the code if you do not require this step)
Report will be saved in Report folder which will show success and error.
Logs folder will contain logs for the whole operation so you can track the changes done by the script.
PowerShell
<# .NOTES =========================================================================== Created with: ISE Created on: 3/4/2020 1:46 PM Created by: Vikas Sukhija Organization: Filename: BulkProcessingTeamsOnlyMode.ps1 =========================================================================== .DESCRIPTION This script will bulk add or remove users to teams only mode #> param ( [string]$Userlist = $(Read-Host "Enter the text file path that contains userprincipalnames"), [string]$Operation = $(Read-Host "Type Enable for Enabling Teams Only mode and Disable for Island mode"), [string]$domain = $(Read-Host "Type Onmicrosoft Domain"), [string]$group = $(Read-Host "Type AD group that you want to use") ) function Write-Log { [CmdletBinding()] param ( [Parameter(Mandatory = $true,ParameterSetName = 'Create')] [array]$Name, [Parameter(Mandatory = $true,ParameterSetName = 'Create')] [string]$Ext, [Parameter(Mandatory = $true,ParameterSetName = 'Create')] [string]$folder, [Parameter(ParameterSetName = 'Create',Position = 0)][switch]$Create, [Parameter(Mandatory = $true,ParameterSetName = 'Message')] [String]$Message, [Parameter(Mandatory = $true,ParameterSetName = 'Message')] [String]$path, [Parameter(Mandatory = $false,ParameterSetName = 'Message')] [ValidateSet('Information','Warning','Error')] [string]$Severity = 'Information', [Parameter(ParameterSetName = 'Message',Position = 0)][Switch]$MSG ) switch ($PsCmdlet.ParameterSetName) { "Create" { $log = @() $date1 = Get-Date -Format d $date1 = $date1.ToString().Replace("/", "-") $time = Get-Date -Format t $time = $time.ToString().Replace(":", "-") $time = $time.ToString().Replace(" ", "") foreach ($n in $Name) {$log += (Get-Location).Path + "\" + $folder + "\" + $n + "_" + $date1 + "_" + $time + "_.$Ext"} return $log } "Message" { $date = Get-Date $concatmessage = "|$date" + "| |" + $Message +"| |" + "$Severity|" switch($Severity){ "Information"{Write-Host -Object $concatmessage -ForegroundColor Green} "Warning"{Write-Host -Object $concatmessage -ForegroundColor Yellow} "Error"{Write-Host -Object $concatmessage -ForegroundColor Red} } Add-Content -Path $path -Value $concatmessage } } } #Function Write-Log function Start-ProgressBar { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] $Title, [Parameter(Mandatory = $true)] [int]$Timer ) For ($i = 1; $i -le $Timer; $i++) { Start-Sleep -Seconds 1; Write-Progress -Activity $Title -Status "$i" -PercentComplete ($i /100 * 100) } } #Function Start-ProgressBar function LaunchSOL { param ( $Domain, $UserCredential ) Write-Host -Object "Enter Skype Online Credentials" -ForegroundColor Green $CSSession = New-CsOnlineSession -Credential $UserCredential -OverrideAdminDomain $Domain -Verbose Import-PSSession -Session $CSSession -Prefix "SOL" return $UserCredential } Function RemoveSOL { $Session = Get-PSSession | Where-Object -FilterScript { $_.ComputerName -like "*.online.lync.com" } Remove-PSSession $Session } #################Check if logs folder is created################## $logpath = (Get-Location).path + "\logs" $testlogpath = Test-Path -Path $logpath if($testlogpath -eq $false) { Start-ProgressBar -Title "Creating logs folder" -Timer 10 New-Item -Path (Get-Location).path -Name Logs -Type directory } $Reportpath = (Get-Location).path + "\Report" $testlogpath = Test-Path -Path $Reportpath if($testlogpath -eq $false) { Start-ProgressBar -Title "Creating Report folder" -Timer 10 New-Item -Path (Get-Location).path -Name Report -Type directory } ####################Load variables and log####################### $log = Write-Log -Name "BulkADDRemoveTeamsonly-Log" -folder "logs" -Ext "log" $Report1 = Write-Log -Name "BulkADDRemoveTeamsonly-Report" -folder "Report" -Ext "csv" $users = Get-Content $Userlist $collection = @() Write-Log -Message "Start Script" -path $log ######connect to Skob for checking user identity########## try { LaunchSOL -Domain $Domain -allowclobber Write-Log -Message "Connected to SKOBOnline" -path $log } catch { $exception = $($_.Exception.Message) Write-Log -Message "$exception" -path $log -Severity Error Write-Log -Message "Exception has occured in connecting to SOL" -path $log -Severity Error Exit; } ##################start processing users######################## if($Operation -eq "Enable"){ Start-ProgressBar -Title "Enable operation selected" -Timer 10 Write-Log -Message "Enable operation selected" -path $log if($users.count -gt "0"){ $users | ForEach-Object{ $error.clear() $UPN = $_.trim() $mcoll = "" | Select UPN, TeamModeStatus, ADGroupSTatus $mcoll.UPN = $UPN Write-Log -Message "Processing Enable operation on $UPN" -path $log Grant-SOLCsTeamsUpgradePolicy -PolicyName UpgradeToTeams -Identity $UPN if($error){ $mcoll.TeamModeStatus = "Error" Write-Log -Message "Error Processing Enable operation on $UPN" -path $log } else{ $mcoll.TeamModeStatus= "Success" Write-Log -Message "Successful Processing Enable operation on $UPN" -path $log Write-Log -Message "ADD user $UPN to $group" -path $log $getaduser = Get-ADUser -Filter {UserPrincipalName -eq $UPN} Add-ADGroupMember -Identity $group -Members $getaduser.SamAccountName if($error){ $mcoll.ADGroupSTatus = "Error" Write-Log -Message "Error Adding $upn operation on $group" -path $log } else{ $mcoll.ADGroupSTatus = "Added" Write-Log -Message "Successfully added $upn to $group" -path $log } } $collection+=$mcoll } } } $collection | export-csv $Report1 -NoTypeInformation ##############Disable Operation########################## if($Operation -eq "Disable"){ Start-ProgressBar -Title "Disable operation selected" -Timer 10 Write-Log -Message "Disable operation selected" -path $log if($users.count -gt "0"){ $users | ForEach-Object{ $error.clear() $UPN = $_.trim() $mcoll = "" | Select UPN, TeamModeStatus, ADGroupSTatus $mcoll.UPN = $UPN Write-Log -Message "Processing Disable operation on $UPN" -path $log Grant-SOLCsTeamsUpgradePolicy -PolicyName Islands -Identity $UPN if($error){ $mcoll.TeamModeStatus = "Error" Write-Log -Message "Error Processing Disable operation on $UPN" -path $log } else{ $mcoll.TeamModeStatus= "Success" Write-Log -Message "Successful Procssing Disable operation on $UPN" -path $log Write-Log -Message "Remove user $UPN to $group" -path $log $getaduser = Get-ADUser -Filter {UserPrincipalName -eq $UPN} Remove-ADGroupMember -Identity $group -Members $getaduser.SamAccountName -confirm:$false if($error){ $mcoll.ADGroupSTatus = "Error" Write-Log -Message "Error Removing $upn operation on $group" -path $log } else{ $mcoll.ADGroupSTatus = "Removed" Write-Log -Message "Successfully Removed $upn to $group" -path $log } } $collection+=$mcoll } } } $collection | export-csv $Report1 -NoTypeInformation Write-log -Message "Script Finished" -path $log RemoveSOL #############################################################################################
Thanks for reading and downloading..
Tech Wizard
Hi, Thanks a lot for the excellent script works great, but can you post a version with the group membership adding option as i do not need this, i tried to remove the parameter and it though the error, only Teamonly mode setup is fine for my requirements, besically below function not needed and output should be green
ADD users to the AD group on Enable operation.
Remove users to the AD group on Disable operation.
I will be posting another free script solution this week which will enable Teamsonly mode based on AD group, which will enable the user for teamsonly mode if user is member of the group.
You can check later on my blog to see if that works for you.
Thanks, but i have used your script earlier for 40 users, one users has duplicate meeting invite after migration. do u know why? Only one user faced this issue and not sure why suddenly get duplicated on teams. It should migrate as it is from sfb
https://github.com/VikasSukhija/Downloads/blob/master/BulkProcessingTeamsOnlyModeV2.ps1
Select groupoperation as NO , and group as anything, it will skip AD operation alltogether.
Not tested it but updated the code..
We migrated 10000 users using the script without issues, I can not relate it to script, it might be Microsoft backend issue as script is just turning the teamsonly mode, Microsoft runs back-end process to convert it when it sees the flag.
Please advise if this will migrate the users Skype for Business meetings as well? If doing for a single user via the GUI, the skype meetings are migrated – just wondering if this script will do that?
Yes, its is same as gui but for doing bulk operation. We migrated 10000 users using this.
You can test with few users first to be sure.
Could I confirm the onmicrosoft domain requirement – just to clarify this – it is def not the upn but the onmicrosoft tenancy name that is required?
That’s fantastic as it will save me weeks of manual work doing via the gui. I shall test with some sample users. Did you say that the AD group functionality can be disabled without issue in the script
This new version can skip AD operation if not required..
https://github.com/VikasSukhija/Downloads/blob/master/BulkProcessingTeamsOnlyModeV2.ps1
Select groupoperation as NO , and group as anything, it will skip AD operation all together.
Not tested it but updated the code..
Looks awesome, I shall give it a go. My query is around MFA and basic authentication – I have configured MFA and the winrm service/basic auth is off. Any way around that, given that Microsoft will remove support for basic auth at some time
Hi, I just tested the new code and I think it is skipping the No logic for AD groups – whether No or Yes is configured it still asks for the AD group name
Actually tested it and it seems to work great with the skip AD group as well. Would it be possible to add a section to check the csmeeting migration status as well?
Hi, Is it possible to skip Meeting Migration (MMS) and only do Teams Migration with it? Let me know how or which parameter to disable MMS migration.
Does anyone know if there is a “maximum” number of users this should be run against? You mentioned you used it on all 10,000 users in your org – was that all at once or did you limit it to batches of a certain size?
I limited it to batches as MS throttles it..