PowerShell modules versioning

Modules are the way to package logic in PowerShell. Simple. Modules are shared, published to the gallery, developed and naturually evolve. Which means that they can have breaking changes. You don’t want them in production, do you?

To avoid this possibility, you should be able to explicitly specify version of used module. How to do that?

ModuleSpecification

When you reference a module somehow (i.e. Get-Module, Import-Module, Import-DscResouce -ModuleName, Get-DscResource -Module) you can provide FullyQuilifiedName or ModuleSpecification.

It can be one of two things:

  1. [string], i.e. "xExchange" (xExchange)
  2. [hashtable] with module name and version.
    1. @{ModuleName = "xExchange"; ModuleVersion = "1.1.0.0"}
    2. @{ModuleName = "xExchange"; RequiredVersion = "1.1.0.0"}

RequiredVersion vs ModuleVersion

Why do we have two of them and what’s the difference? I found some info in a release notes

Windows PowerShell 5.0 implements support for multiple versions of a single Windows PowerShell module in the same folder in $PSModulePath. A RequiredVersion property has been added to the ModuleSpecification class to help you get the desired version of a module; this property is mutually-exclusive with the ModuleVersion property. RequiredVersion is now supported as part of the value of the FullyQualifiedName parameter of the Get-Module, Import-Module, and Remove-Module cmdlets.

It doesn’t explain the difference, but we can find it out from an experement.

Experiment

Let’s get both modules from PowerShellGallery

Find-Module xExchange -AllVersions | ? {$_.Version -eq '1.1.0.0' -or $_.Version -eq '1.2.0.0'} | Install-Module

Now, let try all mentioned variations

PS> Get-Module -ListAvailable -FullyQualifiedName 'xExchange'


    Directory: C:\Program Files\WindowsPowerShell\Modules


ModuleType Version    Name                                ExportedCommands                              
---------- -------    ----                                ----------------                              
Manifest   1.2.0.0    xExchange                                                                         
Manifest   1.1.0.0    xExchange 

PS> Get-Module -ListAvailable -FullyQualifiedName @{ModuleName = 'xExchange'; ModuleVersion = "1.1.0.0"}


    Directory: C:\Program Files\WindowsPowerShell\Modules


ModuleType Version    Name                                ExportedCommands                              
---------- -------    ----                                ----------------                              
Manifest   1.2.0.0    xExchange                                                                         
Manifest   1.1.0.0    xExchange                                                                         



PS> Get-Module -ListAvailable -FullyQualifiedName @{ModuleName = 'xExchange'; RequiredVersion = "1.1.0.0"}


    Directory: C:\Program Files\WindowsPowerShell\Modules


ModuleType Version    Name                                ExportedCommands                              
---------- -------    ----                                ----------------                              
Manifest   1.1.0.0    xExchange      

The output is different: ModuleVersion query returns both 1.1.0.0 and 1.2.0.0. Let’s try to query version ‘1.2.0.0’

PS> Get-Module -ListAvailable -FullyQualifiedName @{ModuleName = 'xExchange'; ModuleVersion = "1.2.0.0"}


    Directory: C:\Program Files\WindowsPowerShell\Modules


ModuleType Version    Name                                ExportedCommands                              
---------- -------    ----                                ----------------                              
Manifest   1.2.0.0    xExchange                                                                         


PS> Get-Module -ListAvailable -FullyQualifiedName @{ModuleName = 'xExchange'; RequiredVersion = "1.2.0.0"}


    Directory: C:\Program Files\WindowsPowerShell\Modules


ModuleType Version    Name                                ExportedCommands                              
---------- -------    ----                                ----------------                              
Manifest   1.2.0.0    xExchange      

Now queries return the same results.

Conclusion

RequiredVersion really sticks to a particular version.

ModuleVersion returns all versions that are equal or higher.