17

NSIS has a Name variable that you define in the script:

Name "MyApp"

It defines the name of the installer, that gets displayed as the window title, etc.

Is there a way to pull the .NET Version number out of my main EXE and append it to the Name?

So that my installer name would automatically be 'MyApp V2.2.0.0" or whatever?

codeulike
  • 22,514
  • 29
  • 120
  • 167
  • Nobody talks about it, but I think the best way to solve it without plugin is to use the function "searchparse" since NSIS > V2.39 I did a small article on it. http://ti-r.com/?Articles/NSIS/NSIS-versionning – Ti-R Aug 13 '18 at 14:32

7 Answers7

22

There might be a very simple way to do this, but I don't know what it is. When I first started using NSIS, I developed this workaround to suit my needs and haven't revisited the problem since to see if there's anything more elegant.

I wanted my installers to have the same version number, description, and copyright info as my main executable. So I wrote a short C# application called GetAssemblyInfoForNSIS that pulls that file info from an executable and writes it into a .nsh file that my installers include.

Here is the C# app:

using System;
using System.Collections.Generic;
using System.Text;

namespace GetAssemblyInfoForNSIS {
    class Program {
        /// <summary>
        /// This program is used at compile-time by the NSIS Install Scripts.
        /// It copies the file properties of an assembly and writes that info a
        /// header file that the scripts use to make the installer match the program
        /// </summary>
        static void Main(string[] args) {
            try {
                String inputFile = args[0];
                String outputFile = args[1];
                System.Diagnostics.FileVersionInfo fileInfo = System.Diagnostics.FileVersionInfo.GetVersionInfo(inputFile);
                using (System.IO.TextWriter writer = new System.IO.StreamWriter(outputFile, false, Encoding.Default)) {
                    writer.WriteLine("!define VERSION \"" + fileInfo.ProductVersion + "\"");
                    writer.WriteLine("!define DESCRIPTION \"" + fileInfo.FileDescription + "\"");
                    writer.WriteLine("!define COPYRIGHT \"" + fileInfo.LegalCopyright + "\"");
                    writer.Close();
                }
            } catch (Exception e) {
                Console.WriteLine(e.Message + "\n\n");
                Console.WriteLine("Usage: GetAssemblyInfoForNSIS.exe MyApp.exe MyAppVersionInfo.nsh\n");
            }
        }
    }
}

So if you use that application like so:

GetAssemblyInfoForNSIS.exe MyApp.exe MyAppVersionInfo.nsh

You would get a file named MyAppVersionInfo.nsh that looks something like this (assuming this info is in your executable):

!define VERSION "2.0" 
!define DESCRIPTION "My awesome application"
!define COPYRIGHT "Copyright © Me 2010"

At the top of my NSIS script, I do something like this:

!define GetAssemblyInfoForNSIS "C:\MyPath\GetAssemblyInfoForNSIS.exe"
!define PrimaryAssembly "C:\MyPath\MyApp.exe"
!define VersionHeader "C:\MyPath\MyAppVersionInfo.nsh"
!system '"${GetAssemblyInfoForNSIS}" "${PrimaryAssembly}" "${VersionHeader}"'
!include /NONFATAL "${VersionHeader}"

!ifdef VERSION
    Name "My App ${VERSION}"
!else
    Name "My App"
!endif

!ifdef DESCRIPTION
    VIAddVersionKey FileDescription "${DESCRIPTION}"
!endif

!ifdef COPYRIGHT
    VIAddVersionKey LegalCopyright "${COPYRIGHT}"
!endif

The first 3 defines set up the file names to use in the !system call to GetAssemblyInfoForNSIS.exe. This system call takes place during your installer's compilation and generates the .nsh file right before you include it. I use the /NONFATAL switch so that my installer doesn't fail completely if an error occurs in generating the include file.

Kyle Gagnet
  • 2,294
  • 2
  • 20
  • 27
12

You can do this without .NET by using the GetVersion plugin, but following the same basic logic:

Here is ExtractVersionInfo.nsi:

!define File "...\path\to\your\app.exe"

OutFile "ExtractVersionInfo.exe"
SilentInstall silent
RequestExecutionLevel user

