本文以一个完整的、传统界面的网易云音乐安装包的脚本为示例,来介绍 NSIS 传统用户界面的开发流程。

网易云音乐安装脚本

完整的示例脚本如下,脚本中包含了详细的注释加以解释说明。请将下面脚本保存为.nsi 文件(需使用 ANSI 编码保存),编译即可生成安装包。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# 单行注释用井号"#"或分号";",跨行注释用可以用C/C++中注释语法。
# 使用!define定义一些常量(如安装包的版本号等)
# 对常量或变量的引用可以使用如${PRODUCT_NAME}格式,也可以使用如$PRODUCT_NAME格式

!define PRODUCT_NAME "网易云音乐"
!define EXE_NAME "cloudmusic.exe"
!define PRODUCT_VERSION "1.0.0.1"
!define PRODUCT_PUBLISHER "NetEase"
!define PRODUCT_LEGAL "NetEase 1999-2014"
!define TEMP_DIR ""

/*
NSIS内置了一些常用的变量,如
$INSTDIR 表示用户定义的解压路径;
$DESKTOP 表示Windows桌面目录;
等等。


也可以用 Var 命令来声明自己的变量($VARNAME)。 NSIS的变量都是全局的并且可以在任何区段或函数中使用。
另外堆栈可以用来作为临时存储。 使用 Push 和 Pop 命令来访问堆栈。Push把一个值添加到堆栈,Pop移除一个值并且设置该变量。
且NSIS内置了20个已注册的变量 (如 $0~$9 和 $R0~$R9)。 这些变量不需要声明就可以使用。
*/

# 定义安装包可执行文件的版本信息
VIProductVersion "${PRODUCT_VERSION}"
VIAddVersionKey "ProductVersion" "${PRODUCT_VERSION}"
VIAddVersionKey "ProductName" "${PRODUCT_NAME}"
VIAddVersionKey "CompanyName" "${PRODUCT_PUBLISHER}"
VIAddVersionKey "FileVersion" "${PRODUCT_VERSION}"
VIAddVersionKey "InternalName" "${EXE_NAME}"
VIAddVersionKey "FileDescription" "${PRODUCT_NAME}"
VIAddVersionKey "LegalCopyright" "${PRODUCT_LEGAL}"

# ==================== NSIS属性 ================================
# 设置安装包的压缩方案,有ZLIB(默认)、BZIP2、LZMA
SetCompressor lzma

; 设置安装包名字,显示在安装包标题栏等位置
Name "$PRODUCT_NAME"

# 安装包可执行程序文件名
OutFile "网易云音乐安装-Basic UI.exe"

# 安装包默认安装位置,也就是安装路径的默认值
InstallDir "$PROGRAMFILES\Netease\CloudMusic"


# 设置是否显示安装详细信息
ShowInstDetails hide

# 设置是否显示卸载详细信息
ShowUnInstDetails hide

# 针对Vista和win7+ 的UAC进行权限请求.
# RequestExecutionLevel none|user|highest|admin
RequestExecutionLevel admin


# 安装和卸载程序的图标
Icon "image\logo.ico"
UninstallIcon "image\un_logo.ico"


/*
向导页面是NSIS安装程序中最重要的界面元素,在nsis脚本中可以使用NSIS内置页面或者定制界面,
通过脚本可以指定页面的顺序、显示样子和行为。 PageEx指令用来定义安装程序中的页面,也可以使用Page指令,但PageEx提供更多选项;UninstPage用来定义卸载页面。
页面显示的顺序和它在nsis脚本中定义的次序一致。

安装页面有:license|components|directory|instfiles|
卸载页面有:uninstConfirm

每个页面有不同元素和属性。
也可以使用Page custom来自定义页面,这个后面的文章有讲到。
*/

PageEx license
LicenseData "license.rtf" #可以是txt或rtf文件格式
PageExEnd


