MAKEMSI quickly and reliably creates MSI files in a non-programmatic way
Have your say! Join the MAKEMSI discussion list or view archive! Suggest improvements. No question too simple or too complex.
[Bottom][Contents][Prev]: Browse Dialog - Changing Directory[Next]: Files In Use - ADD
Have your say! Join the MAKEMSI discussion list or view archive! Suggest improvements. No question too simple or too complex.
\->Tips and Tricks->File and Directory->File Version Compare Code

File Version Compare Code

The following code demonstrates a VBSCRIPT function which will compare file version numbers such as ("5.60.1234.0001" and "5.60"). It is in the form of a macro so that you could define it in your common header file and refer to the macro in any "VbsCa" code that needed it (and an example of this is provided below as well as in the "MDAC not too old?" launch condition section).

This is the macro to define the VBSCRIPT function "CompareFileVersions()"):

;--- Define Return codes ----------------------------------------------------
#define FILEVER_RC_F1_EQUAL_F2          0
#define FILEVER_RC_F1_LESS_THAN_F2     -1
#define FILEVER_RC_F1_GREATER_THAN_F2   1

;--- Define the macro -------------------------------------------------------
#(  '<?NewLine>'
    ;--- Define macro used to include this code -----------------------------
    #define INCLUDE_VBSCRIPT_FUNCTION-CompareFileVersions   ;;Version 09.138

    '========================================================================
    function CompareFileVersions(VerF1, VerF2)
    '========================================================================
        '-------- Init ------------------------------------------------------
        CaDebug 0, "CompareFileVersions() """ & VerF1 & """ with """ & VerF2 & """"
        VbsCaLogInc 1
        on error resume next
        CompareFileVersions = <$FILEVER_RC_F1_EQUAL_F2>

        '-------- Split up the version numbers ------------------------------
        dim VerBitsF1 : VerBitsF1 = split(VerF1, ".")
        dim VerBitsF2 : VerBitsF2 = split(VerF2, ".")

        '-------- How many "bits" are there (use largest of the two) --------
        dim LastIndex : LastIndex = ubound(VerBitsF1)
        if  ubound(VerBitsF2) > LastIndex then
            LastIndex = ubound(VerBitsF2)
        end if

        '-------- Work through each of the bits (probably 4) ----------------
        dim i
        for i = 0 to LastIndex
            '--- Work out the 2 "bits" to compare (use "0" on shorter versions) ---
            dim BitF1, BitF2
            if  i <= ubound(VerBitsF1) then BitF1 = VerBitsF1(i) else BitF1 = ""
            if  i <= ubound(VerBitsF2) then BitF2 = VerBitsF2(i) else BitF2 = ""
            if  BitF1 = "" then  BitF1 = "0"        ;;May as well be paranoid...
            if  BitF2 = "" then  BitF2 = "0"

            '-------- Compare the values (exit when mismatch found) ---------
            CaDebug 0, "Comparing level #" & i+1 & """: " & BitF1 & """ with """ & BitF2 & """"
            VbsCaLogInc 1
            if  cint(BitF1) > cint(BitF2) then
                CaDebug 0, """" & BitF1 & """ is greater than """ & BitF2 & """"
                CompareFileVersions = <$FILEVER_RC_F1_GREATER_THAN_F2>
            else
                if  cint(BitF1) < cint(BitF2) then
                    CaDebug 0, """" & BitF1 & """ is less than """ & BitF2 & """"
                    CompareFileVersions = <$FILEVER_RC_F1_LESS_THAN_F2>
                end if
            end if
            VbsCaLogInc -1
            if CompareFileVersions <> <$FILEVER_RC_F1_EQUAL_F2> then exit for
        next
        CaDebug 0, "Compare answer is " & CompareFileVersions
        VbsCaLogInc -1
    end function
#)

Custom Action To Check Installed File Version

The following code defines a macro (which makes use of the one above) to generate custom actions to validate that an installed file has a minimum version:

