Finding Teams and Yammer Groups with PowerShell

How to Find Teams in a Tenant

The question of how to find the set of Microsoft 365 Groups (previously known as Office 365 Groups) enabled for Teams in a tenant using PowerShell has existed since Teams arrived in November 2016. In many cases, the desire is to create an array of teams where each item is subsequently processed. For example, you might want to create a report about the teams and groups in a tenant.

Several theories were advanced about the best way find Teams-enabled groups, many centering on the ProvisioningOption property returned by the Get-UnifiedGroup cmdlet. This property is long since deprecated, even if you can still find old articles about its use among the debris of the internet.                                                           

Get-Team is a Slow Cmdlet

The Teams PowerShell module contains the Get-Team cmdlet to find team-enabled groups. Although Get-Team does a fine job of returning the set of teams in a tenant, it is slow. Painfully slow. What’s surprising about this is that the underlying Graph call returns the data fast.

This code requests the set of teams in a tenant. The code uses pagination to find all the teams, 100 at a time. The result is a hashtable containing the object identifier and display name of the teams.

$Uri = "`$filter=resourceProvisioningOptions/Any(x:x eq 'Team')" $headers = @{Authorization = "Bearer $token"}
# Create list of Teams in the tenant
Write-Host "Fetching Teams…"
# Build a hashtable containing the temas. If more than 100 teams exist, fetch and continue processing using the NextLink 
$Teams = Invoke-WebRequest -Method GET -Uri $Uri-ContentType "application/json" -Headers $headers | ConvertFrom-Json
$TeamsHash = @{}
$Teams.Value.ForEach( {
   $TeamsHash.Add($_.Id, $_.DisplayName) } )
$NextLink = $Teams.'@Odata.NextLink'
While ($NextLink -ne $Null) {
   $Teams = Invoke-WebRequest -Method GET -Uri $NextLink -ContentType $ctype -Headers $headers | ConvertFrom-Json
   $Teams.Value.ForEach( {
      $TeamsHash.Add($_.Id, $_.DisplayName) } )
   $NextLink = $Teams.'@odata.NextLink' }

The equivalent use of Get-Team to create an array of teams holding just the identifier and display name is:

[array]$Teams = Get-Team | Select GroupId, DisplayName 

When I ran the code in my tenant against 65 teams (of 191 groups), Get-Team returns in a little over ten seconds while the Graph call takes less than a second. That’s quite a difference. In both cases, the result is an average over ten runs.

Using Get-UnifiedGroup to Find Teams

The Graph call finds Teams by applying a filter for a GET against the Groups endpoint. You can do the same using the Get-UnifiedGroup cmdlet:

$Groups = Get-UnifiedGroup -Filter {ResourceProvisioningOptions -eq "Team"} -ResultSize Unlimited | Select ExternalDirectoryObjectId, DisplayName

The command completes in less than six seconds.

Obviously, we’re not comparing apples with apples here. The Get-Team and Get-UnifiedGroup cmdlets do other processing when they fetch information, such as populating a set of useful properties about teams and groups that we might wish to access. But the basic point remains true: if you just want to fetch a set of groups or teams to use as input for whatever processing is necessary, a call to the Graph is more complicated but much faster.

Another thing to note is that the ResourceProvisioningOptions property might not contain “Team” for some old or inactive teams. This is a known issue with the Graph.

Finding Yammer-Enabled Groups

Given that the ResourceProvisioningOptions property is populated for Teams, could the property be used to find Microsoft 365 Groups used by Yammer communities in networks configured in Microsoft 365 native mode? The answer is no. “Team” appears to be the only option populated by Groups.

To find the set of groups used by Yammer, you can run the command:

Get-UnifiedGroup |?{$_.GroupSku -eq "Yammer"}

The command is slow because it uses a client side filter.

A close examination of group properties reveals another property called ResourceBehaviorOptions. Some groups have “YammerProvisioning” in this property, so can we run this command to find Yammer-connected groups?

Get-UnifiedGroup -Filter {ResourceBehaviorOptions -eq "YammerProvisioning"}

Alas, the answer is no. Although Groups use the ResourceBehaviorOptions property to understand what options are configured by applications using the group, it seems that only Yammer groups created before April 2019 populate the property, so you’re forced to use the slower command to find the complete set of Yammer groups.

Teams Resource Behaviors

By comparison, groups used by Teams created after May 2018 populate the property with WelcomeEmailDisabled, SubscribeMembersToCalendarEventsDisabled, and HideGroupInOutlook. WelcomeEmailDisabled means that Teams sends its own “welcome to Teams” email to new members instead of the generic “welcome to the group” message. HideGroupInOutlook means that the group is hidden from Exchange address lists and isn’t visible to Outlook clients.

SubscribeMembersToCalendarEventsDisabled is the most interesting option. It means that members of the team don’t receive updates for events scheduled in the group calendar. People often wonder why team members don’t receive notifications for channel meetings, which are created in the group calendar. Teams disables the subscription to the group calendar to stop team members receiving email notifications (a big thing for Teams is to reduce the amount of email). Therefore, the only people who receive email notifications for channel meetings are those who are explicitly added as a meeting participant.

Flexibility of PowerShell

The beauty of PowerShell is that it’s very flexible. That can also be its downfall as many ways often exist to get work done. The trick is to figure out which is the fastest or most efficient method in different circumstances. Sometimes it will be a cmdlet from one module, sometimes a cmdlet from a different module, or maybe even a quick call to the Graph.

5 Replies to “Finding Teams and Yammer Groups with PowerShell”

  1. Hi Tony,

    Do you also happen to figure out a way to find the list of groups that are using planner or the total plans/all planner groups in the tenant ?

Leave a Reply

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