Script to move bulk users to Teams Only mode from On Premise Skype for Business Servers

When we enable Teams for Skype for Business Hybrid users the final stage of action is to move the actual on premise Skype for Business Account to Office 365 to make them to Teams only mode. As more organization are adopting the Microsoft Teams in a full fast track approach the last stage of migration is to move all the local accounts to Teams Only Mode.

This script will help in moving the users on batches to Teams Only Mode from an input csv file. It also provides the time taken to complete the batch on screen once the migration is completed.

Example below:



Measure-Command {
[CmdletBinding()]
param( [string] $UsersList = $(Read-Host -prompt `
    “Input the CSV File with Location”))
$Users = Import-Csv $UsersList -Delimiter ";"

#To Connect to Teams. Make sure you have the new Teams Module installed.

$admin="enteryouradminaccount@domain.com";
$pwd = "enteryourpasswordhere";
$securepwd = ConvertTo-SecureString $pwd -AsPlainText -Force;
$cred = New-Object Management.Automation.PSCredential ($admin.Replace('sip:', ''), $securepwd);
Import-Module MicrosoftTeams
Connect-MicrosoftTeams

#Initialize parameters and variables.

$sip= $users.SipAddress
$count = $users.count

write-host "We have found" $count "Users to Migrate" -foregroundcolor Yellow -backgroundcolor Black
$pauseSeconds = 10
$Sleep = 20

Write-Host "Pausing for " $pauseSeconds " seconds to verify your count..." -ForegroundColor Yellow
Start-Sleep -s $pauseSeconds

#To Enable Logging and store them for failed migration and any errors.

$transcriptname = “MoveCSUserStatus” + `
    (Get-Date -format s).Replace(“:”,”-“) +”.txt”
Start-Transcript $transcriptname

#Take export of SFB enabled users before move.

$Users | % {get-csuser -Identity $_.SipAddress} | Where-object {$_.Enabled -eq $True} | Select-object  SamAccountName,sipaddress,Enabled,EnterpriseVoiceEnabled | Out-File SFBUsersBeforeMove.csv -append          
  
#Hosted Migration Override URL - Use the correct URL based on your tenant
$URL= "https://adminof.online.lync.com/HostedMigration/hostedmigrationService.svc"

#Initiate Move-CsUser Operation.

foreach ($user in $users) {
Move-CsUser -Identity $user.SipAddress -Target sipfed.online.lync.com -HostedMigrationOverrideUrl $URL  -MoveToTeams -BypassAudioConferencingCheck -BypassEnterpriseVoiceCheck -Confirm:$False -credential $cred
}

#Pause for 20 seconds 

Start-Sleep -s $sleep 

#Validate the Move and complete Successfully Moved and Failed Users.

$loop = foreach ($user in $users) {
Get-CsOnlineUser -Identity $user.sipaddress | Select-object  sipaddress,hostingprovider,TeamsUpgradeEffectiveMode,RegistrarPool} 
$loop| Out-File TeamsOnlyMigrationStatus.csv -append

#Validate the meeting Migration status
$loop = foreach ($user in $users) {
Get-CsMeetingMigrationStatus -Identity $user.sipaddress | Select-Object UserPrincipalName,State,MigrationType,LastMessage,FailedMeetings}
$loop| Out-File MeetingMigrationStatus.csv -append

Stop-Transcript
Write-Host "Migration Script Completed Please Refer Transcript File for any Errors" -ForegroundColor Green

#Close the sessions.
          
get-pssession | remove-pssession  

#Send Email report to Notify the Migration have completed - Mention your SMTP server
#Send-MailMessage -from "username@domain.com" -to "admin@domain.com"-subject "TeamsOnlyMigrationTaskCompleted: No File" -body "Teams Only Migration Batch have been completed.Please refer log file Location for further information" -SmtpServer "Mention your SMTP Server" 
}

Notes:

  1. Make sure that you whitelist the traffic to office365 services to establish successful connection to the SFBO session.
  2. If there are multiple number of users recommended to split up the batches and execute them from 2 servers.
  3. Ensure the SSL traffic inspection, IP connection limits are excluded from Firewall/Proxy from the network side.
  4. Moving this from a shared bandwidth might be a bit slower and moving this from a temporary dedicated IP address might provide a better performance.
  5. This script uses -UseOauth switch. Make sure the Onpremise SFB servers are patched to the required version. Else use the legacy option by removing this switch. Recommended to run this first with few users list verify based on your environment and then later run for bulk users.

Regards

Sathish Veerapandian

21 thoughts on “Script to move bulk users to Teams Only mode from On Premise Skype for Business Servers

  1. Ally February 20, 2021 at 6:17 am Reply

    Awsome! I am in the process of moving my hybrid SFB on-premises users to teams only mode in parts. In my hybrid environment if I search users in teams I can see all sfb on-premises and online users. Can’t I just change the mode for individual users to teams only instead of running this script? I believe they are homed in on-premises that’s why I must have to move them. Please correct me if I am wrong? Thanks

    Like

    • Sathish Veerapandian April 11, 2021 at 12:52 pm Reply

      Hi Ally if you are running hybrid version of SFB and users are not moved SFB Online Unfortunately we cannot move them to Teams Only mode. So the first step is to move them to Online.

      Like

      • Ally April 30, 2021 at 9:38 am

        Hi Satish, Thanks for the clarification. Do you by any chance know how we move users from SFB on-prem (hybrid) to Teams after July 31, 2021 when SFB and online will be end of life? Has Microsoft defined any process that you are aware of?

        Thanks

        Ally

        Like

      • Sathish Veerapandian May 2, 2021 at 7:57 am

        Hi Ally you can still move users directly from Skype on prem to Teams only after July 31st. Microsoft has moved all of the backend core components that was present in Skype Online to Teams. https://docs.microsoft.com/en-us/skypeforbusiness/hybrid/move-users-from-on-premises-to-teams

        Like

  2. aldo February 23, 2021 at 11:49 am Reply

    This is just what I am looking for, thanks, how does the CSV need to be formatted?

    Like

  3. Daniel desire April 9, 2021 at 9:16 pm Reply

    Hi Sathish, I guess the scripts are run from skype for business front end. Will this work for migration of thousands users. I use a quite similar script and it times out after 15 users, so I have to close the session and restart a new one.

    Like

    • Sathish Veerapandian April 11, 2021 at 12:50 pm Reply

      Hi Daniel this is a known issue recently after upgrading the Teams PowerShell module. The only workaround that you can use is to use the Legacy Authentication parameter trick in the Script. YOu can use the below cmd in your script to use the Legacy Authentication.
      Read-Host -Prompt “Enter your tenant password” -AsSecureString | ConvertFrom-SecureString | Out-File “cred.txt”
      $User = “Adminaccount@domain.com”
      $Pass = Get-Content “cred.txt” | ConvertTo-SecureString
      $credential= new-object -typename System.Management.Automation.PSCredential -argumentlist $AdminName, $Pass

      Like

  4. Daniel Desire April 21, 2021 at 9:10 am Reply

    Hi Sathish, Thanks for your reply. My account has MFA enforced would -Credentials work ? Have you seen admins with MFA enabled doing batch migrations without any or little intervention? I have been struggling for a solution for months. I opened a case with MS some time ago and they said that they don’t support in house scripts and I don’t see solutions in any article on the web. I came across yours and thought you may have experience or idea to tackle that. I doubt I’m the only one admin with MFA trying to migrate batches of users.

    Like

    • Sathish Veerapandian April 21, 2021 at 3:20 pm Reply

      Hi Daniel
      Not sure haven’t tried with an MFA enabled account. Are you trying with the newer version of Powershell Module. We had the issue with version 1.1.16 and upgraded to the latest version , post that we are not having any issues. You can try to run fiddler and parallelly run your script and see where and in which URL it gets failed and there could be some URLs getting blocked if you are behind the proxy make sure all the office 365 and IP ranges are whitelisted.

      Like

      • Jean Paul April 27, 2021 at 2:01 pm

        Hi Sathish,

        Your script contains

        Connect-MicrosoftTeams -Credential $mycred
        Import-Module MicrosoftTeams
        $sfbsession = New-CsOnlineSession
        Import-PSSession $sfbsession

        Is that correct/updated?
        Should we not import the module, then connect?
        On another side, the new teams module doesn’t include New-csonlinesession.

        Connect-MicrosoftTeams is required to get the “CS” cmdleds, skype online connector has retired on feb.

        Please advise

        Like

      • Sathish Veerapandian April 28, 2021 at 5:37 am

        Hi Jean
        yes you are correct when we use the new teams module we can ignore the New-Csonlinesession . I have updated the script now.

        Like

  5. Jean April 28, 2021 at 10:09 pm Reply

    Thanks, however I still see references to new-csonlinesssion in the script.

    $NewSession=$x/250
    if($NewSession -eq 1) {
    get-pssession | remove-pssession
    Disconnect-MicrosoftTeams
    Connect-MicrosoftTeams -Credential $mycred
    Import-Module MicrosoftTeams
    $sfbsession = New-CsOnlineSession
    Import-PSSession $sfbsession
    $NewSession=0
    $x=0
    Write-Host “Refreshing the Skype online Session” -ForegroundColor Green
    }

    Can you please also explain what $x/250 does?

    Thanks

    Jean

    Like

    • Sathish Veerapandian May 2, 2021 at 8:07 am Reply

      Hi Jean,
      I have updated the script and you can use them now. Earlier i added a loop to refresh the skype online session after every 250 users movement. Now with the new Teams powershell module that is not required. You can use the legacy method and move the users by having the fiddler client open at the same time. That is the work around we have identified.

      Like

  6. Jean May 3, 2021 at 9:02 am Reply

    Thanks for taking the time to reply and modify the scripts.
    It’s a very good work and is very much appreciated for sharing that!

    Noticed a missing command and typo in a varaiable. If you have the chance to confirm that my finding is correct, that would be great. txs again

    Missing “connect-microsofteams” after importing the module.
    Variable $cred specified, but $MyCred used in the Move-csuser command.

    I guess I won’t be able to use the script using legacy authentication because I’m MFA enabled.

    Like

    • Sathish Veerapandian May 10, 2021 at 10:40 am Reply

      Hey Jean
      Thanks for the good catch. Yeah it was a quite busy day and missed to update them between the lines. Have updated the script. Yeah i would recommend to run them from a non-enabled MFA account for the legacy authentication to work. Even exporting the credentials as key file and using them in legacy authentication with an MFA enabled account does not work.

      Like

  7. Ally May 10, 2021 at 2:33 pm Reply

    Hi Satish, By any chance do you have any working power shell scripts to get list of say 50 users from a csv file in SFB server. Actually I want to get-CsUser from the list and then in the second script disable-CsUsers some of those users. I found some but they are giving me errors. Appreciate your help.

    Like

  8. Graham July 22, 2022 at 4:17 pm Reply

    I don’t think you’ve said exactly how the CSV file needs to be formatted. SipAddress is the only thing you mentioned, but that doesn’t work.

    Like

    • Sathish Veerapandian August 1, 2022 at 8:17 pm Reply

      Hi Graham,
      It works with the SIP address column only. Since I used this script in year 2020 for migrating more than 15,000 users. Not sure if something has changed with the new modules. Below is the example I took from the lab server.
      “SipAddress”
      “Ewald.Hollestelle@nl.exchangequery.com”
      “Gautham.Antony@nl.exchangequery.com”
      “jacob.benny@nl.exchangequery.com”
      “Joe.Nash@nl.exchangequery.com”
      May be can you share your error message that you are getting we could see what possibly is going wrong in that environment.

      Like

      • Graham August 12, 2022 at 7:58 pm

        I receive the error “Move-CSuser:Management object not found for identity xxx@xxx.xxx“. And the x’s represent the SIP address for the user, which i verified in the on prem SFB console.

        Like

      • Sathish Veerapandian August 19, 2022 at 11:37 am

        Interesting so im sure that there are no extra spaces on the CSV file. May be try the delimiter option in the script. Or it could be an issue that the SFB servers are unable to contact the SFB hybrid. Can you try with the -proxypool switch and make sure from the server where we are running this script has the connectivity to the SFB FE server and that server needs to have connectivity to Office 365 services. I remember one of my customer had this same issue and the solution was the management server from where the script was running did not have connectivity to Office 365 URLs. After correcting that the issue was solved.

        Like

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.