/*
在一个普通的安装包里用户需要安装许多东西。例如在NSIS安装包里你可以选择安装源码、附加插件、脚本样例或其他。
里面的每个组件都有它自己的代码块,当用户选择了安装该组件,那么安装程序就会执行对应的代码。
在脚本里,这些代码称为区段,见下面的Section。每个可见的区段都可以作为一个组件给用户选择是否安装。你可以只使用一个区段来构建安装包,但是如果你想要使用组件页来让用户选择可选的组件,那你就需要使用多个区段。
*/
PageEx components
Caption "组件选择"
ComponentText "选择安装组件:" "主程序" "快捷方式"
PageExEnd

PageEx directory
Caption "安装目录"
DirText "请选择安装目录:"
PageExEnd

PageEx instfiles
PageExEnd


# 区段1
# 区段名以一个!开头,那么该区段的显示名称将以粗体字显示.
Section "!Files" "des_files"

; 设置下面指定的文件在安装时默认的解压路径
SetOutPath $INSTDIR

; 指明哪些文件需要被压缩进入安装包,"app\*.*"是相对于nsis脚本文件的相对路径
File /r "app\*.*"

SectionEnd


# 区段2
# 该区段专门用来创建一些快捷方式
#
Section "Shortcut" "des_shortcut"
SetShellVarContext all
CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk" "$INSTDIR\${EXE_NAME}"
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\卸载${PRODUCT_NAME}.lnk" "$INSTDIR\uninst.exe"
SetShellVarContext current
SectionEnd


# 区段3
# 区段名为空、遗漏或者以一个 "-" 开头,那么它将是一个隐藏的区段,用户也不能选择禁止它.
#
Section "-Necessary"

# 生成卸载程序
WriteUninstaller "$INSTDIR\uninst.exe"

# 添加卸载信息到控制面板
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "DisplayName" "${PRODUCT_NAME}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "UninstallString" "$INSTDIR\uninst.exe"

/*
在NSIS脚本里每一行都作为一个命令处理,如果这一行太长的话你可以使用“\”来分隔,编译器会自动地把下一行接到上一行来作为完整的一行,而不是看作新的行。
*/
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "DisplayIcon" "$INSTDIR\${EXE_NAME}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "Publisher" "$INSTDIR\${PRODUCT_PUBLISHER}"
SectionEnd


# 卸载区段,如果一个区段名为“Uninstall”或以“un.”为前缀,那么它就是一个卸载程序区段。
#
Section "Uninstall"

; 删除快捷方式,SetShellVarContext 设置操作是针对当前用户还是所有用户
SetShellVarContext all
Delete "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk"
Delete "$SMPROGRAMS\${PRODUCT_NAME}\卸载${PRODUCT_NAME}.lnk"
RMDir "$SMPROGRAMS\${PRODUCT_NAME}\"
Delete "$DESKTOP\${PRODUCT_NAME}.lnk"
SetShellVarContext current

SetOutPath "$INSTDIR"

; 删除安装的文件
Delete "$INSTDIR\*.*"

SetOutPath "$DESKTOP"

RMDir /r "$INSTDIR"
RMDir "$INSTDIR"

SetAutoClose true
SectionEnd


# ============================== 回调函数 ====================================

# 函数名以“.”开头的一般作为回调函数保留.
# 函数名以“un.”开头的函数将会被创建在卸载程序里,因此,普通安装区段和函数不能调用卸载函数,而卸载区段和卸载函数也不能调用普通函数。

Function .onInit
FunctionEnd

Function .onGUIInit

FunctionEnd


# 安装成功以后.
Function .onInstSuccess

FunctionEnd


# 卸载操作开始前.
Function un.onInit
MessageBox MB_ICONQUESTION|MB_YESNO "你确实要完全删除网易云音乐,及其所有组件吗?" /SD IDYES IDYES +2 IDNO +1
Abort
FunctionEnd

# 卸载成功以后.
Function un.onUninstSuccess
MessageBox MB_ICONINFORMATION|MB_OK "${PRODUCT_NAME} 已成功地从你的计算机移除" /SD IDOK
FunctionEnd

上述脚本会将与脚本相同级别的 app 目录下的全部文件(含子目录)打包进安装包。image\logo.icoimage\un_logo.ico分别是安装包和卸载程序的图标。

运行截图