I am attempting to remove one more step in my application's release process by automatically retrieving versioning info from my executable (in this case, a .NET application).
Up to this point, I have been able to get by with a limited knowledge of NSIS, but I am quickly learning that this is not enough.
Step 1: Declare version info in executable
In AssemblyInfo.cs, I declare [assembly: AssemblyVersion("1.0.0.1")]
. This successfully makes the version info appear in the compiled executable (under "File version" and "Product version").
Step 2: Retrieve version info from executable
According to this article on "GetFileVersion", importing "FileFunc.nsh" allows you to retrieve version info from an executable.
Code used:
Section
Var /GLOBAL version
${GetFileVersion} "C:\test.exe" $version
...
SectionEnd
Step 3: Verify contents of function call
Based on section 5.1.7 of the documentation, I should be able to print to the command line during compile time using the "!echo" command. The difference between printing the contents of a variable (or a constant, etc) still confuses me, so I have tried all four of these options:
!echo $version
!echo "$version"
!echo "${version}"
!echo ${version}
This results in:
$version (InstallScript.nsi:15)
$version (InstallScript.nsi:16)
${version} (InstallScript.nsi:17)
${version} (InstallScript.nsi:18)
Step 4: Declare the installer metadata
Based on section 4.8.3, I should be able to add installer metadata via VIProductVersion
and VIAddVersionKey
.
VIProductVersion $version
VIAddVersionKey "FileVersion" "$version"
In the built installer, this adds the string "$version" into the specified fields.
Is there a ToString()
equivalent in NSIS? How can I access a variable's contents? Does the print of the variable name mean that it has no contents? How can I verify that GetFileVersion
is called correctly, executes correctly, and returns a value?
Edit: NSIS v3 now includes a !getdllversion
preprocessor instruction, you only need the GetVersionLocal workaround if you are still using NSIS v2.
There are plans for a !getdllversionlocal in NSIS 2.47, for now you have to use this workaround:
outfile test.exe
requestexecutionlevel user
!macro GetVersionLocal file basedef
!verbose push
!verbose 1
!tempfile _GetVersionLocal_nsi
!tempfile _GetVersionLocal_exe
!appendfile "${_GetVersionLocal_nsi}" 'Outfile "${_GetVersionLocal_exe}"$\nRequestexecutionlevel user$\n'
!appendfile "${_GetVersionLocal_nsi}" 'Section$\n!define D "$"$\n!define N "${D}\n"$\n'
!appendfile "${_GetVersionLocal_nsi}" 'GetDLLVersion "${file}" $2 $4$\n'
!appendfile "${_GetVersionLocal_nsi}" 'IntOp $1 $2 / 0x00010000$\nIntOp $2 $2 & 0x0000FFFF$\n'
!appendfile "${_GetVersionLocal_nsi}" 'IntOp $3 $4 / 0x00010000$\nIntOp $4 $4 & 0x0000FFFF$\n'
!appendfile "${_GetVersionLocal_nsi}" 'FileOpen $0 "${_GetVersionLocal_nsi}" w$\nStrCpy $9 "${N}"$\n'
!appendfile "${_GetVersionLocal_nsi}" 'FileWrite $0 "!define ${basedef}1 $1$9"$\nFileWrite $0 "!define ${basedef}2 $2$9"$\n'
!appendfile "${_GetVersionLocal_nsi}" 'FileWrite $0 "!define ${basedef}3 $3$9"$\nFileWrite $0 "!define ${basedef}4 $4$9"$\n'
!appendfile "${_GetVersionLocal_nsi}" 'FileClose $0$\nSectionend$\n'
!system '"${NSISDIR}\makensis" -NOCD -NOCONFIG "${_GetVersionLocal_nsi}"' = 0
!system '"${_GetVersionLocal_exe}" /S' = 0
!delfile "${_GetVersionLocal_exe}"
!undef _GetVersionLocal_exe
!include "${_GetVersionLocal_nsi}"
!delfile "${_GetVersionLocal_nsi}"
!undef _GetVersionLocal_nsi
!verbose pop
!macroend
!insertmacro GetVersionLocal "$%windir%\Explorer.exe" MyVer_
VIProductVersion "${MyVer_1}.${MyVer_2}.${MyVer_3}.${MyVer_4}"
VIAddVersionKey "FileVersion" "${MyVer_1}.${MyVer_2}.${MyVer_3}.${MyVer_4}"
page instfiles
section
sectionend
This macro:
Updated information:
NSIS now includes !getdllversion command which does the same thing. Usage:
!getdllversion "$%windir%\explorer.exe" expv_
!echo "Explorer.exe version is ${expv_1}.${expv_2}.${expv_3}.${expv_4}"
UPDATE: !getdllversion command is a "Compile Time Command", it's different from the GetDLLVersion instruction. IMO it should have been named as !getdllversionlocal to prevent confusion, since it's similar to GetDLLVersionLocal instruction, not the GetDLLVersion
In the user manual included in NSIS 3.0a1 it says:
5.1.14 !getdllversion
localfilename define_basename
This is similar to GetDLLVersionLocal, only it stores the version number in defines and can therefore be used anywhere, not just inside functions and sections.
!getdllversion "$%windir%\explorer.exe" expv_ !echo "Explorer.exe version is ${expv_1}.${expv_2}.${expv_3}.${expv_4}"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With