PowerShell Module Versioning
Side-by-side versions are two or more versions of one module kept at the same time. Each version lives in its own folder, and you can load one exact version when you need it.
Each version lives in its own version folder
Two version folders are built for one module. The list shows both versions in order.
$env:PSModulePath = $PSScriptRoot + ":" + $env:PSModulePath
$null = New-Item -ItemType Directory -Force -Path (Join-Path $PSScriptRoot "GreetTools/1.0.0")
$null = New-Item -ItemType Directory -Force -Path (Join-Path $PSScriptRoot "GreetTools/2.0.0")
Set-Content -Path (Join-Path $PSScriptRoot "GreetTools/1.0.0/GreetTools.psm1") -Value 'function Get-Greeting { "Hello v1" }'
Set-Content -Path (Join-Path $PSScriptRoot "GreetTools/1.0.0/GreetTools.psd1") -Value '@{ RootModule = "GreetTools.psm1"; ModuleVersion = "1.0.0"; FunctionsToExport = @("Get-Greeting") }'
Set-Content -Path (Join-Path $PSScriptRoot "GreetTools/2.0.0/GreetTools.psm1") -Value 'function Get-Greeting { "Hello v2" }'
Set-Content -Path (Join-Path $PSScriptRoot "GreetTools/2.0.0/GreetTools.psd1") -Value '@{ RootModule = "GreetTools.psm1"; ModuleVersion = "2.0.0"; FunctionsToExport = @("Get-Greeting") }'
Get-Module -ListAvailable -Name "GreetTools" | Sort-Object Version | ForEach-Object { $_.Version.ToString() }Importing by name alone loads the newest version
No version is named on import. The newest version answers the call.
$env:PSModulePath = $PSScriptRoot + ":" + $env:PSModulePath
$null = New-Item -ItemType Directory -Force -Path (Join-Path $PSScriptRoot "GreetTools/1.0.0")
$null = New-Item -ItemType Directory -Force -Path (Join-Path $PSScriptRoot "GreetTools/2.0.0")
Set-Content -Path (Join-Path $PSScriptRoot "GreetTools/1.0.0/GreetTools.psm1") -Value 'function Get-Greeting { "Hello v1" }'
Set-Content -Path (Join-Path $PSScriptRoot "GreetTools/1.0.0/GreetTools.psd1") -Value '@{ RootModule = "GreetTools.psm1"; ModuleVersion = "1.0.0"; FunctionsToExport = @("Get-Greeting") }'
Set-Content -Path (Join-Path $PSScriptRoot "GreetTools/2.0.0/GreetTools.psm1") -Value 'function Get-Greeting { "Hello v2" }'
Set-Content -Path (Join-Path $PSScriptRoot "GreetTools/2.0.0/GreetTools.psd1") -Value '@{ RootModule = "GreetTools.psm1"; ModuleVersion = "2.0.0"; FunctionsToExport = @("Get-Greeting") }'
Import-Module "GreetTools"
Get-GreetingRequiredVersion loads one exact older version
RequiredVersion names one exact version. The older version answers the call.
$env:PSModulePath = $PSScriptRoot + ":" + $env:PSModulePath
$null = New-Item -ItemType Directory -Force -Path (Join-Path $PSScriptRoot "GreetTools/1.0.0")
$null = New-Item -ItemType Directory -Force -Path (Join-Path $PSScriptRoot "GreetTools/2.0.0")
Set-Content -Path (Join-Path $PSScriptRoot "GreetTools/1.0.0/GreetTools.psm1") -Value 'function Get-Greeting { "Hello v1" }'
Set-Content -Path (Join-Path $PSScriptRoot "GreetTools/1.0.0/GreetTools.psd1") -Value '@{ RootModule = "GreetTools.psm1"; ModuleVersion = "1.0.0"; FunctionsToExport = @("Get-Greeting") }'
Set-Content -Path (Join-Path $PSScriptRoot "GreetTools/2.0.0/GreetTools.psm1") -Value 'function Get-Greeting { "Hello v2" }'
Set-Content -Path (Join-Path $PSScriptRoot "GreetTools/2.0.0/GreetTools.psd1") -Value '@{ RootModule = "GreetTools.psm1"; ModuleVersion = "2.0.0"; FunctionsToExport = @("Get-Greeting") }'
Import-Module "GreetTools" -RequiredVersion "1.0.0"
Get-GreetingExample
$env:PSModulePath = $PSScriptRoot + ":" + $env:PSModulePath
$null = New-Item -ItemType Directory -Force -Path (Join-Path $PSScriptRoot "GreetTools/1.0.0")
$null = New-Item -ItemType Directory -Force -Path (Join-Path $PSScriptRoot "GreetTools/2.0.0")
$null = New-Item -ItemType Directory -Force -Path (Join-Path $PSScriptRoot "BareTools/1.0.0")
Set-Content -Path (Join-Path $PSScriptRoot "GreetTools/1.0.0/GreetTools.psm1") -Value 'function Get-Greeting { "Hello v1" }'
Set-Content -Path (Join-Path $PSScriptRoot "GreetTools/1.0.0/GreetTools.psd1") -Value '@{ RootModule = "GreetTools.psm1"; ModuleVersion = "1.0.0"; FunctionsToExport = @("Get-Greeting") }'
Set-Content -Path (Join-Path $PSScriptRoot "GreetTools/2.0.0/GreetTools.psm1") -Value 'function Get-Greeting { "Hello v2" }'
Set-Content -Path (Join-Path $PSScriptRoot "GreetTools/2.0.0/GreetTools.psd1") -Value '@{ RootModule = "GreetTools.psm1"; ModuleVersion = "2.0.0"; FunctionsToExport = @("Get-Greeting") }'
Set-Content -Path (Join-Path $PSScriptRoot "BareTools/1.0.0/BareTools.psm1") -Value 'function Get-Bare { "bare" }'
(Get-Module -ListAvailable -Name "GreetTools" | Sort-Object Version | ForEach-Object { $_.Version.ToString() }) -join ", "
(Get-Module -ListAvailable -Name "BareTools").CountKey points
- Version folder: a folder named with a version number that holds one version of a module.
- Use Get-Module -ListAvailable to list the versions found for a module name.
- Default load: importing a module by name alone loads its newest version.
- Use Import-Module -RequiredVersion to load one exact version instead.
- A version folder needs a .psd1 file, or Get-Module -ListAvailable skips that version.
In this example, two versions of GreetTools are built, plus a folder with only a code file. The version list shows both real versions, and the bare folder counts as zero.
Note
an old version stays usable after a new version arrives, because each version keeps its own folder.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
A module has versions 1.0.0 and 2.0.0 in version folders. You import it by name alone, with no version flag. Which version loads?