#(
    #define FileVerMustbeAtLeast            ;;Version 09.138

    ;--- Adjust the value to something Windows Installer can compare ----
    <$VbsCa Binary="FileVer_{$File}_MustbeAtLeast.vbs" DATA="{$File}">
    #( '<?NewLine>'
       <$VbsCaEntry "ValidateFileVersion">
            ;--- Init (get "passed" parameters) -----------------------------
            dim VerMin     : VerMin         = VbsCaCadGet("VerMin")
            dim FileName   : FileName       = VbsCaCadGet("FileName")
            CaDebug 1, "Verifying version of """ & FileName & """"
            VbsCaLogInc 1

            ;--- Now Get the file version -----------------------------------
            dim VerFile : VerFile = GetFileVersion(FileName)
            CaDebug 2, "Version is " & VerFile

            ;--- Compare ------------------------------------------------
            CaDebug 0, "Comparing the versions..."
            dim CompRc, PropertyValue
            CompRc = CompareFileVersions(VerFile, VerMin)
            if  CompRc <> <$FILEVER_RC_F1_EQUAL_F2> and CompRc = <$FILEVER_RC_F1_LESS_THAN_F2> then
                VbsCaRaiseError "ValidateFileVersion()", "The file """ & FileName & """ has version " & VerFile & vbCRLF & vbCRLF & "This doesn't meet the minimum requirement of version " & VerMin
            end if
            CaDebug 0, "Version of the file is OK..."

            ;--- set the property ---------------------------------------
            VbsCaLogInc -1
       <$/VbsCaEntry>

       <?NewLine><?NewLine>
       '++++++++++++++++++++++++++++++++
       function GetFileVersion(FileName)
       '++++++++++++++++++++++++++++++++
            ;--- Make sure the file exists ----------------------------------
            dim oFS : set oFS = CaMkObject("Scripting.FileSystemObject")
            if  not oFS.FileExists(FileName) then
                VbsCaRaiseError "ValidateFileVersion()", "The file """ & FileName & """ doesn't exist!"
            end if
            set oFS = Nothing

            ;--- Get the file info ------------------------------------------
            dim oInstaller : set oInstaller = CaMkObject("WindowsInstaller.Installer")
            on error resume next
            GetFileVersion = oInstaller.FileVersion(FileName, 0)
            if  err.number <> 0 then
                dim Reason : Reason = "0x" & hex(err.number) & " - " & err.description
                on error goto 0
                VbsCaRaiseError "ValidateFileVersion()", "Couldn't get the file version for """ & FileName & """." & vbCRLF & vbCRLF & "Reason: " & Reason
            end if

            ;--- Term -------------------------------------------------------
            set oInstaller = Nothing
       end function

       ;--- Add required compare function(s) ----------------------------
       <$INCLUDE_VBSCRIPT_FUNCTION-CompareFileVersions>
    #)
    <$/VbsCa>
    <$VbsCaSetup Binary="FileVer_{$File}_MustbeAtLeast.vbs" Key="FileVer_{$File}" Entry="ValidateFileVersion" Seq="InstallInitialize-" CONDITION=^<$CONDITION_INSTALL_ONLY>^ DATA="{$File}">
#)

Now that you have defined the two macros above you can use them as follows:

#data "userenv_dll"
   "FileName" "[SystemFolder]userenv.dll" ;;Full name of the file
   "VerMin"   '5.00.2195.3652'            ;;Minimum version we want
#data
<$FileVerMustbeAtLeast File="userenv_dll">


Microsoft awarded me an MVP (Most Valuable Professional award) in 2004, 2005, 2006, 2007, 2008 & 2009 for the Windows SDK (Windows Installer) area.Please email me any feedback, additional information or corrections.
See this page online (look for updates)

[Top][Contents][Prev]: Browse Dialog - Changing Directory[Next]: Files In Use - ADD


MAKEMSI© is (C)opyright Dennis Bareis 2003-2008 (All rights reserved).
Saturday May 28 2022 at 3:11pm
Visit MAKEMSI's Home Page
Microsoft awarded me an MVP (Most Valuable Professional award) in 2004, 2005, 2006, 2007, 2008 & 2009 for the Windows SDK (Windows Installer) area.