Comparing version numbers – Part II

Today I’d like to share a function for comparing semantic version numbers in PowerShell. To recap: Software developers should use a logical versioning style to better manage dependencies and to just make their releases and cycles well understandable. There is some kind of a specification out there. I’m not sure how “official” this is but it doesn’t look bad and sounds reasonable. Of course, if the 4th element is used for “beta” or “rc” like they suggest in the specification, the comparison solely by numbers is impossible. But you get the picture.

You might have seen the first article about a quick fix if you compare versions with more than 4 elements.ย Here’s a function that will shorten a version string to just 4 elements but will not fail if the version number has less than 4 elements.

I’m sure by using RegEx you could solve that problem much more sleek but for now I’ll just stick with the following solution:

Function Convert-VersionString {
    <#
    .SYNOPSIS
        Splits a version number using the dots and rebuilds the string with a maximum of 4 elements (Major.Minor.Build.Revision).
    .DESCRIPTION
        Splits a version number using the dots and rebuilds the string with a maximum of 4 elements (Major.Minor.Build.Revision).
        The goal is to use this reformatted string with the [version] accelerator. Of course this function can only be used
        if it's possible to ignore everything after the 4th element.
    .PARAMETER String
        Enter the version string.
    .EXAMPLE
        Convert-VersionString -String "3.0.2.2.0"
        The result will be: 3.0.2.2      
    .Notes
        Author: Fabian Szalatnay
        Date:   13. December 2018
    #>
    Param (
        [Parameter(Mandatory=$true)] [string]$String
    )
    # Set the maximum of elements in your version string
    $Digits  = 4
    # Initialize an empty version string
    $Version = ""
    # Split the string at every dot occurrence
    $Split   = $String.Split('.')
    # Check if the current number of elements is less than the maximum value, if so then set the maxium value to the current number
    if ($Split.Count -le $Digits) {$Digits = $Split.Count}
    # Loop trough the elements until you reach the maximum number minus 1 (the array starts with 0, therefore loop fom 0-3)
    for ($i=0;$i -le $Digits-1;$i++){
        # Build the new version string
        $Version = $Version + "." + $Split[$i]
    }
    # Echo the conversion result to keep you updated
    if ($Split.Count -gt $Digits) {
        Write-Log "Please note: $String was shortened to $($Version.Trim('.')) to make it 'semantic' for the [version] accelerator."
    }
    # Return the final version string and trim all leading and trailing dots that might occur
    Return $Version.Trim('.')
}

Let’s check out how we use that function:

Convert-VersionString -String "3.0.2.2.0"

Enclose the expression with parentheses to use it directly in your code:

$a = "3.0.2.2.0"
$b = "3.0.2.3.0"

if ([version](Convert-VersionString -String $a) -gt [version](Convert-VersionString -String $b)) {
    Write-Host "$a is greater than $b"
}
else {
    Write-Host "$a is less than $b"
}

Output:

Please note: 3.0.2.2.0 was shortened to 3.0.2.2 to make it 'semantic' for the [version] accelerator.
Please note: 3.0.2.3.0 was shortened to 3.0.2.3 to make it 'semantic' for the [version] accelerator.
3.0.2.2.0 is less than 3.0.2.3.0

So, if you’re a RegEx geek, don’t hesitate to post your solution in the comments ๐Ÿ˜‰

If you’re struggling with the comparison of file versions, check out this askpfe article to learn how to do proper file comparison.

2 thoughts on “Comparing version numbers – Part II”

  1. Hi Fabian,

    Coming a bit late to the fight, but here’s a quick solution to convert your string (regardless of length) to a version object:

    $Version = [Version] ($VersionString -replace ‘^(\d+(\.\d+){0,3})(\.\d+)*$’ , ‘$1’)

    This will effectively only catch up to 4 version bits and convert it to a [Version] object.

    Mickael

    Reply
    • Hi Mickael
      I knew it, RegEx for the Win ๐Ÿ™‚ Many thanks for your comment. Yours is a very pretty solution. Awesome!
      Regards
      Fabian

      Reply

Leave a Comment