Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Module clean-up script during updates
Module clean-up script during updates.
This script will presently remove all pre-existing versions from all 'Modules' paths within $env:PSModulePath.
This script will then install the desired new version within a single PSModulePath based upon the version of PowerShell running the script.
PS C:\> Invoke-Expression "& { $(Invoke-RestMethod -url "") } -ModuleList Pester"
This would be similar to running 'Install-Module Pester' on a local terminal window
PS C:\> Invoke-Expression "& { $(Invoke-RestMethod -url "") } -ModuleList Pester, PSReadline -AllowPreRelease"
This shows how you can update multiple modules in a single request and grab the very latest release for each
PS C:\> iex "& { $(irm } -ModuleList Pester -MinimumVersion 4.0 -MaximumVersion 4.9 -Force"
This shows how you might allow a the latest minor version within a given major release
PS C:\> iex "& { $(irm } -ModuleList Pester -RequiredVersion 5.1.0 -Force"
This shows how you might set a very specific version
This script will currently remove ALL pre-existing versions of a given module prior to installing so if the install fails, you may need to re-install manually.
#Requires -RunAsAdministrator
[CmdletBinding(DefaultParameterSetName = 'NewestVersion')]
param (
[string]$Repository = "PSGallery",
[string]$InstallationPolicy = 'Trusted',
[ValidateSet("AllUsers", "CurrentUser")]
[string]$Scope = "AllUsers",
[Parameter(ParameterSetName = 'MinMaxVersion')]
[Parameter(ParameterSetName = 'MinMaxVersion')]
[Parameter(ParameterSetName = 'RequiredVersion')]
Begin {
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
Process {
Set-PSRepository -Name $Repository -InstallationPolicy $InstallationPolicy
$total = $ModuleList.Count
$count = 0
Foreach ($moduleName in $ModuleList) {
Write-Verbose "Updating [$moduleName] ($count of $total)"
if ($PSEdition -eq 'Core') {
Write-Verbose "Getting versions supported by Core"
$installedVersions = Get-Module -Name $moduleName -ListAvailable -PSEdition Core
} else {
Write-Verbose "Getting versions supported by Desktop"
$installedVersions = Get-Module -Name $moduleName -ListAvailable -PSEdition Desk
$installedVersions = Get-Module -Name $moduleName -ListAvailable
if ($null -ne $installedVersions) {
$folderPaths = (Get-Item $installedVersions.modulebase).parent.Fullname | Sort-Object -Unique
foreach ($folderPath in $folderPaths) {
takeown /F $folderPath /A /R
icacls $folderPath /reset
# grant permissions to Administrators group, but use SID to do
# it because it is localized on non-us installations of Windows
icacls $folderPath /grant "*S-1-5-32-544:F" /inheritance:d /T
Remove-Item -Path $folderPath -Recurse -Force -Confirm:$false
$hash = @{}
$hash.Add("Name", $moduleName )
$hash.Add("Repository", $Repository)
$hash.Add("Scope", $Scope)
switch ($PsCmdlet.ParameterSetName) {
MinMaxVersion {
if ($PSBoundParameters.ContainsKey('MinimumVersion')) { $hash.Add("MinimumVersion", $MinimumVersion) }
if ($PSBoundParameters.ContainsKey('MaximumVersion')) { $hash.Add("MaximumVersion", $MaximumVersion) }
RequiredVersion {
$hash.Add("RequiredVersion", $RequiredVersion)
if ($PSBoundParameters.ContainsKey('AcceptLicense')) { $hash.Add("AcceptLicense", $True) }
if ($PSBoundParameters.ContainsKey('AllowClobber')) { $hash.Add("AllowClobber", $True) }
if ($PSBoundParameters.ContainsKey('AllowPrerelease')) { $hash.Add("AllowPrerelease", $True) }
if ($PSBoundParameters.ContainsKey('Force')) { $hash.Add("Force", $True) }
if ($PSBoundParameters.ContainsKey('SkipPublisherCheck')) { $hash.Add("SkipPublisherCheck", $True) }
if ($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent) {
foreach ($key in $hash.Keys) {
Write-Verbose "$key $($hash[$key])"
Install-Module @hash
End {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment