Question:
Is there an easy way to pass version as a parameter to Get-Module
?
I have two different versions of Azure PowerShell installed:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
C:\WINDOWS\system32> get-module -name azure -listavailable Directory: C:\Program Files\WindowsPowerShell\Modules\... ModuleType Version Name ---------- ------- ---- Manifest 1.0.4 Azure Directory: C:\Program Files (x86)\Microsoft SDKs\Azure\... ModuleType Version Name ---------- ------- ---- Manifest 1.0.2 Azure |
And I wish to remove one of them using a command like:
1 2 |
Get-Module -name azure -version 1.0.2 | remove-module |
Answer:
Please see: get-help Remove-Module -full
1 2 3 4 5 6 7 8 9 10 11 12 |
-FullyQualifiedName [ Removes modules with names that are specified in the form of ModuleSpecification objects (described by the Remarks section of Module Specification Constructor (Hashtable) on MSDN). For example, the FullyQualifiedName parameter accepts a module name that is specified in the format @{ModuleName = "modulename"; ModuleVersion = "version_number"} or @{ModuleName = "modulename"; ModuleVersion = "version_number"; Guid = "GUID"}. ModuleName and ModuleVersion are required, but Guid is optional. You cannot specify the FullyQualifiedName parameter in the same command as a Name parameter; the two parameters are mutually exclusive. |
Notice:
FullyQualifiedName parameter accepts a module name that is specified in the format @{ModuleName = “modulename”; ModuleVersion = “version_number”}
Based on that, the following should be what you are after:
1 2 |
Remove-Module -FullyQualifiedName @{ModuleName = "Azure"; ModuleVersion = "1.0.2"} |
Improved Answer (edit)
Did more investigation on this, and there are some quirks when removing using ModuleVersion
(which can be a string
or a [version]
).
If you specify ModuleVersion
, Remove-Module
will remove all matching modules with that version and greater.
To get an explicit match, you must also pass the guid
.
1 2 |
Get-Module 'Azure' | where {([string]($_.Version)).StartsWith('1.0.2')} | Remove-Module |
Since that is a lot to type, I suggest adding a function to your profile to make this easier.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
function Remove-ModuleWithVersion { param ( [Parameter(Mandatory=$true)] [string] $Module, [Parameter(Mandatory=$true)] [string] $VersionToMatch ) Get-Module $Module | where {([string]($_.Version)).StartsWith($VersionToMatch)} | Remove-Module -Verbose } |
and call like:
1 2 |
Remove-ModuleWithVersion 'Azure' '1.0.2' |
Testing and analysis
I might as well share how I tested this to arrive at my conclusion. I will leave some details to the reader for self-investigation…
Create two modules, and export a function from each, using different function names to make testing easier.
D:\test\modtest\v1\ModTest.psd1 with version 1.1.0.1
D:\test\modtest\v1\ModTest.psm1
1 2 3 4 5 6 7 |
function Show-Hello1 { "Hello v1.1" } Export-ModuleMember -Function Show-Hello1 |
D:\test\modtest\v2\ModTest.psd1 with version 1.2.0.2
D:\test\modtest\v2\ModTest.psm1
1 2 3 4 5 6 7 |
function Show-Hello2 { "Hello v1.2" } Export-ModuleMember -Function Show-Hello2 |
Create a function to load the modules, call exported functions, show modules before, remove a module using the parameters specified, show modules after.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
function Invoke-LoadAndRemove($minor, $useString, $guid = $null) { "`n------`n$($minor), $($useString), '$($guid)'" "`nimport modules..." ipmo D:\test\modtest\v1\ModTest.psd1 -Force #-Verbose ipmo D:\test\modtest\v2\ModTest.psd1 -Force #-Verbose "call exported functions..." Show-Hello1 Show-Hello2 "modules before..." Get-Module *mod* if ($useString) { $ver = "1.$minor.0.$minor" } else { $ver = [version]::new(1, $minor, 0, $minor) } "`nremoving version: $ver, -> $($ver.GetType()), useGuid=$($useGuid)" if ($useGuid) { Remove-Module -FullyQualifiedName @{ModuleName = "ModTest"; ModuleVersion = $ver} -Verbose } else { Remove-Module -FullyQualifiedName @{ModuleName = "ModTest"; ModuleVersion = $ver; Guid = $guid} -Verbose } "modules after..." Get-Module *mod* "done." } |
call various ways to demonstrate how Remove-Module works…
1 2 3 4 5 6 7 |
Invoke-LoadAndRemove 2 $true Invoke-LoadAndRemove 1 $true Invoke-LoadAndRemove 2 $false Invoke-LoadAndRemove 1 $false Invoke-LoadAndRemove 1 $false 'b213dea3-4ae3-4fde-a9c6-0ac4a8d1890c' Invoke-LoadAndRemove 2 $true '02fdc44a-2c32-4f7b-8573-b1317b03269a' |
This is the part, where I leave it to the reader to analyze the output further to verify the conclusions of this article.
That said, this was what I noticed that caused me to investigate further:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
modules before... Script 1.2.0.2 ModTest Show-Hello2 Script 1.1.0.1 ModTest Show-Hello1 removing version: 1.2.0.2, -> string, useGuid= VERBOSE: Performing the operation "Remove-Module" on target "ModTest (Path: 'D:\test\modtest\v2\ModTest.psm1')". VERBOSE: Removing the imported "Show-Hello2" function. modules after... Script 1.1.0.1 ModTest Show-Hello1 done. ------ modules before... Script 1.2.0.2 ModTest Show-Hello2 Script 1.1.0.1 ModTest Show-Hello1 removing version: 1.1.0.1, -> string, useGuid= VERBOSE: Performing the operation "Remove-Module" on target "ModTest (Path: 'D:\test\modtest\v2\ModTest.psm1')". VERBOSE: Performing the operation "Remove-Module" on target "ModTest (Path: 'D:\test\modtest\v1\ModTest.psm1')". VERBOSE: Removing the imported "Show-Hello2" function. VERBOSE: Removing the imported "Show-Hello1" function. modules after... done. |
Notice that when removing 1.2.0.2, it works as expected. When removing 1.1.0.1, both 1.1.0.1 and 1.2.0.2 are removed!