Why the PowerShell Module for Teams is Critically Flawed
Update 5 December:Microsoft has released Version 0.9.1 of the PowerShell module for Teams. Use this version for your testing. It is less buggy than 0.9 and has the ability to create a new team for an Office 365 Group that already exists. Remember to run Uninstall-Module MicrosoftTeams -AllVersions to remove the old version before you try to install the updated module.
Update: See this article for the latest on the Teams PowerShell module.
PowerShell for Teams
Fans of Microsoft Teams applauded the release of a beta version (0.90) of a PowerShell module for Teams, the first sign that Microsoft is close to fulfilling their commitment made at the Ignite 2017 conference. Some documentation is also available on GitHub.
The Teams module holds 24 cmdlets from Connect-MicrosoftTeams, which you use to connect to the endpoint for Teams, to Set-TeamGuestSettings, to set the properties of a team that govern how guest users interact with the team. You can use the cmdlets to update team settings, add or remove channels, add or remove members to a team, or even create a new team. And most importantly, you can update the photo (avatar) for a team.
The module is easy to install, but that is the highlight. Everything else about the Teams PowerShell module is a disappointment, not least because it is unstable (at least, in my hands). Figure 1 shows how the fundamental Get-Team cmdlet responds sometimes.
Problems are expected in unfinished code. I accept that. What I find problematic and worrying is the approach the developers took in creating the cmdlets and how the cmdlets behave.
Teams and Groups
Given the dependency on Office 365 Groups, it is natural to assume that the Teams module would function somewhat like the cmdlets used to interact with Groups. These cmdlets are in the Exchange Online set and behave in a similar manner to other Exchange cmdlets, meaning that you can identify the target object for a cmdlet using several ways.
For instance, to return the properties of a group with the Get-UnifiedGroup cmdlet, you can pass the name, alias, email address, display name, distinguished name, or – if you really must, the object’s GUID.
Uniqueness Does Not Mean Goodness
The best thing about a GUID is its guarantee of uniqueness. It is, after all, a globally unique identifier. Every object in Azure Active Directory has a GUID. For instance, to retrieve the GUID for an Office 365 Group, you can use this command:
[PS] C:\> $GroupId = (Get-UnifiedGroup -Identity GroupName).ExternalDirectoryObjectId
The $Group variable now holds the GUID, a value like 84fee8ec1-d85f-4564-a786-1f7bedd9862c.
Equipped with the GUID, we can now use the Teams PowerShell cmdlets to interrogate various settings of a team. For example, here is how to return the settings controlling what team members can do with channels, apps, tabs, and connectors.
[PS] C:\> Get-TeamMemberSettings -GroupId $GroupId
AllowCreateUpdateChannels : True
AllowDeleteChannels : False
AllowAddRemoveApps : True
AllowCreateUpdateRemoveTabs : True
AllowCreateUpdateRemoveConnectors : True
The problem with GUIDs is immediately apparent. They are difficult to remember and utterly incomprehensible to humans. On the upside, computers like them.
The Teams PowerShell module insists on using GUIDs to identify teams. That approach is fine if you write scripts because you can fetch the GUID, put it in a variable, and then use that variable with the Teams cmdlets.
It is a pain to have to deal with GUIDs when you use PowerShell interactively. I cannot understand why the Teams developers went down this route and failed to follow the lead set by Groups to support identifying teams via their name, display name, or alias (of the underlying group). Doing so would have made these cmdlets easier to use.
The developers of the Azure Active Directory PowerShell module take the same approach and use GUIDs to identify objects. But at least they provide the ability to search for an account, group, or other object.
GUIDs Might Be Good
Arguing against myself, I could construct some logic for insisting on GUIDs. First, Teams does not insist on unique display names and it is possible to have multiple teams that share the same name (a confusing state that should be not allowed). Second, Teams does not use email in the same way as Groups, so can make the case that aliases are unavailable unless you load the Exchange Online cmdlet set into a session. That seems reasonable, but surely some programming magic could make the group alias available.
Third, the Teams cmdlets appear to be based on the Microsoft Graph API, which just loves GUIDs. The easiest way for the Teams developers to create the PowerShell cmdlets is to keep them as close as possible to the underlying Graph code.
The Big Problem with Teams PowerShell
I do not like dealing with GUIDs, but I can get over it. The biggest issue with the Teams PowerShell module is the way that the developers take a user-centric view of teams instead of a tenant-wide view. It looks very much like the idea is to transpose whatever functionality is available in the Teams client to PowerShell cmdlets. It is natural to work with the settings for a single team through a client GUI, but not with PowerShell.
Critically, there is no way to create a collection of the complete set of teams in a tenant. The Get-Team cmdlet, which you might assume is the way to fetch information about teams, does nothing more than return the set of teams that the currently signed in user belongs to. Unsurprisingly, that is exactly the function needed by the Teams client.
It would be acceptable if the cmdlet was called Get-MyTeams, but administrators more often need to work with all the teams in a tenant.
PowerShell exists to automate common administrative operations. It has been that way since Exchange 2007 was the first major Microsoft server application to embrace PowerShell in 2006. To automate administration, you need to be able to work with all the objects of a certain type, not just those associated with a user. You need to be able to filter the set of available objects (hopefully, using server-side filtering) to return the set that you want to work with. You can then step through each object to decide how to process it.
Get-UnifiedGroup Does Not Help
You can make the argument that you can use the Get-UnifiedGroup cmdlet to work with the Office 365 Groups that underpin Teams. However, although every team has a group, not every group has a team.
The other issue is that Get-UnifiedGroup supports no method to return just the set of groups that are team-enabled. It would be wonderful if Microsoft updated the cmdlet so that group properties included indicators of whether a group was linked to Teams, Planner, Stream, Yammer, and the other Office 365 apps that use Office 365 Groups as an identity and membership service.
Waiting For 1.0
Some will say that these criticisms are unfair to Microsoft. After all, having a flawed PowerShell module for Teams is better than having no module. I agree, but that is no reason to ignore obvious problems.
It is also true that the module has not even reached 1.0 status yet. Something wonderful might happen between 0.9 and 1.0, but I suspect not. I think that the developers are tied into GUIDs and have focused on dealing with individual teams rather than delivering the ability to manage sets of teams. My hope is that by raising the issue now, Microsoft might be willing to improve matters in the future.
We await the release of the 1.0 module and full documentation to make a final call on the usefulness of the PowerShell module for Teams. For now, I am disappointed because I think the current module is nowhere near as valuable as it should be. I await being proven wrong.
Follow Tony on Twitter @12Knocksinna.
Want to know more about how to manage Office 365? Find what you need to know in “Office 365 for IT Pros”, the most comprehensive eBook covering all aspects of Office 365. Available in PDF and EPUB formats (suitable for iBooks) or for Amazon Kindle.