TL;DR: Update all your PoSH modules from PowershellGallery.com within your ISE profile - and with lightning speed!
I recently received a IseSteroids License due to being an MVP - many thanks to Tobias Weltner for this valuable gift!
I then started to think about "how do I keep IseSteroids" up to date? It receives minor updates quite frequently, so I tried this simple command in my personal ISE profile:
Update-Module -Name IseSteroids
This was a "no brainer" - update-module is a slow running thing. So ok, lets go - google/bing/whatever. I finally came up with a solution that has "history":
ScriptingFee had the idea of parsing the IseSteroids release history page to grab the latest version number. Then she compares this to the local IseSteroids version and in case of mismatch updates the module.
This idea was picked up by Tobias and driven a bit farther. He detects the most up to date version from the powershell gallery URL for a given module.
I had the idea of putting this into a pipeline aware function and wrap it in a second function that will update any module - including support for pipelining, whatIf/Confirm and Force. Here's what I came up with - comments welcome :-)
And if someone suggests to publish it to the Powershell Gallery - ok, then I will do, I promise!
function Get-PublishedModuleVersion
{
<#
.SYNOPSIS
Takes a module name and searches the Powershell gallery for its current version number. It accepts pipeline input for the module name.
.DESCRIPTION
When using Get-InstalledModule | Update-Module, this takes a long time. So some smart people on the web thought about how to improve this process.
The result is impressing - fetching the version number from the Powershell gallery URL for a module is a huge improvement over relying on Update-Module to detect the version numbers on its own.
.PARAMETER ModuleName
Specifies a module name to search the current version for
.EXAMPLE
Get-PublishedModuleVersion -ModuleName IseSteroids
Searches for the IseSteroids version in the Powershell gallery and returns its version number.
.LINK
http://www.powertheshell.com/findmoduleversion/
http://scriptingfee.de/isesteroids-auf-aktuellem-stand-halten/
.INPUTS
System.String
.OUTPUTS
System.Version
#>
[ CmdletBinding() ]
param
(
[ Parameter( Position = 0, HelpMessage='A module name must be specified to search for its current version. Please enter the name of a module.', Mandatory = $True, ValueFromPipeline = $True ) ] [string] $ModuleName
)
begin {
$baseurl = 'https://www.powershellgallery.com/packages'
}
process {
# access the main module page, and add a random number to trick proxies
$url = ( '{0}/{1}/?dummy={2}' -f $baseurl, $ModuleName, ( Get-Random ) )
$request = [System.Net.WebRequest]::Create( $url )
# do not allow to redirect. The result is a "MovedPermanently"
$request.AllowAutoRedirect = $false
try
{
# send the request
$response = $request.GetResponse()
# get back the URL of the true destination page, and split off the version
$response.GetResponseHeader( 'Location' ).Split( '/' )[-1] -as [Version]
# make sure to clean up
$response.Close()
$response.Dispose()
}
catch
{
Write-Warning -Message $_.Exception.Message
}
}
}
function Update-OutdatedModule {
<#
.SYNOPSIS
This function updates one or more modules that were installed from the PowerShell gallery if newer versions are available. It accepts pipeline input for the module name.
.DESCRIPTION
Updating modules from the Powershell Gallery can be done via calling Update-Module. This can even be used in a pipeline with Get-InstalledModule | Update-Module. But that's a quite slow command - so this workaround was created.
Update-OutdatedModule checks the module's download URL for the most current version number, and it updates only if the local version is older.
For modules that are installed for all users, it obviously requires an elevated session to work.
.PARAMETER ModuleName
The name of the module to update.
.PARAMETER Force
Updates the module even if the currently installed version is up to date.
.EXAMPLE
Update-OutdatedModule -ModuleName ScriptCop -Force
Updates the ScriptCop module regardless of its current version
.EXAMPLE
( Get-InstalledModules ).Name | Update-OutdatedModules -WhatIf
Checks if newer versions for any module are available, but does not update.
.NOTES
Place additional notes here.
.LINK
https://evilgpo.blogspot.com
http://powertheshell.com
.INPUTS
System.String
.OUTPUTS
None
#>
[ CmdletBinding( SupportsShouldProcess = $True ) ]
param(
[ Parameter( Position = 0, HelpMessage='One or more module names to be updated must be specified. Please enter the name of a module.', ValueFromPipeline = $True, Mandatory = $True ) ] [String] $ModuleName,
[Switch] $Force
)
process {
# first, get the version of the currently installed module. If it is not installed, Get-InstalledModule will throw a non-terminating error
Write-Verbose -Message ( 'Trying to check module version for {0}...' -f $ModuleName )
$CurrentModuleVersion = ( Get-InstalledModule -Name $ModuleName ).Version
If ( $CurrentModuleVersion -eq $null ) { Return }
Write-Verbose -Message ( 'Found installed version : {0}' -f $CurrentModuleVersion.ToString() )
# Then get the version that is available in the powershell gallery. If it is not in the gallery, Get-PublishedModuleVersion will throw a warning
Write-Host ( 'Checking current {0} version {1} for updates...' -f $ModuleName, $CurrentModuleVersion )
$AvailableModuleVersion = Get-PublishedModuleVersion -ModuleName $ModuleName
If ( $AvailableModuleVersion -eq $null ) { Return }
Write-Verbose -Message ( 'Latest available version: {0}' -f $AvailableModuleVersion.ToString() )
# Check if versions already match. Since we use [version] types, we do not need to take care if the version has 2, 3 or 4 parts.
If ( $CurrentModuleVersion -ge $AvailableModuleVersion )
{
Write-Host ( '{0} version is already up to date.' -f $ModuleName ) -ForegroundColor Green
If ( $Force )
{
Write-Verbose -Message '"Force" specified, updating anyway...'
# fooling the second check if -force was specified - better ideas welcome about how to pass -force down to Update-Module...
$CurrentModuleVersion = [Version]0.0.0.0
}
}
# check if versions do not match (will always be true if -force was specified) and do what has to be done
If ( $CurrentModuleVersion -lt $AvailableModuleVersion )
{
Write-Host ( 'Updating {0} to new version {1}...' -f $ModuleName, $AvailableModuleVersion ) -ForegroundColor Yellow
If ( $PSCmdlet.ShouldProcess( $ModuleName ) )
{
# We always use the -force switch here because we already caught if the module does not need to be updated.
# If we reach this line, the module is either outdated or the -force switch was specified by the user
Update-Module -Name $ModuleName -Force -Verbose
}
}
}
}
# Update-OutdatedModule -ModuleName IseSteroids
{
<#
.SYNOPSIS
Takes a module name and searches the Powershell gallery for its current version number. It accepts pipeline input for the module name.
.DESCRIPTION
When using Get-InstalledModule | Update-Module, this takes a long time. So some smart people on the web thought about how to improve this process.
The result is impressing - fetching the version number from the Powershell gallery URL for a module is a huge improvement over relying on Update-Module to detect the version numbers on its own.
.PARAMETER ModuleName
Specifies a module name to search the current version for
.EXAMPLE
Get-PublishedModuleVersion -ModuleName IseSteroids
Searches for the IseSteroids version in the Powershell gallery and returns its version number.
.LINK
http://www.powertheshell.com/findmoduleversion/
http://scriptingfee.de/isesteroids-auf-aktuellem-stand-halten/
.INPUTS
System.String
.OUTPUTS
System.Version
#>
[ CmdletBinding() ]
param
(
[ Parameter( Position = 0, HelpMessage='A module name must be specified to search for its current version. Please enter the name of a module.', Mandatory = $True, ValueFromPipeline = $True ) ] [string] $ModuleName
)
begin {
$baseurl = 'https://www.powershellgallery.com/packages'
}
process {
# access the main module page, and add a random number to trick proxies
$url = ( '{0}/{1}/?dummy={2}' -f $baseurl, $ModuleName, ( Get-Random ) )
$request = [System.Net.WebRequest]::Create( $url )
# do not allow to redirect. The result is a "MovedPermanently"
$request.AllowAutoRedirect = $false
try
{
# send the request
$response = $request.GetResponse()
# get back the URL of the true destination page, and split off the version
$response.GetResponseHeader( 'Location' ).Split( '/' )[-1] -as [Version]
# make sure to clean up
$response.Close()
$response.Dispose()
}
catch
{
Write-Warning -Message $_.Exception.Message
}
}
}
function Update-OutdatedModule {
<#
.SYNOPSIS
This function updates one or more modules that were installed from the PowerShell gallery if newer versions are available. It accepts pipeline input for the module name.
.DESCRIPTION
Updating modules from the Powershell Gallery can be done via calling Update-Module. This can even be used in a pipeline with Get-InstalledModule | Update-Module. But that's a quite slow command - so this workaround was created.
Update-OutdatedModule checks the module's download URL for the most current version number, and it updates only if the local version is older.
For modules that are installed for all users, it obviously requires an elevated session to work.
.PARAMETER ModuleName
The name of the module to update.
.PARAMETER Force
Updates the module even if the currently installed version is up to date.
.EXAMPLE
Update-OutdatedModule -ModuleName ScriptCop -Force
Updates the ScriptCop module regardless of its current version
.EXAMPLE
( Get-InstalledModules ).Name | Update-OutdatedModules -WhatIf
Checks if newer versions for any module are available, but does not update.
.NOTES
Place additional notes here.
.LINK
https://evilgpo.blogspot.com
http://powertheshell.com
.INPUTS
System.String
.OUTPUTS
None
#>
[ CmdletBinding( SupportsShouldProcess = $True ) ]
param(
[ Parameter( Position = 0, HelpMessage='One or more module names to be updated must be specified. Please enter the name of a module.', ValueFromPipeline = $True, Mandatory = $True ) ] [String] $ModuleName,
[Switch] $Force
)
process {
# first, get the version of the currently installed module. If it is not installed, Get-InstalledModule will throw a non-terminating error
Write-Verbose -Message ( 'Trying to check module version for {0}...' -f $ModuleName )
$CurrentModuleVersion = ( Get-InstalledModule -Name $ModuleName ).Version
If ( $CurrentModuleVersion -eq $null ) { Return }
Write-Verbose -Message ( 'Found installed version : {0}' -f $CurrentModuleVersion.ToString() )
# Then get the version that is available in the powershell gallery. If it is not in the gallery, Get-PublishedModuleVersion will throw a warning
Write-Host ( 'Checking current {0} version {1} for updates...' -f $ModuleName, $CurrentModuleVersion )
$AvailableModuleVersion = Get-PublishedModuleVersion -ModuleName $ModuleName
If ( $AvailableModuleVersion -eq $null ) { Return }
Write-Verbose -Message ( 'Latest available version: {0}' -f $AvailableModuleVersion.ToString() )
# Check if versions already match. Since we use [version] types, we do not need to take care if the version has 2, 3 or 4 parts.
If ( $CurrentModuleVersion -ge $AvailableModuleVersion )
{
Write-Host ( '{0} version is already up to date.' -f $ModuleName ) -ForegroundColor Green
If ( $Force )
{
Write-Verbose -Message '"Force" specified, updating anyway...'
# fooling the second check if -force was specified - better ideas welcome about how to pass -force down to Update-Module...
$CurrentModuleVersion = [Version]0.0.0.0
}
}
# check if versions do not match (will always be true if -force was specified) and do what has to be done
If ( $CurrentModuleVersion -lt $AvailableModuleVersion )
{
Write-Host ( 'Updating {0} to new version {1}...' -f $ModuleName, $AvailableModuleVersion ) -ForegroundColor Yellow
If ( $PSCmdlet.ShouldProcess( $ModuleName ) )
{
# We always use the -force switch here because we already caught if the module does not need to be updated.
# If we reach this line, the module is either outdated or the -force switch was specified by the user
Update-Module -Name $ModuleName -Force -Verbose
}
}
}
}
# Update-OutdatedModule -ModuleName IseSteroids
No comments:
Post a Comment