PowerShell function to find information about module updates

I decided to update the one liner from my blog article last week and take it a step further by turning it into a reusable tool that displays information about module updates that are available regardless of where they were installed from.

#Requires -Version 3.0 -Modules PowerShellGet
function Find-MrModuleUpdate {

<#
.SYNOPSIS
    Finds updates for installed modules from an online gallery that matches the specified criteria.

.DESCRIPTION
    Find-MrModuleUpdate is a PowerShell advanced function that finds updates from an online gallery for locally installed modules
    regardless of whether or not they were originally installed from an online gallery or from the same online gallery where the
    update is found.

.PARAMETER Name
    Specifies the names of one or more modules to search for.

.PARAMETER Scope
    Specifies the search scope of the installed modules. The acceptable values for this parameter are: AllUsers and CurrentUser.

.EXAMPLE
     Find-MrModuleUpdate

.EXAMPLE
     Find-MrModuleUpdate -Name PSScriptAnalyzer, PSVersion

.EXAMPLE
     Find-MrModuleUpdate -Scope CurrentUser

.EXAMPLE
     Find-MrModuleUpdate -Name PSScriptAnalyzer, PSVersion -Scope CurrentUser

.INPUTS
    None

.OUTPUTS
    Mr.ModuleUpdate

.NOTES
    Author:  Mike F Robbins
    Website: http://mikefrobbins.com
    Twitter: @mikefrobbins
#>

    [CmdletBinding()]
    [OutputType('Mr.ModuleUpdate')]
    param (
        [ValidateNotNullOrEmpty()]
        [string[]]$Name,

        [ValidateSet('AllUsers', 'CurrentUser')]
        [string]$Scope
    )

    $AllUsersPath = "$env:ProgramFiles\WindowsPowerShell\Modules\*"
    $CurrentUserPath = "$env:USERPROFILE\Documents\WindowsPowerShell\Modules\*"

    switch ($Scope) {
        'AllUsers' {$Path = $AllUsersPath; break}
        'CurrentUser' {$Path = $CurrentUserPath; break}
        Default {$Path = $AllUsersPath, $CurrentUserPath}
    }

    $Params = @{
        ListAvailable = $true
    }

    if ($PSBoundParameters.Name) {
        $Params.Name = $Name
    }

    $Modules = Get-Module @Params

    foreach ($p in $Path) {

        $ScopedModules = $Modules |
        Where-Object ModuleBase -like $p |
        Sort-Object -Property Name, Version -Descending |
        Get-Unique

        foreach ($Module in $ScopedModules) {

            Remove-Variable -Name InstallInfo -ErrorAction SilentlyContinue
            $Repo = Find-Module -Name $Module.Name -ErrorAction SilentlyContinue

            if ($Repo) {
                $Diff = Compare-Object -ReferenceObject $Module -DifferenceObject $Repo -Property Name, Version |
                        Where-Object SideIndicator -eq '=>'

                if ($Diff) {
                    $PSGetModuleInfoPath = "$($Module.ModuleBase)\PSGetModuleInfo.xml"

                    if (Test-Path -Path $PSGetModuleInfoPath) {
                        $InstallInfo = Import-Clixml -Path $PSGetModuleInfoPath
                    }

                    switch ($Module.ModuleBase) {
                        {$_ -like $AllUsersPath} {$Location = 'AllUsers'; break}
                        {$_ -like $CurrentUserPath} {$Location = 'CurrentUser'; break}
                        Default {Throw 'An unexpected error has occured.'}
                    }

                    [pscustomobject]@{
                        Name = $Module.Name
                        InstalledVersion = $Module.Version
                        InstalledLocation = $Location
                        Repository = $Repo.Repository
                        RepositoryVersion = $Diff.Version
                        InstalledFromRepository = $InstallInfo.Repository
                        PSTypeName = 'Mr.ModuleUpdate'
                    }

                }

            }

        }

    }

}
Find-MrModuleUpdate

find-mrmoduleupdate1a.jpg

As shown in the previous results, the function lists modules that have updates available regardless of where they were originally installed from. It also lists the installed version and location along with the repository where the updated version resides and the updated version number. It also lists where the module was originally installed from by reading the contents of the hidden XML file in the module directory if it was installed using PowerShellGet.

You can narrow your search down to specific modules:

Find-MrModuleUpdate -Name PSScriptAnalyzer, PSVersion

find-mrmoduleupdate2a.jpg

To a specific scope:

Find-MrModuleUpdate -Scope CurrentUser

find-mrmoduleupdate3a.jpg

Use a combination of specific modules and scope to narrow the search down even further:

Find-MrModuleUpdate -Name PSScriptAnalyzer, PSVersion -Scope AllUsers

find-mrmoduleupdate4a.jpg

The function also uses custom formatting to allow for table output with more than four columns by default without having to pipe to Format-Table. The relevant portion of the PS1XML file used for the custom formatting is shown in the code example below:

<View>
    <Name>Mr.ModuleUpdate</Name>
    <ViewSelectedBy>
        <TypeName>Mr.ModuleUpdate</TypeName>
    </ViewSelectedBy>
    <TableControl>
        <TableHeaders>
                <TableColumnHeader>
                <Width>30</Width>
            </TableColumnHeader>
            <TableColumnHeader>
                <Width>16</Width>
            </TableColumnHeader>
            <TableColumnHeader>
                <Width>17</Width>
            </TableColumnHeader>
            <TableColumnHeader>
                <Width>10</Width>
            </TableColumnHeader>
            <TableColumnHeader>
                <Width>17</Width>
            </TableColumnHeader>
            <TableColumnHeader>
                <Width>23</Width>
            </TableColumnHeader>
        </TableHeaders>
        <TableRowEntries>
            <TableRowEntry>
                <TableColumnItems>
                    <TableColumnItem>
                        <PropertyName>Name</PropertyName>
                    </TableColumnItem>
                    <TableColumnItem>
                        <PropertyName>InstalledVersion</PropertyName>
                    </TableColumnItem>
                    <TableColumnItem>
                        <PropertyName>InstalledLocation</PropertyName>
                    </TableColumnItem>
                    <TableColumnItem>
                        <PropertyName>Repository</PropertyName>
                    </TableColumnItem>
                    <TableColumnItem>
                        <PropertyName>RepositoryVersion</PropertyName>
                    </TableColumnItem>
                    <TableColumnItem>
                        <PropertyName>InstalledFromRepository</PropertyName>
                    </TableColumnItem>
                </TableColumnItems>
            </TableRowEntry>
            </TableRowEntries>
    </TableControl>
</View>

The Find-MrModuleUpdate function shown in this blog article is part of my MrToolkit module which can be downloaded from my PowerShell repository on GitHub.

ยต