Table of Contents
PowerShell Module Clash After Recent Microsoft 365 Module Updates
There’s been a bunch of updates for PowerShell modules used to manage Microsoft 365 tenants lately. The Microsoft Graph PowerShell SDK reached version 2.7.0 and then retreated to version 2.6.1 because of a problem with the Restore-MgDirectoryDeletedItem cmdlet. The Microsoft Teams module is now at version 5.7.1 and the Exchange Online module has reached version 3.4. With so much updating to do, I’m glad that I have scripts to update the Microsoft 365 modules on my PC and update the Microsoft 365 modules used as resources in Azure Automation accounts.
After a frenzy of updating, I spun up a new PowerShell session (itself updated to version 7.3.8) and ran the Connect-MicrosoftTeams cmdlet to connect to Teams followed by Connect-Exchange Online. Teams connected but Exchange Online barfed because of an issue loading the Microsoft.Identity.Client DLL. The PowerShell module clash looked like this:
PowerShell 7.3.8 Connect-MicrosoftTeams Account Environment Tenant TenantId ------- ----------- ------ -------- Tony.Redmond@office365itpros.com AzureCloud a562313f-14fc-43a2-9a7a-d2e27f4f3478 a662313f-14fc-43a2-9a7a-d2e27f4f34… Connect-ExchangeOnline OperationStopped: Could not load file or assembly 'Microsoft.Identity.Client, Version=18.104.22.168, Culture=neutral, PublicKeyToken=0a613f4dd989e8ae'.
Different Versions and Dependencies Cause PowerShell Module Clash
A dynamic link library (DLL) is a hunk of sharable code that applications can use. In this case, the two modules call functions in Microsoft.IdentityClient.Dll to authenticate against Entra ID. The problem is that Teams loads version 4.299 of the DLL and when Exchange Online comes along, it has a declared dependency on version 4.44 of the same DLL. PowerShell 7 runs on .NET core and only allows one version of a DLL to load at any time, so the request made by Exchange Online to load version 4.44 is blocked by version 4.299 loaded by Teams. Exchange Online isn’t happy to use a lower version of the module because it might be dependent on something in version 4.44, which leads us to the barf because the assembly couldn’t load.
It’s all perfectly logical and if you reverse the process and connect to Exchange Online first in a session, it loads version 4.44. If you then connect to Teams, the versioning rules for .NET Core allows the Teams module to load a higher version of the module, which is already present. The Teams module is therefore happy to use version 4.44 instead of 4.299. The only workaround to the problem is to close the PowerShell session and restart, loading the Exchange Online module first before loading the Teams module.
Lack of Coordination within Microsoft
Logical as the explanation is (and better than the all-too-often instances when we can’t understand why software fails), it’s disappointing that two Microsoft engineering groups working in the Microsoft 365 ecosystem cannot agree on which version of a critical DLL to use.
Exchange Online has done a lot of work recently to remove basic authentication from email connection protocols. Recently, they also removed support for Remote PowerShell. It’s understandable that their code base is in a state of change. By comparison, since the deprecation of the Skype for Business Connector, the degree of major change for the Teams PowerShell module has been less evident. Sure, Microsoft has modernized cmdlets, fixed bugs, added properties, and so on, but they haven’t ripped the guts out of their authentication stack. It’s plausible that the Teams developers were happy with the older version of the DLL because not much recent change happened (for them) in authentication and this might have allowed a gap to open in DLL versions.
I don’t know if this is what happened. It’s plausible based on observation, but that’s about all. Only Microsoft can say exactly why the two engineering groups arrived in a state of conflict. In any case, because modules like Teams and Exchange are often used together in scripts and interactive sessions, it would be nice if the development groups that produce PowerShell modules used in Microsoft 365 tested for clashes before releasing new versions of their modules.
It’s worth making the point that a dependency clash can happen for any module. I’ve experienced the same problem recently with the Pnp.PowerShell module (here’s a known issue). For instance, in a PowerShell 7 session, run Connect-MgGraph to connect to the Graph and then run Connect-PnpOnline to see another barf:
Connect-PnPOnline: Could not load file or assembly 'Microsoft.Identity.Client, Version=22.214.171.124, Culture=neutral, PublicKeyToken=0a613f4dd989e8ae'. Could not find or load a specific file. (0x80131621)
The truth is that once software has a dependency on something, things can go wrong when the underlying dependency changes. Pnp.PowerShell is a community initiative, so it can’t be blamed for something like this, but Microsoft engineering groups…
Stay Calm and Keep on Updating Your Modules
Microsoft knows about the problem and I believe work is under way to straighten things out. I’m not sure when the results of that activity will be available.
I still believe in updating PowerShell modules soon after new modules become available. It’s better to take advantage of fixes for reported problems than run old modules and find known bugs. But it’s still wise to test updated modules just in case something weird happens, like a version mismatch that causes a PowerShell module clash.
Support the work of the Office 365 for IT Pros team by subscribing to the Office 365 for IT Pros eBook. Your support pays for the time we need to track, analyze, and document the changing world of Microsoft 365 and Office 365.