12 min read
Licensing with Microsoft Graph PowerShell
The Microsoft Graph SDK PowerShell module is replacing two other modules. Learn more about connecting to Graph, finding...
ScriptRunner Blog
Damian shares his knowledge about Microsoft Graph. His third article goes into detail about teams and introduces the Microsoft.Graph.Teams module. Learn how and when to use the sub-module.
In the first two articles in this series, we explored Graph PowerShell and its wide array of sub-modules and cmdlets and then we covered the uses of Graph PowerShell and Exchange Online. Proceeding forward, we now explore Microsoft Teams and Graph PowerShell and in doing so, we find a different setup. The biggest is that we have a dedicated sub-module called Microsoft.Graph.Teams which has hundreds of different cmdlets. We also find commonalities where 'Teams' cmdlets exist outside of this code sub-module:
We can run a quick bit of PowerShell to find any cmdlet with Team in it and get a count by sub-module:
$uniqueTeamsCmdletSources = Get-Command *team* | Where-Object Source -Like *graph* | Sort-Object Source -Unique
$uniqueTeamsCmdletSources.Source |
ForEach-Object {
Write-Host $_ -ForegroundColor Green -NoNewline
Write-Host ' - ' -NoNewline
Write-Host "$((Get-Command *team* -Module $_).Count)"
}
Yielding this:
Cmdlet count per sub-module
Now the Microsoft.Graph.Teams sub-module does have more cmdlets, which do not have the noun 'Team' in them and indeed it has 654 total cmdlets. This leaves 121 cmdlets without that noun. Confirmation:
(Get-Command -Module Microsoft.Graph.Teams | Where-Object Name -NotLike *team*).Count
As we did with Exchange Online, here we will quickly cover some of the common tasks that could be accomplished with the dedicated Microsoft Teams PowerShell Module.
Although this was covered in the first and second articles in this series, it bears repeating that when using Graph PowerShell, we need to scope permissions properly to use the Teams cmdlets.
$AllCmdlets = @()
Foreach ($Cmdlet in $GraphTeamsCmdlets) {
Try {
$Line = Find-MgGraphCommand $Cmdlet.Name -ERRORACTION STOP |
Select Command,Method,URI,Permissions
} Catch {
}
$AllCmdlets += $Line
}
$AllCmdlets |
Select Command,Permisions
Yielding this:
Truncated list of permissions needed
A long list of permissions is needed to run the myriad of cmdlets in the Teams sub-module of Graph. You can download the full output of this file from here.
We can also pull a summary of all delegated Teams permissions using a simple one-liner:
Find-MgGraphPermission teams -PermissionType Delegated
List of permissions for Teams cmdlets in Graph
Well, all these cmdlets are well and good until an Administrator needs to perform a task and has to decide what module to perform a task in. So how should an administrator approach this module? One way is to look at the cmdlets in bunches, perhaps by verbs or nouns. If one wants to perform a particular task, like manage Team reactions, then a noun search would be better. Below we can example these groups by nouns to get an idea what is present in Microsoft Teams vs. Microsoft.Graph.Teams.
When comparing the types of cmdlets, versus what is present in each module, we see cat differences in the types/number of cmdlets:
Comparison of available cmdlets
You can see a breakdown of some cmdlet groups for comparison. The examples above are done by keyword – 'clear', team reactions and dial.
Going forward, those new to Microsoft.Graph.Teams should get a full list of cmdlets and breakdown what is familiar to them in terms of the cmdlets nouns. By doing so they might be able to discern cmdlets to use for their management tasks. Once identified, then review the help and examples for each cmdlet to begin building one-liners and scripts using these newly discovered cmdlets.
Discussing cmdlets and how they are groups can be interesting for those exploring what can be manage in Microsoft Teams with Graph PowerShell, but being able to translate into useable code is by far the most valuable activity. In the below section we will walk through some example scenarios where Graph PowerShell is of use to Administrators.
Combining cmdlets like these three: Get-MgTeam, Get-MgUser, and Get-MgUserJoinedTeam, we can build a script that verifies Microsoft Team memberships. Why would we want to do this? Some sample scenarios would be a tenant-to-tenant migration where we need to validate Team memberships were populated by an external process. Perhaps to validate that at members of a group are members of their respective Teams.
Get-MgUserJoinedTeam -UserId damian@powershellgeek.com
Get-MgUser | ForEach-Object {
Write-Host "$($_.DisplayName)" -ForegroundColor Green
$Groups = Get-MgUserJoined
Team -UserId $_.Id
If ($Groups.Count -eq 0 ) {
Write-host 'No Groups' -ForegroundColor Yellow
} Else {
$Groups
}
}
Get-MgTeamMember -TeamId cfdba387-1319-4f6b-a883-8700046f07e7
List of members in a Team (default view)
$Members | Format-List
Additional properties
Notice that each member of the Team has a property called 'additional properties' and inside of this, we see the 'userId' key/value pair.
Now that we have a list of members, we can pull that user's Id which could then in turn be used in a lookup of the full user account:
$Members.AdditionalProperties.userId
Notice that 'userId' is actually case-sensitive and is something that may be worth remembering for future properties of Graph objects. We can now loop this into finding all user properties for group members:
$Members.AdditionalProperties.userId | ForEach-Object { Get-MgUser -UserId $_ }
List of users, their Ids, mail address and UserPrincipalNames (UPN)
Get-MgTeam | ForEach-Object {
Write-Host "$($_.DisplayName)" -ForegroundColor Green
$Members = Get-MgTeamMember -TeamId $_.id
$Members.AdditionalProperties.userId |
ForEach-Object {
Get-MgUser -UserId $_
}
}
Another area where the cmdlets differ between the modules is Channel management where the Microsoft Teams module has 14 cmdlets with the noun 'channel' in them whereas the Microsoft.Graph.Teams PowerShell module has 283 cmdlets:
A small sampling of Teams cmdlets, focused on the noun 'channel'
Among these cmdlets, we will see many similarities:
Add-TeamChannelUser, Get-TeamChannelUser and Remove-TeamChannelUser
Add-MgTeamChannelMember, Add-MgTeamPrimaryChannelMember, Add-MgTeamworkDeletedTeamChannelMember, Get-MgGroupTeamChannelMember, Get-MgGroupTeamChannelMemberCount, Get-MgGroupTeamPrimaryChannelMember, Get-MgGroupTeamPrimaryChannelMembe rCount, Get-MgTeamChannelMember, Get-MgTeamChannelMemberCount, Get-MgTeamPrimaryChannelMember, Get-MgTeamPrimaryChannelMemberCount
Get-MgTeamworkDeletedTeamChannelMember, Get-MgTeamworkDeletedTeamChannelMemberCount, New-MgGroupTeamChannelMember, New-MgGroupTeamPrimaryChannelMember, New-MgTeamChannelMember, New-MgTeamPrimaryChannelMember, New-MgTeamworkDeletedTeamChannelMember, Remove-MgGroupTeamChannelMember, Remove-MgGroupTeamPrimaryChannelMember, Remove-MgTeamChannelMember, Remove-MgTeamPrimaryChannelMember, Remove-MgTeamworkDeletedTeamChannelMember, Update-MgGroupTeamChannelMember, Update-MgGroupTeamPrimaryChannelMember, Update-MgTeamChannelMember, Update-MgTeamPrimaryChannelMember and Update-MgTeamworkDeletedTeamChannelMember
What we see is that the Graph PowerShell cmdlets are more numerous, and more laser focused on certain aspects of user memberships in a Team Channel and also the fact that users are called members in the cmdlets whereas the same nomenclature in Teams refers to users as 'users' not members.
First, we need an Id of the Team where we are getting the Channel memberships of:
Get-MgTeam
Copy the Id of the Team and then get a list of channels:
Get-MgTeamChannel -TeamId cfdba387-1319-4f6b-a883-8700046f07e7
Copy the Id of the channel and now pull members of that channel:
Get-MgTeamChannelMember -ChannelId 19:1b01cc16e436489dbf22462dfce1443d@thread.skype -TeamId cfdba387-1319-4f6b-a883-8700046f07e7
What if we want a list of all members, of all Team / channels?
$Teams = Get-MgTeam | Select DisplayName,Id
Foreach ($Team in $Teams) {
$Channels = Get-MgTeamChannel -TeamId $Team.Id
Foreach ($Channel in $Channels) {
$AllMembers = $Null
$AllMembers = @()
$JoinedMembers = $Null
$JoinedMembers = @()
$Members = Get-MgTeamChannelMember -ChannelId $Channel.Id -TeamId $Team.Id
Write-Host "$($Team.DisplayName)" -ForegroundColor Green -NoNewline
Write-Host " / $($Channel.DisplayName) / " -ForegroundColor Yellow -NoNewLine
$MemberCount = $Members.Count
If ($MemberCount -gt 2) {
Foreach ($Member in $Members) {
$AllMembers += $Member.AdditionalProperties.email
}
$JoinedMembers = $AllMembers -join ','
$JoinedMembers
} Else {
Write-Host "$($Member.AdditionalProperties.email)"
}
}
}
Running this code will provide these results:
Consent to permissions
Note that you will need to consent to the these permissions to make it work: Team.ReadBasic.All,ChannelMember.Read.All.
In this example we have a consulting firm that wants to create a new team each time a client is on-boarded and needs assistance. We can use PowerShell to create the Team, create channels and add members to each as needed for the project work to occur.
First, we have a CSV input file to be used for configuration of the new teams:
Name, Description, AllowAddRemoveApps, AllowCreatePrivateChannels, AllowCreateUpdateChannels, AllowDeleteChannels, AllowCreateUpdateRemoveConnectors, AllowCreateUpdateRemoveTabs, Guest-AllowCreateUpdateChannels, Guest-AllowDeleteChannels
"Project Falcon","Falcon, llc - client team",$False,$True,$True,$False,$True,$False,$False,$False
"Big Box, Inc.","Big Box, Inc. - Banking Industry",$False,$True,$True,$True,$True,$False,$False,$False
Using the PowerShell code block below, we can create the new Teams:
Foreach ($Team in $Teams) {
$params = @{
"template@odata.bind" = "https://graph.microsoft.com/v1.0/teamsTemplates('educationClass')"
DisplayName = $Team.Name
Description = $Team.Description
Visibility = $Team.visibility
MemberSettings = @{
AllowAddRemoveApps = $Team.allowAddRemoveApps
AllowCreatePrivateChannels = $Team.AllowCreatePrivateChannels
AllowCreateUpdateChannels = $Team.allowCreateUpdateChannels
AllowCreateUpdateRemoveConnectors = $Team.allowCreateUpdateRemoveConnectors
AllowCreateUpdateRemoveTabs = $Team.allowCreateUpdateRemoveTabs
AllowDeleteChannels = $Team.allowDeleteChannels
}
GuestSettings = @{
AllowCreateUpdateChannels = $Team.AllowCreateUpdateChannels
AllowDeleteChannels = $Team.AllowDeleteChannels
}
}
Try {
New-MgTeam -BodyParameter $params -ErrorAction STOP
} Catch {
Write-Host 'Failed to create team: ' -ForegroundColor Red -NoNewline
Write-Host "Error message - $_.Exception.Message" -ForegroundColor Yellow
}
}
After the code is run, no feedback is provided, so we will need to run Get-MgTeam to validate the creation:
New Teams are present in the red rectangle
Then we need some sort of input CSV for channels:
Team,ChannelName,Members,Description,membershipType
"HR Department",InternalProject-Vision,,"Effort to upgrade ERM app.",standard
"HR Department",InternalProject-Money,,"Effort to improve salaries.",private
Using this CSV, we can run the below block of PowerShell code:
Foreach ($Channel in $TeamsChannels) {
$teamId = (Get-MgTeam | Where-Object DisplayName -eq $Channel.Team).Id
$params = @{
"@odata.type" = "#Microsoft.Graph.channel"
MembershipType = $Channel.MembershipType
DisplayName = $Channel.ChannelName
Description = $Channel.Description
}
Try {
New-MgTeamChannel -TeamId $teamId -BodyParameter $params -ErrorAction STOP
} Catch {
Write-Host 'Failed to create channel in Team: ' -ForegroundColor Red -NoNewline
Write-Host "Error message - $_.Exception.Message" -ForegroundColor Yellow
}
}
Which yields these results from the sample CSV:
We see our two new channels that were added to the HR Team
Microsoft Teams is as complex a product as Exchange Online to manage. There are hundreds of settings and nuances to be aware of and secure to make the most of Teams. In the Microsoft.Graph.Teams module we are able to provide some real management and processing of settings, teams, channels and users with PowerShell. There are some operations that are not possible, for example, there is no Grant set of cmdlets, so those operations will need to be performed in the Microsoft Teams PowerShell module. Now, like everything in Teams, it will take some time to get the permissions correct and some extra work will be needed to create BodyParameter settings to appropriately make changes. The hint here is to use help and practice some examples. In the end, this sub-module is quite useful and more so than the Exchange cmdlets in Graph – worth the time of Microsoft Teams administrators to learn.
Simplify and automate your Microsoft Teams management with our 8-page PowerShell cheat sheet for Microsoft Teams. This handy guide provides you with quick-reference cmdlets and code snippets to manage users, channels, policies and more with ease. Ideal for both beginners and seasoned administrators.
Unleash the full potential of PowerShell with our handy poster. Whether you're a beginner or a seasoned pro, this cheat sheet is designed to be your go-to resource for the most important and commonly used cmdlets.
The poster is available for download and in paper form.
Get your PowerShell goodies here!
And do you know our webinars?
Managing Teams can be pretty time consuming. Have you ever wondered how you could optimize and reduce the arising workload?
The PowerShell module for Microsoft Teams is your key: it allows you to standardize and automate many repetitive tasks.
This webinar is aimed at administrators, IT and DevOps professionals, PowerShell developers and IT managers.
Sign up for the next Teams webinar!
Sep 14, 2023 by Damian Scoles
The Microsoft Graph SDK PowerShell module is replacing two other modules. Learn more about connecting to Graph, finding...
Mar 6, 2024 by Damian Scoles
With MS Online and Azure AD module deprecation, it's time to map previous tasks to new methods. We hope the following...
Oct 8, 2024 by Damian Scoles
Users will encounter one or two hurdles when they start using Graph. Damian Scoles wrote three articles provides help...
Damian Scoles is a ten-time Microsoft MVP specializing in Exchange, Office 365 and PowerShell who has 25 years of IT industry experience. He is based in the Chicago area and started out managing Exchange 5.5 and Windows NT. Over the years he has worked with Office 365 since BPOS and his experience has grown to include Azure AD, Security and Compliance Admin Centers, and Exchange Online. His community outreach includes contributing to TechNet forums, creating PowerShell scripts that can be found on his blogs, writing in-depth PowerShell / Office365 / Exchange blog articles, tweeting, and creating PowerShell videos on YouTube. He has written five PowerShell books and is also actively working on the book "Microsoft 365 Security for IT Pros".