0
votes

Have been working with NSIS (v3.05) for a few weeks. Does what it needs to do. I have been chasing the following problem for a few days and have not been able to comprehend it completely. Problem statement: Compare two (2) versions with each other. Many ways to implement. I chose the following: 1st 'version' (string) is retrieved from the currently installed versions .txt file via (function) LineRead (!include TextFunc.nsh) like this:

IfFileExists "C:\$PROGRAMFILES64\...\VERSION.txt" 0 +31 # Open the file and perform N FileRead 
    DetailPrint "VERSION.txt found!"   
    ${LineRead} "C:\$PROGRAMFILES64\...\VERSION.txt" "7" $4  # $4 = '1.x.y.z' (for example)

2nd 'version' is retrieved with following code:

!getdllversion "C:\...\application_name.exe" expversion_
StrCpy $7 ${expversion_}  # pass the define string 'expversion' to $7

As last part I use following code for comparison of $4 and $7:

${VersionCompare} $4 $7 $R0

This can only work as I know for sure that '$4' (version string #1) and '$7' (version string #2) are correct inputs for VersionCompare (output: $R0)

Question: Is there a way to display (for test/check) the content of $4 (@ compile time) in order to know for sure var $4 contains the correct string to be passed to function 'VersionCompare'? (tried 'DetailPrint $4'; does not resolve into the expected string (retrieved by function 'LineRead'). (I know that 'DetailPrint' only displays during executing the installation '.exe. file So is makes sense not seeing that @ compile time.)

Output from MakeNSIS:
IfFileExists: "C:\$PROGRAMFILES64\...\VERSION.txt" ? 0 : +31
DetailPrint: "VERSION.txt found!"
!insertmacro: LineReadCall
!insertmacro: end of LineReadCall
DetailPrint: "The version number of the currently installed app: $4"

How-To get $4 resolve into the version string (for testing purposes) during compile time)?

Question number 2: I use the preprocessor command '!GetDLLVersion' in a function to retrieve version number of the to be installed version of the 'app' (via The NSIS Installer...). MakeNSIS displays resolving the version correctly:

Function: "VersionRetrievalBinary"
!getdllversion: C:\1_SW_dev\...\app.exe (1.8.47.5)->(expversion_<1..4>)

Question: What exactly is 'expverion_'?; a var or a define? If a define (which I read here => Reference/!getdllversion), do I need to define it in my script as follow?:

!define expverion_1 " "  # Major; single digit
!define expverion_2 "  "  # Minor; 2-digit
!define expverion_3 "   " # Build; 3-digit
!define expverion_4 "   "# Revision; 3-digit

Being unsure what 'expversion_' exactly is and operates/works MakeNSIS throws following warning that -I think- indicates clearly something is incorrect:

warning 6000: unknown variable/constant "{expversion_}" detected, ignoring (C:\1_SW_dev\...\app_client.nsi:295)

The worrying part is the word 'ignoring' in the MakeNSIS compiling message. Can I conclude from above mentioned warning message that assigning the string derived from the (define?) with name "expversion_" is not passed to var $7 by means of command:

StrCpy $7 ${expversion_}

Following MakeNSIS message (@ compile time) appears to confirm this:

StrCpy $7 "${expversion_}" () ()

It appears to resolve empty (unsure if I read this MakeNSIS message correctly).

Although having learned a lot wrt NSIS (and liking it) and gone through most of the relevant documentation I do not get my head around this one.

Thnx in advance for solving this specific piece of the puzzle.

Have solved the puzzle myself. The solution to a version comparison is rather 'simple'. The essential parts herewith: (add to .onInit)

  1. Create a function (e.g. name 'VersionComparison')
  2. Read local version from registry
  3. 'Read' installation version from binary (e.g. .DLL or .exe)
  4. Use VersionCompare (!include WordFunc.nsh) to perform the actual comparison.
1
Hi Anders. Thnx for the quick response. Learned a lot. Will process the info provided and let you know the results.. - Guybrush_Treepwood
Appeared that your logic needed -for my script- some modification wrt syntax (compliant to LogicLib.nsh): ${IF} $R1 < 1 !error "Major version must be at least 1! We don't ship beta software ;)" ${EndIf}. Thnx anyway. - Guybrush_Treepwood
Hi Anders. Successfully solved the puzzle myself. I have added the solution puzzle pieces. Will also add the code snippet. Have not used your route, as It does not appear to be working for me... - Guybrush_Treepwood

1 Answers

0
votes

I'll tackle the !getdllversion issue first. It extracts the 4 16-bit numbers from the start of the version info block and stores them in 4 defines. It simply uses the name you pass in plus a number when naming the defines.

!getdllversion "$%windir%\explorer.exe" foo
!warning ${foo2} ; This prints the minor version

There is no specific number of digits as expected by your comments. Each of the 4 numbers go from 0 to 65535.

You can do basic verification of these numbers at compile time:

!if ${foo1} < 1
!error "Major version must at least be 1, we don't ship beta software :) " 
!endif

The 2nd problem is harder to solve. Variables can only be expanded when the installer is running. The only option is to actually generate and run a "installer" from inside your main .nsi:

!makensis vertest.nsi = 0
!execute '"$%temp%\vertest.exe" /S' = 0
!defile "$%temp%\vertest.exe" 

where vertest.nsi would look something like

OutFile "$%temp%\vertest.exe" 
RequestExecutionLevel user
SilentInstall silent

Section
Do version test here and Goto.. 
fail:
Abort
success:
SectionEnd