NSIS 使用

NSIS 是流行的 Windows 程序打包程序。使用其脚本配置快速生成。该工具支持在多个平台下工作。
本文在 MacOS 下安装该工具,并打包使用 golang 的 Wails 编写的客户端程序。

安装 NSIS

该软件支持 Windows,Linux 和 MacOS。根据 Wails 官网部分 指引安装即可。
在 MacOS 系统中,本文使用 homebrew 安装。

1
brew install nsis

实际安装的二进制命令为 makensis

脚本编写

Wails 创建的项目自带了 nsis 的配置脚本。但是对于初次接触的人不好理解里面各种命令、指令的作用 。本人从空白到打包完成给出基础的命令。细节部分还不到位,还需要查询资料后处理。

⚠️注意:NSIS 脚本的执行是自上而下执行。所以命令的执行是有先后顺序的,必须按照以下顺序依次配置编写。

首先创建一个文件,结尾使用 .nsi 结尾,该文件就是我们的打包配置脚本了。

NSIS 的安装界面我们使用现代的 UI 设计,否则安装界面的样式就跟上个世纪的一样。在文件开头写入

1
2
# 引入现代化用户界面
!include "MUI2.nsh"

定义常用的一些变量,包含桌面快捷方式名称,主程序文件名,安装程序欢迎界面的程序名称。常量使用如下方式定义,在使用时使用 ${常量名称} 来引用。

1
2
3
4
5
# 常量定义
!define DESKTOP_SHORTCUT_NAME "TestProject.lnk"
!define MAIN_BIN_NAME "test_project.exe"
!define SERVER_JAR_NAME "demo-0.0.1-SNAPSHOT.jar"
!define INSTALLER_TITLE_NAME "测试程序"

定义我们的安装程序生成后放的位置,注意该位置是相对于你 nsi 脚本存放的位置。当然你也可以使用绝对路径或者仅写一个文件名,如果仅有文件名,那么打包输出的位置就是本脚本所在的位置同级。

1
Outfile "../../DemoInstaller.exe"  # NSIS 编译打包输出位置,相对于本脚本的位置

定义安装界面的一些名字和提示语

1
2
3
Caption "${INSTALLER_TITLE_NAME} Installer"  # 设置安装窗口标题
Name "${INSTALLER_TITLE_NAME}" # 安装界面欢迎标题中的程序名称
BrandingText "欢迎使用 ${INSTALLER_TITLE_NAME}" # 设置左下角灰色标语

配置关闭警告和安装程序的图标以及卸载程序的图标,这里的文件路径也是相对于本脚本的路径,也可以写绝对路径。图标必须是 Windows 使用的 .ico 文件,否则无效。

1
2
3
!define MUI_ABORTWARNING   # 关闭安装程序弹窗确认
!define MUI_ICON "..\icon.ico" # 设置安装程序图标
!define MUI_UNICON "..\icon.ico" # 设置卸载程序图标

设置程序的默认安装位置。这里的 $PROGRAMFILES 就是最常见的 C:\Program XXXX 的那个,后面可以自行拼接路径。和大多数安装程序一样,安装时会自动创建安装目录,如果目录不存在的话。

1
2
# 安装目录默认路径
InstallDir "$PROGRAMFILES\MyApp"

请求管理员权限,因为安装程序可以让用户自行选择安装位置,为了防止某些文件权限问题,请求管理员权限以正常写入磁盘文件。

1
2
# 请求管理员权限
RequestExecutionLevel admin

界面设置,NSIS 新版的安装界面都是模块化的,需要什么界面就插入什么界面。这里的 license 文件路径同上,都是相对于本脚本的位置。license 文件是必须的,需要事先准备好。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 安装器界面设置
!define MUI_PRODUCT_NAME "${APP_NAME}" # 设置产品名称
!insertmacro MUI_PAGE_WELCOME # 欢迎界面
!insertmacro MUI_PAGE_LICENSE "../../bin/license.txt" # 许可证界面,license.txt为你的许可证文件
!insertmacro MUI_PAGE_DIRECTORY # 选择安装目录界面
!insertmacro MUI_PAGE_INSTFILES # 安装进度界面
!insertmacro MUI_PAGE_FINISH # 完成界面

# 卸载界面设置
!insertmacro MUI_UNPAGE_WELCOME # 卸载欢迎界面
!insertmacro MUI_UNPAGE_CONFIRM # 卸载确认界面
!insertmacro MUI_UNPAGE_INSTFILES # 卸载进度界面
!insertmacro MUI_UNPAGE_FINISH # 卸载完成界面

# 设置语言为简体中文
!insertmacro MUI_LANGUAGE "SimpChinese"

主要部分,安装逻辑和卸载逻辑。本质上我们的程序二进制都是由编译器生成。附属的库文件什么的都是事先准备好的。NSIS 的打包动作等同于创建压缩文件。配置参考如下内容注释

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
# 定义安装的 Section
Section "Install"
# 创建目录 $INSTDIR 就是用户选择的安装目录。
# 注意 Windows 上的路径必须是 \ 间隔。
CreateDirectory "$INSTDIR\Resources"
CreateDirectory "$INSTDIR\Resources\jre"

# 设置文件输出路径,可以理解为切换工作目录。
# 以下两行意思是:安装时复制本机本脚本相对路径的 ../../bin/${MAIN_BIN_NAME} 文件到用户指定的安装目录
SetOutPath "$INSTDIR"
File "../../bin/${MAIN_BIN_NAME}" # 这里的路径为相对本脚本的路径

# 更换输出路径
SetOutPath "$INSTDIR\Resources"
File "../../bin/${SERVER_JAR_NAME}"

# 更换输出路径
# 复制 jre 整个文件夹,注意这里的复制是文件夹下的所有内容,并且是递归复制。
SetOutPath "$INSTDIR\Resources\jre"
File /r "../../bin/windows/jre/*.*"

# 创建桌面快捷方式,两个参数,第一个是跨界方式名称,第二个是你主程序的文件名。路径是 Windows 上的路径。
CreateShortcut "$DESKTOP\${DESKTOP_SHORTCUT_NAME}" "$INSTDIR\${MAIN_BIN_NAME}"

# 添加卸载程序,卸载程序名也是自己写的
WriteUninstaller "$INSTDIR\uninstaller.exe"

SectionEnd

# 卸载 Section
Section "Uninstall"

# 删除安装目录及其所有内容
RMDir /r "$INSTDIR"

# 删除桌面快捷方式
Delete "$DESKTOP\${DESKTOP_SHORTCUT_NAME}"

SectionEnd

开始编译

上述脚本准备好之后,执行命令。

1
makensis build/windows/installer/installer.nsi

注册表问题

通常来讲 Windows 上面安装的程序都可以在 控制面板 中卸载。这个功能需要在注册表中写入部分内容,且是约定的规范。本文创建的脚本,没有这块操作。所以安装完成后就是一个“绿色软件”。