I'm trying to compare a couple of version numbers with a simple PowerShell example. From the below, I would expect $thisversion to be less than $nextversion. But the comparison suggests not? What am i missing? I'm gathering that [version] treats "03" as just "3", but that doesn't solve my problem. How can i factor in leading zeros into version comparison?
$thisversion = "14.03.0.0"
$nextversion = "14.1.0.56686"
write-host $thisversion
write-host $nextversion
if (([version]$thisversion) -lt ([version]$nextversion)) {
write-host "$thisversion is less then $nextversion"
}
([version]$thisversion).CompareTo(([version]$nextversion))
#returns 1
The reason for this request is due to sloppy software vendors. I'm sorting through a list of software and trying to work out older versions. In a few cases (for example), "Vendor App 14.03.0.0" is an older version of "Vendor App 14.1.0.56686".
UPDATE
A tweak to @zett42 answer below:
function CompareVersionStrings([string]$Version1, [string]$Version2) {
$v1 = $Version1.Split('.') -replace '^0', '0.'
$v2 = $Version2.Split('.') -replace '^0', '0.'
[Array]::Resize( [ref] $v1, 4 )
[Array]::Resize( [ref] $v2, 4 )
for ($i=0; $i-lt 4; $i++) {
switch (($v1[$i].length).CompareTo(($v2[$i].length))) {
{$_ -lt 0} { $v1[$i] = $v1[$i].PadRight($v2[$i].Length,'0') }
{$_ -gt 0} { $v2[$i] = $v2[$i].PadRight($v1[$i].Length,'0') }
}
}
$v1f = $v1 | % {[float]$_}
$v2f = $v2 | % {[float]$_}
return [Collections.StructuralComparisons]::StructuralComparer.Compare( $v1f, $v2f )
}
$thisversion = "14.1.0.5668"
$nextversion = "14.1.0.56686"
switch (CompareVersionStrings $thisversion $nextversion) {
{$_ -lt 0} { write-host "$thisversion is less than $nextversion" }
{$_ -gt 0} { write-host "$thisversion is greater than $nextversion" }
{$_ -eq 0} { write-host "$thisversion is the same as $nextversion" }
}
Continuing from my comment, I would convert all fields of the version to
[float]. Before conversion, if a version field starts with zero, I would interpret it as a fraction of1by inserting a.after the first0.So
14.03.0.0becomes the sequence of floating point numbers14.0,0.3,0.0,0.0.Similarly,
14.003.01.0becomes the sequence of floating point numbers14.0,0.03,0.1,0.0.Simplest solution
$array1 -lt $array2just doesn't work. To use it, we call[Collections.StructuralComparisons]::StructuralComparer.Compare(), which returns-1(array1 < array2),0(array1 = array2) or1(array1 > array2).0.0for missing elements):More elaborate test:
Output:
Extended solution
You may want to encapsulate version numbers with
[float]fields in a dedicated class, similar to[Version], to be able to use PowerShell's standard comparison operators like-lt,-eqand-gt.The following class
FloatVersionparses version numbers that may contain leading zeros and implements theIComparableinterface to support the standard comparison operators.The floating point numbers that make up the version are stored as
[Tuple[float,float,float,float]], which already provides lexicographical comparison.Usage example:
More elaborate test:
Output: