Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Removing a PowerShell module using its version number

Tags:

powershell

Is there an easy way to pass version as a parameter to Get-Module?

I have two different versions of Azure PowerShell installed:

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:

Get-Module -name azure -version 1.0.2 | remove-module
like image 672
Yar Avatar asked Mar 19 '16 02:03

Yar


1 Answers

Please see: get-help Remove-Module -full

-FullyQualifiedName [<String[]>]
        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:

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.

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.

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:

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

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

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.

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...

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:

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!

like image 104
Kory Gill Avatar answered Oct 05 '22 21:10

Kory Gill