Issue:

Updating your PowerShell modules is a common task and one you should do regularly when utilising any cloud based modules.
But how to maintain current versions without bloat or getting versions confused?

Solution:

As always read and understand the code before running.
Learn and improve is the goal of this blog.



#requires -version 4.0
#requires –runasadministrator
function Uninstall-xOldPSModule {
    <#
    .Synopsis
       Removes older versions of PowerShell Modules.

    .DESCRIPTION
       Removes older versions of PowerShell Modules.
       We enforce administrator mode for a clean uninstall.
       No parameters at this stage. Potential to include a wildcard or search function.
       Supports should process so can use -WhatIf and -Confirm:$false to blast through,
       otherwise you will be asked to uninstall each version for safety.
       
    .EXAMPLE
       Uninstall-xOldPSModule 

    .EXAMPLE
       Uninstall-xOldPSModule -Confirm:$false -Verbose
       
    .NOTES
       	AUTHOR   : Steve Rackham
    	BLOG     : https://siliconwolf.net
    	GIT      : https://github.com/siliconWOLF
    	TWITTER  : https://twitter.com/siliconW0LF
    	LINKEDIN : https://nz.linkedin.com/in/steverackham

    #>
    
    [cmdletbinding(
        SupportsShouldProcess,
        ConfirmImpact = 'High'
    )]
    param () # END PARAMS

    # GET --------------------------------------------------------------------------
    # Capture the installed modules.
    try {
        $Modules = Get-InstalledModule -ErrorAction Stop
        $OffSet = 0 - ($Modules.Name | Measure-Object -Maximum -Property Length).Maximum
        Write-Verbose ("{0,$OffSet} : {1}" -f "[ PSMODULES ]", "CLEAN UP [ $($Modules.Count) ]: READY..." )

    }
    catch {
        Write-Warning ("{0,$OffSet} : {1}" -f "[ MODULES ]", "FAILURE! $($Error[0].Exception.Message)")
        Return

    } # END-TRY/CATCH

    # SET --------------------------------------------------------------------------
    
    $i = 0

    foreach ($Module in $Modules) {
        Write-Verbose ("{0,$OffSet} : {1}" -f "[ $($Module.Name) ]", "Processing... ")

        # Capture latest version.
        $LatestVersion = Get-InstalledModule $Module.Name

        # Capture all versions for comparison.
        $ModuleVersions = Get-InstalledModule $Module.Name -AllVersions

        # Check versions and if more than one remove the older version.
        if ($ModuleVersions.Count -gt 1) {
            if ($PSCmdlet.ShouldProcess(
                    "[ $($Module.Name) ]Uninstalling : $($ModuleVersion.Version)  ",
                    "[ $($Module.Name) ] Confirm Uninstall : $($ModuleVersion.Version) ",
                    'IMPORTANT!')) {
                foreach ($ModuleVersion in $ModuleVersions) {

                    if ($ModuleVersion.Version -ne $LatestVersion.Version) {
                        $ModuleVersion | Uninstall-Module -Force -Confirm:$false
                        Write-Verbose ("{0,$OffSet} : {1}" -f "[ $($Module.Name) ]", "Uninstalled Version: $($ModuleVersion.Version))" )

                    } # END if ($ModuleVersion.Version -ne $LatestVersion.Version)
                } # END if $PSCmdlet.ShouldProcess
            } # END FOREACH ($version in $modVersions)
        } # END if ($ModuleVersions.Count -gt 1)


        # STATUS OUTPUT: -----------------------------------------------------------
        $i++

        $Activity = "Processing PowerShell Module Versions..."
        $CurrentOperation = "Processing Module: $($Module.Name)"
        $PercentComplete = (($i / $Modules.Count) * 100)
        $Status = "PROCESSING: $i of $($Modules.Count)"
        Write-Progress -Activity $Activity -CurrentOperation $CurrentOperation -PercentComplete $PercentComplete -Status $Status

    } # END FOREACH ($mod in $modules)

    Write-Verbose ("{0,$OffSet} : {1}" -f "[ PSMODULES ]", "CLEAN UP [ $($Modules.Count) ]: COMPLETED." )

} # END FUNCTION Remove-xOldPSModule ###############################################