Skip to content

Instantly share code, notes, and snippets.

@jdhitsolutions
Last active July 31, 2023 21:33
Show Gist options
  • Save jdhitsolutions/7217ed9293f18e8d454e3f88ecb38b67 to your computer and use it in GitHub Desktop.
Save jdhitsolutions/7217ed9293f18e8d454e3f88ecb38b67 to your computer and use it in GitHub Desktop.
Use this command to compare module versions between what is installed against an online repository like the PSGallery. Results will be automatically sorted by module name.
#requires -version 5.0
# https://gist.github.com/jdhitsolutions/7217ed9293f18e8d454e3f88ecb38b67
Function Compare-Module {
<#
.Synopsis
Compare module versions.
.Description
Use this command to compare module versions between what is installed against an online repository like the PSGallery. Results will be automatically sorted by module name.
.Parameter Name
The name of a module to check. Wildcards are permitted.
.Notes
Version: 1.2
Learn more about PowerShell:
http://jdhitsolutions.com/blog/essential-powershell-resources/
.Example
PS C:\> Compare-Module | Where-objject {$_.UpdateNeeded}
Name : Azure
OnlineVersion : 1.5.1
InstalledVersion : 1.0.4
PublishedDate : 6/27/2016 6:50:11 PM
UpdateNeeded : True
Name : Azure.Storage
OnlineVersion : 1.1.4
InstalledVersion : 1.0.4
PublishedDate : 6/27/2016 6:48:07 PM
UpdateNeeded : True
Name : AzureRM
OnlineVersion : 1.5.1
InstalledVersion : 1.2.0
PublishedDate : 6/27/2016 7:08:50 PM
UpdateNeeded : True
...
.Example
PS C:\> Compare-Module | Where UpdateNeeded | Out-Gridview -title "Select modules to update" -outputMode multiple | Foreach { Update-Module $_.name }
Compare modules and send results to Out-Gridview. Use Out-Gridview as an object picker to decide what modules to update.
.Example
PS C:\> compare-module -name xWindows* | format-table
Name OnlineVersion InstalledVersion PublishedDate UpdateNeeded
---- ------------- ---------------- ------------- ------------
xWindowsEventForwarding 1.0.0.0 1.0.0.0 6/17/2015 9:46:32 PM False
xWindowsRestore 1.0.0 1.0.0 12/18/2014 4:22:42 AM False
xWindowsUpdate 2.5.0.0 2.3.0.0 5/18/2016 11:02:47 PM True
Compare all modules that start with xWindows and display results in a table format.
.Example
PS C:\> get-dscresource cAD* | Select moduleName -Unique | compare-module
Name : cActiveDirectory
OnlineVersion : 1.1.1
InstalledVersion : 1.0.1
PublishedDate : 6/23/2015 9:24:55 PM
UpdateNeeded : True
Get all DSC Resources that start with cAD and select the corresponding module name. Since the module name will be listed for every resource, get a unique list and pipe that to Compare-Module.
.Link
Find-Module
.Link
Get-Module
.Link
Update-Module
.Inputs
[string]
.Outputs
[PSCustomObject]
#>
[cmdletbinding()]
[alias("cmo")]
Param
(
[Parameter(
Position = 0,
ValueFromPipelineByPropertyName
)]
[ValidateNotNullorEmpty()]
[Alias("modulename")]
[string]$Name,
[ValidateNotNullorEmpty()]
[string]$Gallery = "PSGallery"
)
Begin {
Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)"
$progParam = @{
Activity = $MyInvocation.MyCommand
Status = "Getting installed modules"
CurrentOperation = "Get-Module -ListAvailable"
PercentComplete = 25
}
Write-Progress @progParam
} #begin
Process {
$gmoParams = @{
ListAvailable = $True
}
if ($Name) {
$gmoParams.Add("Name", $Name)
}
$installed = Get-Module @gmoParams
if ($installed) {
$progParam.Status = "Getting online modules"
$progParam.CurrentOperation = "Find-Module -repository $Gallery"
$progParam.PercentComplete = 50
Write-Progress @progParam
$fmoParams = @{
Repository = $Gallery
ErrorAction = "Stop"
}
if ($Name) {
$fmoParams.Add("Name", $Name)
}
Try {
$online = Find-Module @fmoParams
}
Catch {
Write-Warning "Failed to find online module(s). $($_.Exception.message)"
}
$progParam.status = "Comparing $($installed.count) installed modules to $($online.count) online modules."
$progParam.percentComplete = 80
Write-Progress @progParam
$data = $online | Where-Object {$installed.name -contains $_.name} |
Select-Object -property Name,
@{Name = "OnlineVersion"; Expression = {$_.Version}},
@{Name = "InstalledVersion"; Expression = {
#save the name from the incoming online object
$name = $_.Name
$installed.Where( {$_.name -eq $name}).Version -join ","}
},
PublishedDate,
@{Name = "UpdateNeeded"; Expression = {
$name = $_.Name
#there could me multiple versions installed
$installedVersions = $installed.Where( {$_.name -eq $name}).Version | Sort-Object
foreach ($item in $installedVersions) {
If ([version]$_.Version -gt [version]$item) {
$result = $True
}
else {
$result = $False
}
}
$result
}
} | Sort-Object -Property Name
$progParam.PercentComplete = 100
$progParam.Completed = $True
Write-Progress @progparam
#write the results to the pipeline
$data
}
else {
Write-Warning "No local module or modules found"
}
} #Progress
End {
Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)"
} #end
} #close function
@jdhitsolutions
Copy link
Author

@jdhitsolutions
Copy link
Author

Modified to v1.1 to Sort locally installed version numbers before comparing them to online version.

@schittli
Copy link

Thanks a lot for your Function,! but you compare version strings and not Version Objects.
Therefore, your code does not recognize that Version 11 is newer than Version 2:

C:\Temp> '2.0.0.0' -gt '10.0.0.0'
true # For versions, this result is wrong

This works:

C:\Temp> [version]'2.2.3.4' -gt [version]'11.2.3.4'
False

Kind regards, Thomas

@jdhitsolutions
Copy link
Author

This function has been incorporated in the PSScriptTools module.

@jdhitsolutions
Copy link
Author

And as far as I can tell, my code is actually comparing version objects, not the strings.

@jdhitsolutions
Copy link
Author

Turns out I was wrong. PowerShell works better when I force the comparison as [version] types. Updated this file and the version in the PSScriptTools module that will ship with v1.8.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment