tianyi
tianyi

Reputation: 377

Compare the software version number in PowerShell

I use PowerShell to install software, I need to compare the version number. Some software version numbers are divided into multiple sections, how to compare? Here's an example:

$Old_ver=18.05
$New_ver=19.00

if ($New_ver -gt $Old_ver) {
    Write-Output "You need to install a new version"
} elseif ($New_ver -eq $Old_ver) {
    Write-Output "You have already installed"
} else {
    Write-Output "You have installed a new version"
}

Upvotes: 4

Views: 3450

Answers (3)

DRamos
DRamos

Reputation: 1

Here is a PowerShell function that will properly convert software version strings into .Net [Version] objects used for comparison:

<#
.SYNOPSIS
Converts a version string into a .Net [version] object
The version string may have up to 4 numerical segments that are separated by a period.
Any additional segments are ignored.
A non numerical segment or empty string will result in a $null version

.EXAMPLE
'1.2.3' -> Maj=1  Min=2  Build=3  Revision=0
'1'     -> Maj=1  Min=0  Build=0  Revision=0  
'0.2'   -> Maj=0  Min=2  Build=0  Revision=0
#>
function Convert-VersionString
{
    [CmdletBinding()]
    [OutputType([version])]
    param (
        [Parameter()]
        [string] $version = $null
    )

    [version]$ver = $null
    if (![string]::IsNullOrWhiteSpace($version))
    {
        try 
        {
            $parts = $version -split '\.'
            [Array]::Resize( [ref] $parts, 4 )
            $ver = New-Object -TypeName System.Version -ArgumentList $parts
        }
        catch {}
    }
    return $ver
}


<#
.SYNOPSIS
Returns -1, 0 or 1 depending whether v1 is lower, equal or higher than v2
The input strings are converted to a .net [version] using Convert-VersionString()
The version string may have up to 4 numerical segments that are separated by a period.
Any additional segments are ignored.
A non numerical segment or empty string will result in a $null version which has the lowest value.

.EXAMPLE
Compare-Version '1.2.3'     '1.2.3'  # Returns  0
Compare-Version '1.2.3.0'   '1.2.3'  # Returns  0
Compare-Version '1.2.3'     '2.0'    # Returns -1
Compare-Version '1.2.3'     '1.2.34' # Returns -1
Compare-Version '1.2.3'     '1.0'    # Returns +1
Compare-Version '0'         $null    # Returns +1
Compare-Version '0'         '1.abc'  # Returns +1
#>
function Compare-Version
{
    [CmdletBinding()]
    param (
        [Parameter(Position="0")]
        [string] $v1 = $null,

        [Parameter(Position="1")]
        [string] $v2 = $null
    )

    [version]$ver1 = Convert-VersionString -version $v1
    [version]$ver2 = Convert-VersionString -version $v2
    
    if ($ver1 -lt $ver2)
    {
        return -1
    }
    elseif ($ver1 -eq $ver2)
    {
        return 0
    }
    return 1
}

Upvotes: 0

mhu
mhu

Reputation: 18041

Besides casting to [Version], you could also instantiate the Version objects directly:

$Old_ver = [Version]::new(18, 5)
$New_ver = [Version]::new(19, 0)

or

$Old_ver = [Version]::new('18.05')
$New_ver = [Version]::new('19.00')

Upvotes: 2

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200233

Define your version numbers as strings and cast them to [version] objects.

[version]$Old_ver = '18.05'
[version]$New_ver = '19.00'

Upvotes: 9

Related Questions