Skip to content

Instantly share code, notes, and snippets.

@jorgeasaurus
Created January 1, 2025 21:25
Show Gist options
  • Save jorgeasaurus/e902a70bfa260176bba8b0d86b81299c to your computer and use it in GitHub Desktop.
Save jorgeasaurus/e902a70bfa260176bba8b0d86b81299c to your computer and use it in GitHub Desktop.
Update PowerShell modules to their latest versions using PowerShell 7 parallel processing.
#Requires -Version 7.0
<#
.SYNOPSIS
Updates PowerShell modules to their latest versions.
.DESCRIPTION
Updates all or specified PowerShell modules to their latest versions, with options for
prerelease versions and parallel processing. Automatically removes older versions after update.
.PARAMETER AllowPrerelease
If specified, allows updating to prerelease versions.
.PARAMETER Name
Specifies the names of modules to update. Defaults to '*' for all modules.
.PARAMETER WhatIf
Shows what would happen if the function runs without actually performing updates.
.PARAMETER ThrottleLimit
Maximum number of concurrent operations. Defaults to 5.
.EXAMPLE
Update-Modules
Updates all installed modules to their latest stable versions.
.EXAMPLE
Update-Modules -Name "Az" -AllowPrerelease
Updates the Az module to its latest version, including prereleases.
#>
function Update-Modules {
param (
[switch]$AllowPrerelease, # Include prerelease versions in updates
[string]$Name = '*', # Module name filter, '*' for all modules
[switch]$WhatIf, # Preview changes without applying them
[int]$ThrottleLimit = 5 # Control parallel execution limit
)
# Initialize by getting all installed modules matching the name filter
Write-Host ("Retrieving all installed modules ...") -ForegroundColor Green
[array]$CurrentModules = Get-InstalledModule -Name $Name -ErrorAction SilentlyContinue |
Select-Object Name, Version, Repository |
Sort-Object Name
# Exit if no modules are found
if (-not $CurrentModules) {
Write-Host ("No modules found.") -ForegroundColor Gray
return
}
# Display initial status
Write-Host ("{0} modules found." -f $CurrentModules.Count) -ForegroundColor Gray
Write-Host ("Updating installed modules to the latest {0} version ..." -f $(if ($AllowPrerelease) { "PreRelease" } else { "Production" })) -ForegroundColor Green
# Store original versions for comparison in summary
$script:OldVersions = @{}
foreach ($Module in $CurrentModules) {
$script:OldVersions[$Module.Name] = $Module.Version
}
# Process updates in parallel for better performance
$CurrentModules | ForEach-Object -Parallel {
$Module = $_
$AllowPrerelease = $using:AllowPrerelease
$WhatIf = $using:WhatIf
try {
# Find the latest available version
$findParams = @{
Name = $Module.Name
AllowPrerelease = $AllowPrerelease
ErrorAction = 'Stop'
}
$latest = Find-Module @findParams | Select-Object -First 1
# Update only if a newer version is available
if ($latest.Version -and $Module.Version -and ([version]$latest.Version -gt [version]$Module.Version)) {
$updateParams = @{
Name = $Module.Name
AllowPrerelease = $AllowPrerelease
AcceptLicense = $true
Force = $true
WhatIf = $WhatIf
ErrorAction = 'Stop'
}
Update-Module @updateParams
Write-Host ("Updated {0} from version {1} to {2}" -f $Module.Name, $Module.Version, $latest.Version) -ForegroundColor Yellow
# Remove older versions to save disk space
if (-not $WhatIf) {
$AllVersions = Get-InstalledModule -Name $Module.Name -AllVersions | Sort-Object PublishedDate -Descending
foreach ($Version in $AllVersions | Select-Object -Skip 1) {
try {
Uninstall-Module -Name $Module.Name -RequiredVersion $Version.Version -Force -ErrorAction Stop
Write-Host ("Uninstalled older version {0} of {1}" -f $Version.Version, $Module.Name) -ForegroundColor Gray
} catch {
Write-Warning ("Failed to uninstall version {0} of {1}: {2}" -f $Version.Version, $Module.Name, $_.Exception.Message)
}
}
}
} else {
Write-Host ("{0} is up to date (version {1})" -f $Module.Name, $Module.Version) -ForegroundColor Cyan
}
} catch {
Write-Warning ("{0}: {1}" -f $Module.Name, $_.Exception.Message)
}
} -ThrottleLimit $ThrottleLimit
# Generate summary report of all updates
if (-not $WhatIf) {
$NewModules = Get-InstalledModule -Name $Name -ErrorAction SilentlyContinue |
Select-Object Name, Version |
Sort-Object Name
# Compare new versions with original versions
$UpdatedModules = $NewModules | Where-Object {
$script:OldVersions[$_.Name] -ne $_.Version
}
# Display summary of changes
if ($UpdatedModules) {
Write-Host "`nUpdated modules:" -ForegroundColor Green
foreach ($Module in $UpdatedModules) {
Write-Host ("- {0}: {1} -> {2}" -f $Module.Name, $script:OldVersions[$Module.Name], $Module.Version) -ForegroundColor Green
}
} else {
Write-Host "`nNo modules were updated." -ForegroundColor Gray
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment