Important to Update PowerShell Modules Regularly
Updated: 15 August 2023
It’s important to keep PowerShell modules updated because Microsoft introduces new cmdlets and cmdlet parameters to support new functionality, like SharePoint Online site URL rename. Or when Microsoft updates the Microsoft Graph PowerShell SDK or MicrosoftTeams modules, both of which receive updates on a monthly (or even more frequent) basis.
Scripting PowerShell Updates
Most of the important PowerShell modules used with Microsoft 365 are now available in the PowerShell Gallery and can be installed and updated from there. It seemed appropriate to write a script to:
- Define a set of modules that I’m interested in updating, such as the Exchange Online Management module, Microsoft Teams, the Microsoft Graph PowerShell SDK, ORCA (used to check Advanced Threat Protection Settings) and so on.
- Check the PowerShell Gallery to see if an update is available, and if so, download and install it.
- Clean up afterwards by checking the PC for versions of a module and removing all but the latest to ensure that scripts only ever run the latest cmdlets.
Here’s the basic processing steps for the original version of the script (I update the code on an ongoing basis to cope with changes, such as the split of the Microsoft Graph PowerShell SDK into V1.0 and beta modules from V2 onward). The script must be run after starting PowerShell as an administrator (otherwise you won’t be able to install the updates). Make sure that all other PowerShell sessions are ended to avoid the possibility of trying to update a module that’s in use.
# Define the set of modules installed and updated from the PowerShell Gallery that we want to maintain $O365Modules = @("MicrosoftTeams", "MicrosoftTeams", "Microsoft.Graph", "ExchangeOnlineManagement", "Microsoft.Online.Sharepoint.PowerShell", "ORCA") # Check and update all modules to make sure that we're at the latest version ForEach ($Module in $O365Modules) { Write-Host "Checking and updating module" $Module Update-Module $Module -Force -Scope AllUsers } # Check and remove older versions of the modules from the PC ForEach ($Module in $O365Modules) { Write-Host "Checking for older versions of" $Module $AllVersions = Get-InstalledModule -Name $Module -AllVersions $AllVersions = $AllVersions | Sort-Object PublishedDate -Descending $MostRecentVersion = $AllVersions[0].Version Write-Host "Most recent version of" $Module "is" $MostRecentVersion "published on" (Get-Date($AllVersions[0].PublishedDate) -format g) If ($AllVersions.Count -gt 1 ) { # More than a single version installed ForEach ($Version in $AllVersions) { #Check each version and remove old versions If ($Version.Version -ne $MostRecentVersion) { # Old version - remove Write-Host "Uninstalling version" $Version.Version "of Module" $Module -foregroundcolor Red Uninstall-Module -Name $Module -RequiredVersion $Version.Version -Force } #End if } #End ForEach } #End If } #End ForEach
You can download the latest version of the script from GitHub and amend it to update the modules you use. Because I use the script to keep my PCs updated with the latest PowerShell modules, the current code is more developed and comprehensive than the snippet shown above. The script isn’t perfect, but it gets the job done for me.
Figure 1 shows some typical output as the script processes the set of Microsoft 365 PowerShell modules and updates those when a new version is available in the PowerShell gallery.

The script installs and updates modules in the $env:ProgramFiles\PowerShell\Modules location to make sure that the files are on the local workstation and available to all users. From PowerShell 6 onward, the default is to install modules in $HOME\Documents\PowerShell\Modules, which might mean that they end up in OneDrive.
Monthly Updates
Given the cadence of Microsoft updates for PowerShell modules, it’s a good idea to update PowerShell modules every month or six weeks. Perhaps reflecting the ongoing growth in Graph APIs, the Microsoft Graph PowerShell SDK receives even more frequent updates. If you use the Graph SDK with Azure Automation, make sure that you update PowerShell modules for the Graph SDK in your Azure Automation accounts too.
Checking, updating, and removing PowerShell modules is not a fast process, but it does help to keep your scripting in good health.
The Office 365 for IT Pros eBook includes extensive coverage of managing Office 365 applications with PowerShell, so we pay attention to this kind of stuff – just like you should.
I receive a number of scope errors when attempting to run this script. Can you provide any guidance to remedy?
Error message syntax:
Update-Module : A parameter cannot be found that matches parameter name ‘Scope’.
…
+ Update-Module $Module -Force -Scope AllUsers }
+ ~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Update-Module], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,Update-Module
From https://docs.microsoft.com/en-us/powershell/module/powershellget/update-module?view=powershell-7
-Scope
Specifies the installation scope of the module. The acceptable values for this parameter are AllUsers and CurrentUser. If Scope isn’t specified, the update is installed in the CurrentUser scope.
The AllUsers scope requires elevated permissions and installs modules in a location that is accessible to all users of the computer:
You’re not running PowerShell in an administrator session.
Thank you for the response, Tony. I am launching Windows PowerShell ISE as administrator and have local admin rights on my PC. Any other thought? Should I try changing the value to CurrentUser if I’m only concerned with it updating for my profile?
You could certainly do that… But before you do, try opening a simple PowerShell session as an admin (not ISE) to see if that works.
One step ahead. I did to no avail. Also tried swapping out AllUsers for CurrentUser. with no luck. Same error complaining that “A parameter cannot be found that matches the parameter name ‘Scope’.”
Sorry to reply so late. Updating Powershellget to version 2.2.3 should resolve this issue as it adds the -scope parameter to the Update-Module command.
Hoping @Paul ticked the ‘Notify me of new comments via email’ checkbox ;p)
Thanks, Matt. I did have it checked, fortunately. 🙂 Update-Module did improve the script run some but I still have a number of lines returning
—–
Checking and updating module MicrosoftTeams
Update-Module : A parameter cannot be found that matches parameter name ‘Scope’.
At C:\Users\aaa0013.BUILD\OneDrive – BMC\Documents\WindowsPowerShell\Scripts\Office 365\UpdateOffice365PowerShellModulesCurrentUser.ps1:15 char:33
+ Update-Module $Module -Force -Scope CurrentUser }
+ ~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Update-Module], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,Update-Module
—–
But then later in the script it returns:
—–
Checking for older versions of MicrosoftTeams
Most recent version of MicrosoftTeams is 1.1.6 published on 9/14/2020 10:22 PM
Uninstalling version 1.0.2 of Module MicrosoftTeams
—–
So I think it worked?
Any thoughts on this error:
$CurrentVersion = $CurrentVersion.Major.toString() + “.” + $CurrentVersion.Minor.toString() + “.” + $CurrentVersion.Build.toString()
You cannot call a method on a null-valued expression.
At line:1 char:1
+ $CurrentVersion = $CurrentVersion.Major.toString() + “.” + $CurrentVe …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Is this a Powershell version thing?
There’s some issue with the $CurrentVersion variable. What is its value?
This code might be better:
$CurrentVersion = (Find-Module -Name $Module | Select-Object -ExpandProperty Version)
If ($CurrentVersion) {
$CurrentVersion = $CurrentVersion.Major.toString() + “.” + $CurrentVersion.Minor.toString() + “.” + $CurrentVersion.Build.toString()
Write-Host (“Current version of the {0} module in the PowerShell Gallery is {1}” -f $Module, $CurrentVersion)
} Else {
$CurrentVersion = “0.0.0”
Write-Host (“No module found for {0}” -f $Module) }
Here’s where I ran those two lines from the script manually. The $currentversion variable does get populated, but the error seems to be generated by the $currentversion.major.tostring() part. Maybe I’m missing something obvious.
$CurrentVersion = (Find-Module -Name MicrosoftTeams | Select-Object -ExpandProperty Version)
$currentversion
4.9.1
$CurrentVersion = $CurrentVersion.Major.toString() + “.” + $CurrentVersion.Minor.toString() + “.” + $CurrentVersion.Build.toString()
You cannot call a method on a null-valued expression.
At line:1 char:1
+ $CurrentVersion = $CurrentVersion.Major.toString() + “.” + $CurrentVe …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Did you try the altered code that I posted? The change I made checks to see if a current version is on the PC (it might not be) and returns a version of 9.0.0 if a module is not present.
Yes, I did try that. Same error. Like I said, when I run that line by itself, it doesn’t seem to recognize the “Major” keyword as valid. I’m getting the version number in $currentversion, but it doesn’t like the line where the script breaks it up into Major, Minor, & Build. Are those variables version specific, are they defined in a function elsewhere?
The version information should come from the PowerShell module that’s registered on your PC. Can you run a Get-Module for the module that it’s failing for and examine what comes back?
I get the same error for each module that it checks. If it’s working for you and not for me, it must be something on my side. I’m researching the source of “major”,”minor” and “build” to see where they come from. That is what’s failing, not the overall script itself.
Apparently the issue was that the $currentversion variable was not cast as [version]. Once I added that, I got no errors. Thanks so much for your script and your assistance.
I also added some code to check if any of the [version] numbers came back as negative (no value). Otherwise, you get this error:
$orcaVersion = $orcaVersion.Major.toString() + “.” + $orcaVersion.Minor.toString() + “.” + $orcaVersion.Build.toString()
Cannot convert value “2.1.-1” to type “System.Version”. Error: “Version’s parameters must be greater than or equal to zero.
Parameter name: build”
At line:1 char:1
+ $orcaVersion = $orcaVersion.Major.toString() + “.” + $orcaVersion.Min …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
+ FullyQualifiedErrorId : RuntimeException
On my machine, the 2.4 version of the script throws an error running under PS 5.1, where the Update-Module command doesn’t recognize the -Scope parameter. After removing that it works just fine. This was on my Windows 11 machine.
Correct. The script is designed to run under PowerShell 7.