Teams-enabled O365 Groups report workaround in PowerShell

David Whitney

Overdue Edit: As of version 0.9.6 of the MicrosoftTeams PowerShell module, the Get-Team command now returns all teams when run as an administrator. Graph API calls can also do this.




With the current (0.9.1) beta version of the Teams PowerShell module, as has been pointed out in other posts, the Get-Team command only returns Teams you -- the user running the command -- are a member of. However, as community member Nino Paulo found in another thread specific to the Graph API endpoint, we can use the error codes we get back from some of the related Teams commands to work around the current limitation. This can work for PowerShell as well, which may fit better into existing workflows and admin experience.


Following is a snippet that uses the Get-UnifiedGroup Exchange Online PS command to get all O365 Groups, then uses the Get-TeamChannel Microsoft Teams PS command across them and based on the response (no error, a 403 Access Denied error, or a 404 Not Found error) reports whether the O365 Group is TeamsEnabled. This can stand as its own .ps1, can fit into another script, or the output can be modified as needed (for example, output Primary SMTP rather than Azure AD Group ID). Note as written it does need to have an Exchange Online PS session and Microsoft Teams PS session already connected to work.


$o365groups = Get-UnifiedGroup
foreach ($o365group in $o365groups) {
    try {
        $teamschannels = Get-TeamChannel -GroupId $o365group.ExternalDirectoryObjectId
        [pscustomobject]@{GroupId = $o365group.ExternalDirectoryObjectId; GroupName = $o365group.DisplayName; TeamsEnabled = $true}
    } catch {
        $ErrorCode = $_.Exception.ErrorCode
        switch ($ErrorCode) {
            "404" {
                [pscustomobject]@{GroupId = $o365group.ExternalDirectoryObjectId; GroupName = $o365group.DisplayName; TeamsEnabled = $false}
            "403" {
                [pscustomobject]@{GroupId = $o365group.ExternalDirectoryObjectId; GroupName = $o365group.DisplayName; TeamsEnabled = $true}
            default {
                Write-Error ("Unknown ErrorCode trying to 'Get-TeamChannel -GroupId {0}' :: {1}" -f $o365group, $ErrorCode)

Sample output from the snippet:

GroupId                              GroupName    TeamsEnabled
-------                              ---------    ------------
399cd314-1c6d-4c8d-ad03-54a0ac07cc93 Test Group 1        False
6a175eba-02d9-44a7-b49e-ac71d7aeeaf7 Test Team            True

As with any example code, please test prior to production use.

14 Replies
Nice script...have you considered to upload to GitHub or the Microsoft TechNet Gallery and even pacakge all the staff in a PowerShell function?
At this time I just wanted to provide it as an example snippet, but it may end up over in the gallery at some point. Thanks for the feedback!

Great Script @David Whitney Thanks for sharing !

Thanks Dave, using Get-TeamChannel is an interesting way to figure out whether a group is team-enabled.


One of the wonders of PowerShell is how easy it is to take different bits of code and stitch them together. I took your code and some code I had for reporting obsolete Office 365 Groups and created a report, which might be easier to process than looking at PowerShell output. All improvements are gratefully accepted.


$Groups = Get-UnifiedGroup
$Report = @()
$OrgName = (Get-OrganizationConfig).Name
$Today = (Get-Date)
$Date = $Today.ToShortDateString()
$ReportFile = "c:\temp\ListOfTeamEnabledGroups.html"
	   BODY{font-family: Arial; font-size: 8pt;}
	   H1{font-size: 22px; font-family: 'Segoe UI Light','Segoe UI','Lucida Grande',Verdana,Arial,Helvetica,sans-serif;}
	   H2{font-size: 18px; font-family: 'Segoe UI Light','Segoe UI','Lucida Grande',Verdana,Arial,Helvetica,sans-serif;}
	   H3{font-size: 16px; font-family: 'Segoe UI Light','Segoe UI','Lucida Grande',Verdana,Arial,Helvetica,sans-serif;}
	   TABLE{border: 1px solid black; border-collapse: collapse; font-size: 8pt;}
	   TH{border: 1px solid #969595; background: #dddddd; padding: 5px; color: #000000;}
	   TD{border: 1px solid #969595; padding: 5px; }
	   td.pass{background: #B7EB83;}
	   td.warn{background: #FFF275;}
	   td.fail{background: #FF2626; color: #ffffff;}
	   td.info{background: #85D4FF;}
           <div align=center>
           <p><h1>Report of Team-Enabled Office 365 Groups</h1></p>
           <p><h3>Generated: " + $date + "</h3></p></div>"
Write-Host "Processing" $Groups.Count "groups"
$TeamsFalse = 0
$TeamsEnabled = $False
foreach ($G in $Groups) {   
     try {       
         $teamschannels = Get-TeamChannel -GroupId $G.ExternalDirectoryObjectId
         $TeamsEnabled = $True
         } catch {
             $ErrorCode = $_.Exception.ErrorCode
             Switch ($ErrorCode) {
               "404" {
                   $TeamsEnabled = $False
               "403" {
                   $TeamsEnabled = $True
                default {
                Write-Error ("Unknown ErrorCode trying to 'Get-TeamChannel -GroupId {0}' :: {1}" -f $G, $ErrorCode)
                TeamEnabled = $False
    $ReportLine = New-Object PSObject -Property @{
        GroupName           = $G.DisplayName
        ManagedBy           = (Get-Mailbox -Identity $G.ManagedBy[0]).DisplayName
        Description         = $G.Notes
        ExternalGuests      = $G.GroupExternalMemberCount
        Members             = $G.GroupMemberCount
        TeamEnabled         = $TeamsEnabled  }      
    $Report += $ReportLine        
$GoodTeams = $Groups.Count - $TeamsFalse
$PcentTeams = (($GoodTeams/$Groups.Count)*100)
Write-Host $GoodTeams "of your" $Groups.Count "Office 365 Groups are team-enabled; that's" ($GoodTeams/$Groups.Count).tostring("P") "of the total..."
# Create the HTML report
$htmlbody = $Report | ConvertTo-Html -Fragment
$htmltail = "<p>Report created for: " + $OrgName + "
             <p>Number of groups scanned:            " + $Groups.Count + "</p>" +
             "<p>Number of Teams-enabled groups    : " + $GoodTeams + "</p>" +
             "<p>Percentage of Teams-enabled groups: " + ($GoodTeams/$Groups.Count).tostring("P") + "</body></html>"	
$htmlreport = $htmlhead + $htmlbody + $htmltail
$htmlreport | Out-File $ReportFile  -Encoding UTF8


@Tony Redmond : many thanks for this script ;)


"$" missed for "TeamsEnabled"


default {
                Write-Error ("Unknown ErrorCode trying to 'Get-TeamChannel -GroupId {0}' :: {1}" -f $G, $ErrorCode)
                TeamEnabled = $False


And it seems also know, we need to use this cmdlet to be able to use Microsoft Teams cmdlet requests :






anyone faced this change too ? :) 


Thanks for feedback


1. You do need to connect to the Teams endpoint to use the Teams cmdlets (Get-Team etc.)


2. I don't recommend checking for channels any longer. It is more effective to look for the presence of the Team Chat folder in the group mailbox and see if any compliance items are in it because that will tell you that the team is used.

Thanks for you guidance ;)


I understand what is "Team Chat" folder in the group mailbox with an other great article from you as allways ... : https://www.petri.com/teams-compliance-story ;)


I understand the logic "because that will tell me that the team is used" but, is this "Team Chat" folder also present by default ? (for exemple : when we look at an "inactive" Teams-enabled O365 Groups)

The Team Chat folder might be present even if a group is not team enabled. I think groups created through OWA might provision the folder. In any case, it is best to check to see if compliance items are present. If the count is 0, then the team has never been used or the group is not team-enabled. A count > 1 means that someone has accessed the group and sent some messages.

Thank you ;)

By the way very happy to see you coming in France next month for MWC'18 and your session : Will Teams Take Over from Email ?!


je suis content d'etre a Paris pour mwc '18 aussi

@Tony Redmond  I love this script. Thanks @Tony Redmond 

I am a PS noob so i might be wrong, but I had to add resultsize parameter to unlimited 2 time 


In the top line:


$Groups = Get-UnifiedGroup -ResultSize Unlimited

 And in a later line (30): 


 $teamschannels = Get-TeamChannel -GroupId $G.ExternalDirectoryObjectId -resultsize unlimted 

 Or am i wrong?

@Tony Redmond 

I thinks it is also needed with the get-mailbox command on line 60. 

I am getting: WARNING: By default, only the first 1000 items are returned.


@Jan KLaasen  Sure. The joy of PowerShell is that you can amend the code to meet your needs.