Back to script library
Entra / Microsoft 365 · Teams

Report teams chat info

Report Teams chat threads for the user signed into an interactive Microsoft Graph PowerShell session.

Connect & set up

Run these once per session. All scopes are read-only unless the script makes changes.

Connect-MgGraph -Scopes Chat.ReadWrite, Chat.ManageDeletion.All -NoWelcome
# Find the object identifier for the signed-in user

Run it

The main script. Copy it, or download the .ps1 and run it from your console.

Connect-MgGraph -Scopes Chat.ReadWrite, Chat.ManageDeletion.All -NoWelcome
# Find the object identifier for the signed-in user
$Account = (Get-MgContext).Account
$UserId = (Get-MgUser -UserId $Account).Id
# Get chats for the user
Write-Host ("Fetching chat threads for user {0}" -f $Account)
[array]$Chats = Get-MgUserChat -Userid $UserId -All -Filter "chattype eq 'group' or chattype eq 'oneonone' or chattype eq 'Meeting'" | Sort-Object LastUpdatedDateTime -Descending
# Extract the identifiers for the tenants that chat threads belong to so that we can resolve them to a tenant name
Write-Host "Finding tenant information for chats..."
$TenantList = [System.Collections.Generic.List[Object]]::new()
ForEach ($Chat in $Chats) {
$TenantList.Add($Chat.TenantId)
}
$TenantsCount = @{}
$TenantList = $TenantList | Sort-Object
$TenantList | ForEach-Object {$TenantsCount[$_]++}
$TenantsCount = $TenantsCount.GetEnumerator() | Sort-Object -Property Value -Descending
$TenantsCount
# Now build a hash table of tenant identifiers and names that we can use to look up tenants
Write-Host "Resolving tenant identifiers..."
$TenantsHash = @{}
ForEach ($Tenant in $TenantsCount) {
$Uri = ("https://graph.microsoft.com/V1.0/tenantRelationships/findTenantInformationByTenantId(tenantId='{0}')" -f $Tenant.Name.ToString())
$ExternalTenantData = Invoke-MgGraphRequest -Uri $Uri -Method Get
$TenantsHash.Add([string]$Tenant.Name.toString(), [string]$ExternalTenantData.displayName)
}
# Create output report
$ChatReport = [System.Collections.Generic.List[Object]]::new()
# Extract information for each chat thread and write it out to the report file
Write-Host "Analyzing chat threads..."
ForEach($Chat in $Chats) {
# Get members of the chat thread
Try {
[array]$Members = Get-MgUserChatMember -UserId $UserId -ChatId $Chat.Id -ErrorAction Stop
# Extract the member display names and remove any blanks (accounts that no longer exist)
[array]$MemberNames = $Members.displayName | Sort-Object -Unique
$NumberOfParticipants = $MemberNames.Count
If ($MemberNames.Count -gt 0) {
$MemberNamesOutput = $MemberNames -Join ", "
}
} Catch {
Write-Host ("Error getting members for chat {0}: {1}" -f $Chat.Id, $_.Exception.Message) -ForegroundColor Red
$MemberNamesOutput = "Error retrieving members"
$NumberOfParticipants = 0
Continue
}
# Get tenant display name
$TenantDisplayName = "Unknown"
$TenantDisplayName = $TenantsHash[$Chat.TenantId]
$ChatReportLine = [PSCustomObject][Ordered]@{
ChatType = $Chat.ChatType
Topic = $Chat.Topic
Created = Get-Date $Chat.CreatedDateTime -format 'dd-MMM-yyyy HH:mm:ss'
LastUpdated = Get-Date $Chat.LastUpdatedDateTime -format 'dd-MMM-yyyy HH:mm:ss'
NumberOfParticipants = $NumberOfParticipants
Participants = $MemberNamesOutput
TenantId = $Chat.TenantId
Tenant = $TenantDisplayName
Id = $Chat.Id
WebUrl = $Chat.WebUrl
}
$ChatReport.Add($ChatReportLine)
} # End ForEach chats
# Tenant analysis
Write-Host ""
Write-Host "Analysis of chat threads by tenant"
Write-Host "----------------------------------"
$ChatReport | Group-Object Tenant -NoElement | Sort-Object Count -Descending | Format-Table @{expression={$_.Name}; label = "Host Tenant"}, Count
Write-Host ""
Write-Host "Analysis of chat threads by type"
Write-Host "--------------------------------"
$ChatReport | Group-Object ChatType -NoElement | Sort-Object Count -Descending | Format-Table @{expression={$_.Name}; label = "Host Tenant"}, Count
Write-Host ""
# And here's what we found sorted by the last updated date
$ChatReport | Select-Object ChatType, Tenant, Topic, Created, LastUpdated, NumberOfParticipants, Participants | Sort-Object LastUpdated -Descending | Out-GridView
# Generate reports
If (Get-Module ImportExcel -ListAvailable) {
$ExcelGenerated = $True
$ExcelTitle = ("Teams Chats for {0}" -f $Account)
Import-Module ImportExcel -ErrorAction SilentlyContinue
$OutputXLSXFile = ((New-Object -ComObject Shell.Application).Namespace('shell:Downloads').Self.Path) + "\TeamsChatListing.xlsx"
If (Test-Path $OutputXLSXFile) {
Remove-Item $OutputXLSXFile -ErrorAction SilentlyContinue
}
$ChatReport | Export-Excel -Path $OutputXLSXFile -WorksheetName "Teams Chats" -Title $ExcelTitle -TitleBold -TableName "TeamsChat"
} Else {
$OutputCSVFile = ((New-Object -ComObject Shell.Application).Namespace('shell:Downloads').Self.Path) + "\TeamsChatListing.csv"
$ChatReport | Export-Csv -Path $OutputCSVFile -NoTypeInformation -Encoding Utf8
}
If ($ExcelGenerated) {
Write-Host ("An Excel worksheet containing the report data is available in {0}" -f $OutputXLSXFile)
} Else {
Write-Host ("A CSV file containing the report data is available in {0}" -f $OutputCSVFile)
}
Attribution