Section

 ## Get file version
 GetDllVersion "${File}" $R0 $R1
  IntOp $R2 $R0 / 0x00010000
  IntOp $R3 $R0 & 0x0000FFFF
  IntOp $R4 $R1 / 0x00010000
  IntOp $R5 $R1 & 0x0000FFFF
  StrCpy $R1 "$R2.$R3.$R4.$R5"

 ## Write it to a !define for use in main script
 FileOpen $R0 "$EXEDIR\App-Version.txt" w
  FileWrite $R0 '!define Version "$R1"'
 FileClose $R0

SectionEnd

You compile this once, and then call it from your real installer:

; We want to stamp the version of the installer into its exe name.
; We will get the version number from the app itself.
!system "ExtractVersionInfo.exe"
!include "App-Version.txt"
Name "My App, Version ${Version}"
OutFile "MyApp-${Version}.exe"
  • It would be really interesting to know: Why is it required to compile a exe instead of just including some code? – FourtyTwo Jul 14 '16 at 12:26
9

Since NSISv3.0 this can be done with !getddlversion without using any third-party software:

!getdllversion "MyApp.exe" ver
Name "MyName ${ver1}.${ver2}.${ver3}.${ver4}"
OutFile "my_name_install_v.${ver1}.${ver2}.${ver3}.${ver4}.exe"
default locale
  • 13,035
  • 13
  • 56
  • 62
  • you sir are my hero. I have used your approach and it works quite well :) ``` !getdllversion "..\${app_name}\${app_name}.exe" ver !define PRODUCT_VERSION "${ver1}.${ver2}.${ver3}.${ver4}" !define VERSION "${ver1}.${ver2}.${ver3}.${ver4}" VIProductVersion "${PRODUCT_VERSION}" VIAddVersionKey "ProductName" "${app_name}" VIAddVersionKey "FileVersion" "${PRODUCT_VERSION}" VIAddVersionKey "VIProductVersion" "${VERSION}" VIAddVersionKey "LegalCopyright" "(C) ${author}" VIAddVersionKey "FileDescription" "${app_name}" ``` – Mike R Mar 24 '21 at 11:59
  • Awesome! Thanks. – Jason Hughes Oct 20 '21 at 21:53
3

I found a way to do this on the NSIS wiki:

http://nsis.sourceforge.net/Version_Info_manipulations_on_compile-time

Ashley Davis
  • 9,896
  • 7
  • 69
  • 87
  • 1
    That is a pretty interesting. I like how the new v3.x of NSIS can accomplish this via, !getdllversion and VIProductVersion/VIAddVersionKey. However, that is if anyone is on v3.x yet. – Damian Jan 12 '17 at 15:29
1

You can achieve this using MSBuild.

  1. Just add your .nsi script to project and set this file property Copy to Output Directory value Copy always or Copy if newer.

  2. Add to your project file (e.g. .csproj or .vbproj) following code (suppose your nsi script has name installer.nsi)

    <Target Name="AfterBuild" Condition=" '$(Configuration)' == 'Release'">
      <!-- Getting assembly information -->
      <GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
        <Output TaskParameter="Assemblies" ItemName="myAssemblyInfo"/>
      </GetAssemblyIdentity>
      <!-- Compile NSIS installer script to get installer file -->
      <Exec Command='"%programfiles(x86)%\nsis\makensis.exe" /DVersion=%(myAssemblyInfo.Version) "$(TargetDir)installer.nsi"'>
        <!-- Just to show output from nsis to VS Output -->
        <Output TaskParameter="ConsoleOutput" PropertyName="OutputOfExec" />
      </Exec>
    </Target>
    
  3. Use $Version variable in your nsi script:

    # define installer name
    OutFile "MyApp-${Version}.exe"
    
Vadim Ovchinnikov
  • 13,327
  • 5
  • 62
  • 90
0

Call simple VBS script after NSIS compile:

Set ddr = CreateObject("Scripting.FileSystemObject")
Version = ddr.GetFileVersion( "..\path_to_version.exe" )
ddr.MoveFile "OutputSetup.exe", "OutputSetup_" & Version & ".exe"
themadmax
  • 2,344
  • 1
  • 31
  • 36
-1

Since NSIS v3.0a0 you can do it directly in the script, no external tools needed: !getdllversion

Sample code (from the documentation):

!getdllversion "$%WINDIR%\Explorer.exe" Expv_
!echo "Explorer.exe version is ${Expv_1}.${Expv_2}.${Expv_3}.${Expv_4}"
YePhIcK
  • 5,816
  • 2
  • 27
  • 52