PSQualityTools.psm1

#Region '.\public\Show-ModuleUpdateStatus.ps1' 0
function Show-ModuleUpdateStatus {
    <#
        .SYNOPSIS
        Show the update status of installed module in the current PowerShell session.
 
        .DESCRIPTION
        Show the version of all installed modules, optionally only show ones that require update.
 
        NOTE: Owing to the nature of checks against remote repositories, the command may take quite a while to run!
 
        .PARAMETER Name
        Name of the module to show the version information of, or a wildcard to show all.
 
        .PARAMETER RequiresUpdate
        Switch to only show modules that require update.
 
        .EXAMPLE
        Show-ModuleUpdateStatus
 
        .EXAMPLE
        Show-ModuleUpdateStatus -Name 'ModuleName'
 
        .EXAMPLE
        Show-ModuleUpdateStatus -RequiresUpdate
 
        .EXAMPLE
        $modules = Show-ModuleUpdateStatus -RequiresUpdate
 
    #>

    [CmdletBinding()]
    [OutputType([System.Object])]
    param (

        [Parameter(ValueFromPipeline = $true)]
        [ValidateNotNullorEmpty()]
        [string[]]$Name = "*",
        [switch]$RequiresUpdate

    )

    # TODO: Check that any marked upgrade isn't already installed, and then mark that update with a * to indicate it's already installed
    # TODO: Add -Quiet flag to produce no output at all (useful for pipelines)
    # TODO: Check that the output can be piped to Update-Module
    # TODO: Handle a remote repository returning multiple versions of a module, this affects the Update check (it flags as true when it shouldn't)
    # TODO: Add a flag to ignore Az* and AzureRm* modules and submodules (-SkipAzure), or only the Azure modules (-OnlyAzure), or add ability to filter in or out modules?
    # TODO: Look a the output on narrow screens and see what can be done to prevent the dreaded ...
    # TODO: Check on reports that first run doesn't produce output table
    # QUERY: Add 24hr local cache of remote results?
    # TODO: Add flag to only query 'CurrentUser' installed modules rather than all modules (-UserModulesOnly)

    begin {

        Write-Debug "Starting Show-ModuleUpdateStatus"
        Write-Information "Working ..." -InformationAction Continue

        Set-StrictMode -Version Latest
        $ErrorActionPreference = 'Stop'

        $Repositories = Get-PSRepository

        try {
            $localModules = Get-Module -Name $name -ListAvailable -ErrorAction Stop | Sort-Object -Property Name
        }
        catch {
            throw $_
        }

    }

    process {

        if ($localModules -is [System.Array]) {

            $moduleOutput = New-Object -TypeName "System.Collections.ArrayList"

            foreach ($moduleToCheck in $localModules) {

                Write-Information " Processing local module: $($moduleToCheck.Name) ($($moduleToCheck.Version)) ..." -InformationAction Continue

                try {

                    $moduleVersionTable = New-Object -TypeName "System.Collections.ArrayList"

                    foreach ($repository in $Repositories) {

                        Write-Verbose "Looking at repository '$($repository.Name)' for $($moduleToCheck.Name)"
                        $moduleInfo = Find-Module -Name $moduleToCheck.Name -Repository $repository.Name -ErrorAction SilentlyContinue

                        if ($null -eq $moduleInfo) {
                            $moduleInfo = @{
                                Repository = $repository.Name
                                Version    = "n/a"
                            }
                        }
                        else {
                            $moduleInfo = @{
                                Repository = $repository.Name
                                Version    = $moduleInfo.Version
                            }
                        }

                        $null = $moduleVersionTable.Add($moduleInfo)

                    }

                    $updateAvailable = $false
                    foreach ($versionsToCheck in $moduleVersionTable) {

                        if ($versionsToCheck.Version -ne 'n/a') {

                            foreach ($version in $versionsToCheck) {
                                try {
                                    if ([System.Version]$version.Version -gt [System.Version]$moduleToCheck.Version ) {
                                        $updateAvailable = $true
                                    }
                                }
                                catch {
                                    Write-Warning -Message "Error parsing version number. $($Error[0])"
                                }
                            }

                        }

                    }

                    $moduleData = [PsCustomObject]@{
                        PSTypeName = "moduleInfo"
                        Name       = $moduleToCheck.Name
                    }

                    $moduleData | Add-Member -NotePropertyName "Local" -NotePropertyValue $moduleToCheck.Version
                    foreach ($version in $moduleVersionTable) {
                        $moduleData | Add-Member -NotePropertyName $version.Repository -NotePropertyValue $version.Version
                    }
                    $moduleData | Add-Member -NotePropertyName "Update" -NotePropertyValue $updateAvailable

                    $null = $moduleOutput.Add($moduleData)

                }
                catch {
                    Write-Error $_
                }

            }

            if ($PSBoundParameters.ContainsKey('RequiresUpdate')) {

                $output = $moduleOutput | Where-Object Update -EQ $true

            }
            else {

                $output = $moduleOutput

            }

            if ($null -ne $output) {

                $output | Format-Table -AutoSize

            }
            else {

                Write-Information '' -InformationAction Continue
                Write-Information 'No module(s) require update.' -InformationAction Continue
                Write-Information '' -InformationAction Continue

            }

        }
        else {
            Write-Warning "No modules found."
        }
    }

    end {

        Write-Debug "Leaving Show-ModuleUpdateStatus"

    }

}

#EndRegion '.\public\Show-ModuleUpdateStatus.ps1' 184