简体   繁体   English

NSIS - 将EXE版本放入安装程序的名称

[英]NSIS - put EXE version into name of installer

NSIS has a Name variable that you define in the script: NSIS有一个您在脚本中定义的Name变量:

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? 有没有办法从我的主EXE中提取.NET版本号并将其附加到名称?

So that my installer name would automatically be 'MyApp V2.2.0.0" or whatever? 这样我的安装程序名称将自动为“MyApp V2.2.0.0”或其他什么?

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. 当我第一次开始使用NSIS时,我开发了这种解决方法以满足我的需求,并且没有重新考虑问题,因为看看是否有更优雅的东西。

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. 所以我编写了一个名为GetAssemblyInfoForNSIS的简短C#应用程序,它从可执行文件中提取该文件信息并将其写入我的安装程序包含的.nsh文件中。

Here is the C# app: 这是C#应用程序:

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 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): 你会得到一个名为MyAppVersionInfo.nsh的文件看起来像这样(假设这个信息在你的可执行文件中):

!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: 在我的NSIS脚本的顶部,我做这样的事情:

!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. 前3个定义设置要在!系统调用GetAssemblyInfoForNSIS.exe时使用的文件名。 This system call takes place during your installer's compilation and generates the .nsh file right before you include it. 此系统调用在安装程序编译期间进行,并在包含之前生成.nsh文件。 I use the /NONFATAL switch so that my installer doesn't fail completely if an error occurs in generating the include file. 我使用/ NONFATAL开关,以便在生成包含文件时发生错误,我的安装程序不会完全失败。

You can do this without .NET by using the GetVersion plugin , but following the same basic logic: 您可以使用GetVersion插件在没有.NET的情况下执行此操作,但遵循相同的基本逻辑:

Here is ExtractVersionInfo.nsi: 这是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"

Since NSISv3.0 this can be done with !getddlversion without using any third-party software: 从NSISv3.0开始,可以使用!getddlversion完成,而无需使用任何第三方软件:

!getdllversion "MyApp.exe" ver
Name "MyName ${ver1}.${ver2}.${ver3}.${ver4}"
OutFile "my_name_install_v.${ver1}.${ver2}.${ver3}.${ver4}.exe"

You can achieve this using MSBuild. 您可以使用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 . 只需将.nsi脚本添加到项目并设置此文件属性Copy to Output DirectoryCopy alwaysCopy if newer

  2. Add to your project file (eg .csproj or . vbproj ) following code (suppose your nsi script has name installer.nsi ) 在代码之后添加到项目文件(例如.csprojvbproj )(假设您的nsi脚本具有名称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: nsi脚本中使用$Version变量:

     # define installer name OutFile "MyApp-${Version}.exe" 

Call simple VBS script after NSIS compile: 在NSIS编译后调用简单的VBS脚本:

Set ddr = CreateObject("Scripting.FileSystemObject")
Version = ddr.GetFileVersion( "..\path_to_version.exe" )
ddr.MoveFile "OutputSetup.exe", "OutputSetup_" & Version & ".exe"

Since NSIS v3.0a0 you can do it directly in the script, no external tools needed: !getdllversion 从NSIS v3.0a0开始,您可以直接在脚本中完成,无需外部工具: !getdllversion

Sample code (from the documentation): 示例代码(来自文档):

!getdllversion "$%WINDIR%\Explorer.exe" Expv_
!echo "Explorer.exe version is ${Expv_1}.${Expv_2}.${Expv_3}.${Expv_4}"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM