大部分的安装软件都有一个setup安装包,安装包或者拷贝文件,或者写注册表,或者写配置文件,或者创建快捷方式等等,所以这些都是自动完成的,用户只需提供一些信息,剩下的安装程序会帮助你完成。用户一般是通过一个向导来完成安装。你不必担心忘记了某些东西,安装程序会替你完成。

NSIS是一个制作安装包的软件,不仅能完成一般的文件拷本,而且还可以完成比较复杂的操作,比如写注册表,设置环境变量,从网上下载最新的文件。
NSIS编译所有文件以及安装脚本为一个可执行文件。

你需要做的只是写一个安装脚本,就可以创建一个安装包。脚本可以用任何文字编辑工具进行编写。

脚本里面的每一行都是一个命令。默认的脚本的扩展名为.nsi,头文件的扩展名为.nsh。包含头文件用如下的脚本
!include Sections.nsh

2.NSIS脚本包含安装包的属性 (Installer Attributes)和Sections节,Functions函数

2.1 安装属性Installer Attributes

安装属性决定安装包的外观。这些属性可以改变安装期间显示的文字以及安装类型的数字,大部分属性在安装期间是不可以改变的。
基本的安装属性如
Name(软件的名字),
InstallDir(要安装到的目录)。更详细的要参考 帮助文件的Install Attributes

Icon (设置setup的图标)

2.2 页面Pages
非静默安装包有一个页向导让用去配置安装包。你可以用Page命令去设置让那个页显示。典型的页面的设置如下:
Page license (显示license agreement页)
Page components(显示组件选择页面)
Page directory (显示安装文件夹的页面)
Page instfiles  (执行安装页面)
UninstPage uninstConfirm(显示卸载确认界面)
UninstPage instfiles(执行卸载的界面)

2.3 Sections节
普通的安装包里面一般有几种文件让用户选择安装,例如NSIS发布包里面的安装程序让你选择安装源代码,插件,例子以及其他。每一个组件有独立的代码。如果用户选择安装这个组件,安装包将执行这个代码。脚本里面,代码定义了节,每一个节对应组件页面里面的一个组件。节section 的名字就是组件的名字。

卸载也有很多的节,卸载的节的名字前面有un.的前缀,例如:
在节里面用到的指令也有很多。包括,解压文件,读写注册表,ini文件或者一般的文件,创建文件夹,创建快捷方式等等。更多情参考instructions
简单的示例:

Section "My Program"
  SetOutPath $INSTDIR ;设置安装目录,这个变量是根据前面的选择目标文件夹得到的
  File "My Program.exe"; 拷贝My Program.exe到目标文件夹
  File "Readme.txt"拷贝readme.txt到目标文件夹
SectionEnd

2.4 Functions函数
函数包含一些脚本代码。NSIS里面有两种类型的code。用户函数(user functions),回调函数(Callback functions)

用户函数就是一般的函数,跟C,C++等语言的函数没有区别。
回调函数是NSIS特有的函数。请参考帮助文件的 Callback Functions

.onInit
这个回调函数在初始化安装快要初始化完成的时候调用。
(安装界面出来以前)询问是否安装?此时可以选择退出安装。
Function .onInit
   MessageBox MB_YESNO "This will install. Continue?" IDYES NoAbort
     Abort ; causes installer to quit.
   NoAbort:
FunctionEnd

3 Working with Scripts 关于脚本的一些常规知识
1。Logical Code Structures逻辑指令
利用logicLib,我们的代码具有很好的可读性。
我们必须包含如下的脚本头文件
!include LogicLib.nsh

如下

${If} $0 == 'some value'
  MessageBox MB_OK '$$0 is some value'
${ElseIf} $0 == 'some other value'
  MessageBox MB_OK '$$0 is some other value'
${Else}
  MessageBox MB_OK '$$0 is "$0"'
${EndIf}

${If} $0 == ''
${AndIf} $1 == ''
  MessageBox MB_OK|MB_ICONSTOP 'both are empty!'
${EndIf}

${Switch} $0
  ${Case} 'some value'
    MessageBox MB_OK '$$0 is some value'
    ${Break}
  ${Case} 'some other value'
    MessageBox MB_OK '$$0 is some other value'
    ${Break}
  ${Default}
    MessageBox MB_OK '$$0 is "$0"'
    ${Break}
${EndSwitch}

StrCpy $R1 0
${While} $R1 < 5
  IntOp $R1 $R1 + 1
  DetailPrint $R1
${EndWhile}
${For} $R1 1 5
  DetailPrint $R1
${Next}
StrCpy $R1 0
${Do}
  IntOp $R1 $R1 + 1
  DetailPrint $R1
${LoopUntil} $R1 >= 5

3.2 Variables关于变量
你可以用Var命令来声明你自己的变量。变量是全局的,可以在任意的函数和节里面使用。

Var BLA ;声明变量

Section bla

  StrCpy $BLA "123" ;拷贝123到变量里面

SectionEnd

另外,有一个栈可以作为临时使用。使用PUSH,POP来访问这个栈。
push增加一个值到栈里面。
pop弹出一个值
系统里面还有20个寄存器变量($R0...$R1),这个静态变量不必声明,也没有名字冲突。如果你需要利用这些变量,请使用前存储这些旧的值,之后再还原这些值。但是必须注意这些顺序。

Function bla

  Push $R0
  Push $R1

    ...code...

  Pop $R1
  Pop $R0

FunctionEnd

3.3 Script Execution 脚本的执行
当运行一个安装或者反安装程序,page被顺序执行。当到达instfiles页面时,对应于被选择的组件的节被执行。如果components pages没有被显示,则所有的节都被执行。
Section里面的代码也有callback functions,如果定义了callback functions,callback functions将可以执行。
例如;.onInit 回调函数被执行在其他脚本执行之前。

笔记1到此结束。这节主要介绍一些脚本的语法。我们在笔记2里面会介绍些比较实用的例子