Microsoft Teams: PowerShell script to add Team owners as a Team members to resolve “Failed to add plan” issue while adding planner to Team which are created using Graph APIs

Failed to add planner in Teams

Hi All,

LIFE IS BEAUTIFUL 🙂 I hope we all are safe:) STAY SAFE, STAY HEALTHY 🙂 STAY HOME 🙂

In my previous article related to Microsoft Teams we discussed the issue while adding Planner to Teams which are created using Graph APIs and workaround – Microsoft Teams : “Failed to create the plan” error while adding Planner to Teams which are created using Graph APIs

Microsoft Teams : “Failed to create the plan” error while adding Planner to Teams which are created using Graph APIs
Fig1 : Microsoft Teams : “Failed to create the plan” error while adding Planner to Teams which are created using Graph APIs

If you didn’t read it yet, kindly please have a look once.

So workaround is adding Owners as Members as well and it resolved the issue. So as discussed in the article we changed the code and Owners could successfully add the Planned to their new Teams.

But then the issue remains same for existing teams, so one of the option is to write PowerShell script and hence this article 🙂

Background: We were provisioning Teams using Microsoft Graph APIs. We have our custom Teams creations form where user can order the Team. We are storing all Team orders in a custom SharePoint list called “TeamsOrder”

So here are the high level steps

  • Connect to Microsoft 365
  • Get the client context
  • Get the Web and List
  • Read all the existing Teams Items from our custom SharePoint list “TeamsOrder” which are created before given date
  • From DisplayName Get the Team
  • Get the Team Owners
  • Add the Team Owners as a Members

Detailed script

  • Get the user details – Here we are storing user details in a text file on file system having two lines in following format
    • UserName
    • Password
#Get the user details
 $user = Get-Content $CredentialFilePath | Select-Object -First 1
 $password = Get-Content $CredentialFilePath | Select-Object -First 1 -Skip 1
 $securePassword = ConvertTo-SecureString $Password -AsPlainText -Force 
  • Connect to Microsoft 365
#Connect to Microsoft 365
$spoManagementCred = New-Object -TypeName 
                System.Management.Automation.PSCredential -argumentlist 
                $user, $securePassword
        
Connect-SPOService -Url $TenantAdminURL -Credential $spoManagementCred
  • Get the Client Context from the site collection where we need to read list and get the teams
 $Context = New-Object 
               Microsoft.SharePoint.Client.ClientContext($ConfigSiteURL)
 $Creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($user,$securePassword)
$Context.Credentials = $Creds
  • Get the web object to get list
$web = $Context.Web
$Context.Load($web)
$Context.ExecuteQuery()
  • Read the list and get list items – Kindly please note query for getting list items is as per our customer requirement :). You can changes with the respective your required fields and values
#Retrieve list
$list = $web.Lists.GetByTitle($ListName)
$Query = New-Object Microsoft.SharePoint.Client.CamlQuery
$Query.ViewXml = "@<View><Query><Where>
                   <And><And><Eq>
                       <FieldRef Name='WorkspaceType' />
                       <Value Type='Text'>Teams</Value>
                    </Eq><Eq>
                        <FieldRef Name='Status' />
                        <Value Type='Text'>Created</Value>
                    </Eq></And><Geq>
                          <FieldRef Name='Created' />
                          <Value Type='DateTime'>2020-07-05T12:00:00Z</Value>
                    </Geq></And>
                    </Where></Query></View>"

            #Get All items from the list
            #$listItems = 
$list.GetItems([Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery())
          $listItems = $list.GetItems($Query)
          $Context.Load($list)
          $Context.Load($listItems)
          $Context.ExecuteQuery()
  • Now get the teams from DisplayName field – Get-Team -DisplayName <Team Display Name>
  • If Team exists then get the team owners – Get-TeamUser -GroupId <Team group id> -Role Owner
  • Loop through all team owners and add them as members – Add-TeamUser -GroupId -User <User> -Role Member
foreach($Item in $listItems){            
  
        $team = Get-Team -DisplayName $Item["Title"]
        if($team){

           #Get Team Owners
           $owners = Get-TeamUser -GroupId $team.GroupId -Role Owner
           #Add Team Owners as a Members
        
          foreach($owner in $owners){
                  try{
           Add-TeamUser -GroupId $team.GroupId -User $owner.User -Role Member
                      Write-Host "Team members are added successfully"
                    }
                    catch{
		           [Exception]		
	write-host "Error occurred while adding Team Members - "  $Error
                         $Error.Clear()
                         }
                 }#foreach($owner in $owners){
                
           }#if($team){
         }#foreach($Item in $listItems){

Complete Script :

<#
.SYNOPSIS
 Script to add the Team Owners as a Team Members. 

.PARAMETER CredentialFilePath
 Microsoft 365 system account credential file path having two lines in following format
    UserName
    Password

 .PARAMETER TenantAdminURL
  Microsoft 365 tenant admin site URL

 .ConfigSiteURL
  Configuration site URL

  .ListName
   "WorkspaceOrder" list from which we need to get the Team
#>

function AddOwnerAsMember
{
    param(
        
        [parameter(Mandatory=$true)][string] $CredentialFilePath,
        [parameter(Mandatory=$true)][string] $TenantAdminURL,
        [parameter(Mandatory=$true)][string] $ConfigSiteURL,
	    [parameter(Mandatory=$true)][string] $ListName

    )#param

    try
	{
        #Get the user details
        $user = Get-Content $CredentialFilePath | Select-Object -First 1
        $password = Get-Content $CredentialFilePath | Select-Object -First 1 -Skip 1
        $securePassword = ConvertTo-SecureString $Password -AsPlainText -Force 

        #Connect to Microsoft 365
        $spoManagementCred = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $user, $securePassword
        Connect-SPOService -Url $TenantAdminURL -Credential $spoManagementCred

        #Bind to Configuration site collection
        $Context = New-Object Microsoft.SharePoint.Client.ClientContext($ConfigSiteURL)
        $Creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($user,$securePassword)
        $Context.Credentials = $Creds
        
        $web = $Context.Web
        $Context.Load($web)
        $Context.ExecuteQuery()

        if($web -ne $null){

            #Retrieve list
            $list = $web.Lists.GetByTitle($ListName)

            $Query = New-Object Microsoft.SharePoint.Client.CamlQuery
            $Query.ViewXml = "@
                            <View>
                                <Query>
                                    <Where>
                                        <And>
                                        <And>
                                        <Eq>
                                            <FieldRef Name='WorkspaceType' /><Value Type='Text'>Teams</Value>
                                        </Eq>
                                        <Eq>
                                            <FieldRef Name='Status' /><Value Type='Text'>Created</Value>
                                        </Eq>
                                        </And>
                                        <Geq>
                                            <FieldRef Name='Created' /><Value Type='DateTime'>2020-07-05T12:00:00Z</Value>
                                        </Geq>
                                        </And>
                                    </Where>
                                </Query>
                            </View>"


            #Get All items from the list
            #$listItems = $list.GetItems([Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery())
            $listItems = $list.GetItems($Query)

            $Context.Load($list)
            $Context.Load($listItems)
            $Context.ExecuteQuery()

            Write-Host "List Item Count - " $listItems.Count

            #Connecting to the Teams
            $Creds = New-Object System.Management.Automation.PSCredential ($user, $securePassword)
            Connect-MicrosoftTeams -Credential $Creds

            #Loop through items
            foreach($Item in $listItems){
                #$msg = [string]::Format("Title {0}, Workspace Type {1}, Status {2}", 
                 #                       $Item["Title"], $Item["WorkspaceType"], $Item["Status"])
                
                
                $team = Get-Team -DisplayName $Item["Title"]
                
                Write-Host "Team Name - "  $Item["Title"]

                if($team){
                    #Get Team Owners
                    $owners = Get-TeamUser -GroupId $team.GroupId -Role Owner
                    Write-Host $owners.Count

                    #Add Team Owners as a Members
                    foreach($owner in $owners){
                        Write-Host "Owner UPN - " $owner.User
                        try{
                            Add-TeamUser -GroupId $team.GroupId -User $owner.User -Role Member
                            Write-Host "Team members are added successfully"
                         }
                         catch{
		                        [Exception]		
		                        write-host "Error occurred while adding Team Members - "  $Error
                                $Error.Clear()
                                continue
	                        }
                    }#foreach($owner in $owners){
                }#if($team){
            }#foreach($Item in $listItems){
        }#if($web -ne $null)
    }
    catch
	{
		[Exception]		
		write-host "Error Occurred " + $Error
        $Error.Clear()
	}

}#AddOwnerAsMember

AddOwnerAsMember 

References:

Thanks for reading 🙂 If its worth at least reading once, kindly please like and share. SHARING IS CARING 🙂

Enjoy the beautiful life 🙂 Have a FUN 🙂 HAVE A SAFE LIFE 🙂 TAKE CARE 🙂

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