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.

EDIT:

Oh dear. Updated version with some improved logic and verbose logging.



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

    .DESCRIPTION
       Removes older versions of PowerShell Modules.
       Enforce administrator mode for a clean uninstall.

    .EXAMPLE
       Remove-LegacyModuleVersions

    .EXAMPLE
       Remove-LegacyModuleVersions -Confirm:$false -Verbose

    .NOTES
        AUTHOR   : Steve Rackham
        BLOG     : https://siliconwolf.net
    	GIT      : https://github.com/siliconWOLF
        LINKEDIN : https://nz.linkedin.com/in/steverackham
        CREATED  : 27.06.2018
        UPDATED  : 31.01.2020

    #>

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

    begin {
        # DEFINITIONS: --------------------------------------------------------
        [int]$Counter = 0
        [int]$CounterTotal = 0
        [int]$UninstalledModules = 0
        # $StringDelimiter = (Get-Culture).TextInfo.ListSeparator

        # Status Flag:
        $Status = @{
            Success     = "[ SUCCESS ]"
            Error       = "[ ERROR   ]"
            Warning     = "[ WARNING ]"
            Information = "[ INFO    ]"
            End         = "[ END     ]"

        } # END $Status

        # GET -----------------------------------------------------------------
        # Capture the installed modules.
        try {
            $Modules = Get-InstalledModule -ErrorAction Stop
            $OffSet = 0 - ($Modules.Name | Measure-Object -Maximum -Property Length).Maximum
            $CounterTotal = $Modules.Count

            Write-Verbose ("{0} , {1} , {2, $Offset} , {3}" -f "$($Status.Information)", "[ $(Get-Date -Format HH:mm:ss.fff) ]", "TARGET: [ $env:COMPUTERNAME ]", "ACTION: Capture All Modules [ $CounterTotal ]."  )
            Write-Verbose ("{0} , {1} , {2, $Offset} , {3}" -f "$($Status.Information)", "[ $(Get-Date -Format HH:mm:ss.fff) ]", "TARGET: [ $env:COMPUTERNAME ]", "ACTION: Processing Modules. This may take some time..."  )

        }
        catch {
            Write-Warning ("{0} , {1} , {2, $Offset} , {3}" -f "$($Status.Error)", "[ $(Get-Date -Format HH:mm:ss.fff) ]", "TARGET: [ $env:COMPUTERNAME ]", "FAILURE! $($Error[0].Exception.Message)"  )

            Return

        } # END-TRY/CATCH

    }

    process {
        # SET -----------------------------------------------------------------
        foreach ($Module in $Modules) {

            # 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) {

                foreach ($ModuleVersion in $ModuleVersions) {
                    if ($PSCmdlet.ShouldProcess(
                            "[ $($Module.Name) ] Uninstalling old version [ $($ModuleVersion.Version) ]",
                            "[ $($Module.Name) ] Old version detected. Uninstall [ $($ModuleVersion.Version) ]? ",
                            'IMPORTANT!')) {
                        if ($ModuleVersion.Version -ne $LatestVersion.Version) {
                            try {
                                $ModuleVersion | Uninstall-Module -Force -Confirm:$false -ErrorAction Stop
                                $UninstalledModules++

                                Write-Verbose ("{0} , {1} , {2, $Offset} , {3}" -f "$($Status.Success)", "[ $(Get-Date -Format HH:mm:ss.fff) ]", "TARGET: [ $($Module.Name) ]", "ACTION: Uninstalled Version [ $($ModuleVersion.Version) ]."  )

                            }
                            catch {
                                Write-Warning ("{0} , {1} , {2, $Offset} , {3}" -f "$($Status.Error)", "[ $(Get-Date -Format HH:mm:ss.fff) ]", "TARGET: [ $($Module.Name) ]", "FAILURE! $($Error[0].Exception.Message)"  )

                            }

                        } # END if ($ModuleVersion.Version -ne $LatestVersion.Version)

                    } # END if $PSCmdlet.ShouldProcess

                } # END FOREACH ($version in $modVersions)

            } # END if ($ModuleVersions.Count -gt 1)

            # STATUS OUTPUT: --------------------------------------------------
            $Counter++

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

        } # END FOREACH ($mod in $modules)

        Write-Output ("{0} , {1} , {2, $Offset} , {3}" -f "$($Status.End)", "[ $(Get-Date -Format HH:mm:ss.fff) ]", "TARGET: [ $env:COMPUTERNAME ]", "ACTION: Uninstalled Old Modules [ $UninstalledModules ]."  )

    } # End process block.

} # END FUNCTION Remove-LegacyModuleVersions ##########################################