使用NSIS工具在linux下自动构建生成windows安装包

目前手头的项目都是基于linux环境下搭建的开发框架,使用docker工具分别生成不同环境下的运行程序,现在需要将生成的运行程序文件自动构建打包生成对应操作系统环境下的安装包程序,这里介绍的是linux下打包生成windows安装包,linux版本是ubuntu22.04,使用的打包工具是NSIS

本章内容
  1. 安装NSIS工具
  2. 了解NSIS工具以及NSIS脚本
  3. 编写NSIS脚本
  4. 利用shell脚本自动输出生成NSIS脚本

1.安装NSIS工具

在命令行直接执行下载命令即可(这里是ubuntu系统,centos自己改成yum安装)

sudo apt-get install nsis

2.了解NSIS工具以及NSIS脚本

NSIS(Nullsoft Scriptable Install System)是一个开源的Windows系统下安装程序制作工具,由Nullsoft开发,该公司也是Winamp媒体播放器的创建者。NSIS的主要功能包括脚本化安装程序的创建,小巧且高度可定制,支持插件,并且是免费和开源的。

NSIS的主要特点是它使用自定义的脚本语言来描述安装程序的行为和界面,这使得开发人员可以根据他们的需求自定义安装过程。此外,NSIS生成的安装程序通常非常小巧,只包含必需的文件和组件,而且它提供了丰富的自定义选项,使开发人员能够创建符合其应用程序需求的安装界面。

NSIS脚本是一种有特定语法规则的规范语言,可以使用任何文本编辑器进行编辑,推荐使用带有行号和语法高亮的编辑器,这样更易于阅读和更新脚本。一个NSIS脚本通常包括Installer Attributes、Page、Sections和Functions等部分,其中OutFile指令是必备的,用于指明安装程序的输出文件。

通过编写NSIS脚本,开发人员可以控制安装程序的各个方面,如安装选项、文件复制、注册表操作等。同时,NSIS还支持插件,这意味着开发人员可以扩展其功能,如添加创建桌面快捷方式、注册文件关联等。

3.编写NSIS脚本

这里不深入教学,有感兴趣的或者不理解的可以搜索NSIS脚本编写的相关文章深入了解学习

下面看一个nsis脚本示例

; 示例NSIS脚本

; 包含MUI宏文件
!include "MUI2.nsh"

; 设置输出文件
Outfile "MyAppSetup.exe"

; 设置安装程序图标(可选)
; Icon "path\to\your\icon.ico"

; 设置安装程序名称
Name "MyApp_Installer"

; 设置安装程序版本信息
VIProductVersion "1.0.0.0"
VIAddVersionKey "ProductName" "MyApp"
VIAddVersionKey "FileDescription" "MyApp Installer"
VIAddVersionKey "FileVersion" "1.0.0.0"
VIAddVersionKey "LegalCopyright" "Your Company Name"

; 请求管理员权限运行
RequestExecutionLevel admin

; 设置默认安装目录
InstallDir "$PROGRAMFILES\MyApp"

; 页面设置
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH

; 语言设置
;!insertmacro MUI_LANGUAGE "English"

; 安装程序段
Section "Main Program" SecMain
    ; 设置该段的描述
    SectionIn RO

    ; 在这里添加你的安装逻辑
    ; 例如,复制文件到安装目录
    SetOutPath $INSTDIR
    File "/home/leo/Debug/TestNSIS.exe"
    File "/home/leo/Debug/TestNSIS.ilk"
    File "/home/leo/Debug/TestNSIS.pdb"
    File "/home/leo/Debug/readme.txt"

    ; 创建快捷方式(可选)
    ; CreateShortCut "$DESKTOP\MyApp.lnk" "$INSTDIR\file.exe"
    CreateShortCut "$DESKTOP\MyApp.lnk" "$INSTDIR\TestNSIS.exe" "" "$INSTDIR\TestNSIS.exe" 0 SW_SHOWNORMAL

    ; 写入卸载信息到注册表(如果需要的话)
    ; WriteRegStr HKLM "Software\YourCompany\MyApp" "UninstallString" '"$INSTDIR\uninst.exe"'

SectionEnd

; 卸载程序段
Section "Uninstall"
    ; 设置该段的描述
    SectionIn RO

    ; 在这里添加你的卸载逻辑
    ; 例如,删除文件和目录
    Delete "$INSTDIR\TestNSIS.exe"

    ; 删除快捷方式(如果创建了的话)
    ; Delete "$DESKTOP\MyApp.lnk"

    ; 从注册表中删除卸载信息(如果写入了的话)
    ; DeleteRegKey HKLM "Software\YourCompany\MyApp"

    ; 删除安装目录(如果为空的话)
    ; RMDir /r "$INSTDIR"

SectionEnd

; 函数:.onInit
Function .onInit
    ; 检查是否已经安装过,如果是则退出安装程序
    ; 可以通过检查注册表或其他方式来实现
FunctionEnd

; 函数:un.onInit
Function un.onInit
    ; 卸载时的初始化操作,例如停止服务、关闭应用程序等
FunctionEnd

 可以根据自己的目录和文件替换修改脚本中的参数,测试生成安装文件,比如上面这个示例代码,只需要修改这一段

    SetOutPath $INSTDIR
    File "/home/leo/Debug/TestNSIS.exe"
    File "/home/leo/Debug/TestNSIS.ilk"
    File "/home/leo/Debug/TestNSIS.pdb"
    File "/home/leo/Debug/readme.txt"

 将 File 后的路径替换为自己需要测试打包的执行文件以及相关依赖即可(第一次测试建议测试程序越简单,相关依赖越少越好)

在命令行执行以下命令,test.nsi就是刚才编辑的nsis脚本

makensis test.nsi

执行成功会生成一个安装包程序exe,名称就是在nsis脚本中指定的这个

; 设置输出文件
Outfile "MyAppSetup.exe"

4.利用shell脚本自动输出生成NSIS脚本

关于为什么要单独用一个shell文件来生成NSIS脚本,主要原因是shell脚本的语法和逻辑比NSIS更简单,方便控制NSIS脚本中的各个变量输入。我们只需要在shell脚本中替换对应变量,然后直接生成输出NSIS脚本代码到文件即可

以下是shell脚本内容示例

#!/bin/bash  

  
# 检查参数数量  
if [ "$#" -ne 7 ]; then  

    echo "Usage: $0  <source_dir> <installer_name> <installer_output> <install_dir> <shortcut_pathname> <app_version> <output_file> "  
    exit 1  
fi  

  
# 定义变量  # 获取参数

SOURCE_DIR="$1"				#源路径/安装文件源目录
INSTALLER_NAME="$2"	#"My_Installer"  #源程序名
INSTALLER_OUTPUT="$3"   #"myInstaller.exe" 	#安装程序输出文件(安装包exe) 
INSTALL_DIR="$4"  #"\$PROGRAMFILES\MyInstaller"  #默认安装目录
SHORTCUT_PATHNAME="\$INSTDIR\\$5"		#快捷方式指向的文件路径 全称
APP_VERSION="$6"		#"1.0.0.0"	#版本号
OUTPUT_FILE="$7"	#"Installer.nsi" 	#输出的nsis脚本名 

# 清空或创建NSIS脚本文件  

> "$OUTPUT_FILE"  


# 写入NSIS脚本头部  

echo "" >> "$OUTPUT_FILE"  

echo "; 包含MUI宏文件" >> "$OUTPUT_FILE"  
echo "!include MUI2.nsh" >> "$OUTPUT_FILE"  
echo "" >> "$OUTPUT_FILE"  

echo "; 设置安装程序图标(可选)" >> "$OUTPUT_FILE"
#echo "Icon \"path\to\your\icon.ico\"" >> "$OUTPUT_FILE" 
echo "" >> "$OUTPUT_FILE"  

echo "; 设置输出文件" >> "$OUTPUT_FILE"  
echo "OutFile \"$INSTALLER_OUTPUT\"" >> "$OUTPUT_FILE"  
echo "" >> "$OUTPUT_FILE"  

echo "; 设置安装程序名称" >> "$OUTPUT_FILE" 
echo "Name \"$INSTALLER_NAME\"" >> "$OUTPUT_FILE"  
echo "" >> "$OUTPUT_FILE"  

echo "; 设置安装程序版本信息" >> "$OUTPUT_FILE" 
echo "VIProductVersion \"$APP_VERSION\"" >> "$OUTPUT_FILE"  
echo "" >> "$OUTPUT_FILE"  

echo "; 请求管理员权限运行" >> "$OUTPUT_FILE" 
echo "RequestExecutionLevel admin" >> "$OUTPUT_FILE"  
echo "" >> "$OUTPUT_FILE"  

echo "; 设置默认安装目录" >> "$OUTPUT_FILE" 
echo "InstallDir \"$INSTALL_DIR\"" >> "$OUTPUT_FILE"  
echo "" >> "$OUTPUT_FILE" 

echo "; 页面设置" >> "$OUTPUT_FILE" 
echo "!insertmacro MUI_PAGE_DIRECTORY" >> "$OUTPUT_FILE"  
echo "!insertmacro MUI_PAGE_INSTFILES" >> "$OUTPUT_FILE"  
echo "!insertmacro MUI_PAGE_FINISH" >> "$OUTPUT_FILE"  
echo "" >> "$OUTPUT_FILE" 

echo "; 语言设置" >> "$OUTPUT_FILE" 
echo "!insertmacro MUI_LANGUAGE \"SimpChinese\"" >> "$OUTPUT_FILE"  
echo "" >> "$OUTPUT_FILE"  


echo "; 安装程序段" >> "$OUTPUT_FILE" 
echo "Section \"Main Program\" SecMain" >> "$OUTPUT_FILE" 
echo "    SectionIn RO" >> "$OUTPUT_FILE" 
#echo "    SetOutPath \$INSTDIR" >> "$OUTPUT_FILE"
echo "    ; 添加安装文件" >> "$OUTPUT_FILE" 

last_dir="\$INSTDIR"

# 递归函数,用于添加目录和文件到NSIS脚本  
function add_to_nsis() {  
    local dir="$1"  
    local parent_dir="$2"
    local rel_path=${dir#$SOURCE_DIR}  # 去除源目录前缀  
    rel_path=${rel_path//\//\\}          # 将"/"替换为"\"  
    rel_path="${rel_path%/}"             # 去除尾部的反斜杠(如果是目录的话)
    local outdir=\$INSTDIR$rel_path
    
    # 如果是目录,则创建目录并递归添加子目录和文件  
    if [ -d "$dir" ]; then     	
        # 检查是否是根目录  
        #if [ "$base_dir" != "" ]; then      
            # 如果不是根目录,则添加CreateDirectory指令  
            #echo "    CreateDirectory $outdir$rel_path" >> "$OUTPUT_FILE"             
        #fi  
        echo "    SetOutPath $outdir" >> "$OUTPUT_FILE"
        last_dir=$outdir
        
        # 递归添加子目录和文件  
        for item in "$dir"/*; do  
            add_to_nsis "$item" "$outdir"
        done  
	
	if [ "$parent_dir" != "$last_dir" ];then
	    echo "    SetOutPath $parent_dir" >> "$OUTPUT_FILE"
	    last_dir=$parent_dir
	fi
    # 如果是文件,则添加文件  
    elif [ -f "$dir" ]; then  
        # 使用绝对路径添加文件,NSIS 将处理路径问题  
        echo "File \"$dir\"" >> "$OUTPUT_FILE"  
    fi    
}  



# 从源目录开始递归处理  
add_to_nsis "$SOURCE_DIR" "\$INSTDIR"


echo "" >> "$OUTPUT_FILE" 

echo "    ; 创建快捷方式(可选)" >> "$OUTPUT_FILE" 
echo "    CreateShortCut \"\$DESKTOP\\$INSTALLER_NAME.lnk\" \"$SHORTCUT_PATHNAME\" \"\" \"$SHORTCUT_PATHNAME\" 0 SW_SHOWNORMAL" >> "$OUTPUT_FILE"
echo "    ; 写入卸载信息到注册表(如果需要的话)" >> "$OUTPUT_FILE" 
echo "    ; WriteRegStr HKLM \"Software\YourCompany\MyApp\" \"UninstallString\" \"$INSTDIR\uninst.exe\"" >> "$OUTPUT_FILE" 
echo "SectionEnd" >> "$OUTPUT_FILE" 
echo "" >> "$OUTPUT_FILE"  

echo "; 卸载程序段" >> "$OUTPUT_FILE" 
echo "Section \"Uninstall\"" >> "$OUTPUT_FILE" 
echo "    ; 设置该段的描述" >> "$OUTPUT_FILE" 
echo "    SectionIn RO" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE" 
echo "    ; 在这里添加你的卸载逻辑" >> "$OUTPUT_FILE" 
echo "" >> "$OUTPUT_FILE"
echo "    ; 例如,删除文件和目录" >> "$OUTPUT_FILE"
echo "    Delete \"\$INSTDIR\\$INSTALLER_OUTPUT\"" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
echo "    ; 删除快捷方式(如果创建了的话)" >> "$OUTPUT_FILE"
echo "    ; Delete \"$DESKTOP\MyApp.lnk\"" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
echo "    ; 从注册表中删除卸载信息(如果写入了的话)" >> "$OUTPUT_FILE"
echo "    ; DeleteRegKey HKLM \"Software\YourCompany\MyApp\"" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
echo "    ; 删除安装目录(如果为空的话)" >> "$OUTPUT_FILE"
echo "    ; RMDir /r \"$INSTDIR\"" >> "$OUTPUT_FILE"
echo "SectionEnd" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"

echo "Function .onInit" >> "$OUTPUT_FILE"
echo "    ; 检查是否已经安装过,如果是则退出安装程序" >> "$OUTPUT_FILE"  
echo "    ; 可以通过检查注册表或其他方式来实现" >> "$OUTPUT_FILE"  
echo "FunctionEnd" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"

echo "Function un.onInit" >> "$OUTPUT_FILE"
echo "    ; 卸载时的初始化操作,例如停止服务、关闭应用程序等" >> "$OUTPUT_FILE"
echo "FunctionEnd" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"  
 
# 完成NSIS脚本  

 首先读取输入参数,包含了源文件目录、程序名、版本号等等,接着一行行向nsis脚本中输出代码内容,后续对NSIS脚本内容的修改和编辑都是在这里控制处理,每一个echo语句都会输出指定内容到NSIS脚本文件中

整体的逻辑很好理解,基本和nsis脚本保持一致,有一个地方需要提一下,就是关于add_to_nsis() 这个函数,主要的作用是递归读取指定的目录,将文件按照读取的结构写入nsis脚本中,保证生成安装包时,所有的文件和目录可以维持原有的结构,对应的就是上面例子里 File 后面对应的部分,只不过那里只有文件,这里增加了目录的概念。

在执行这个脚本时,需要输入参数,用于指定安装程序的相关属性,即脚本开头那里读取的参数内容。

bash ./makeNSIS.sh "/home/leo/" "MyApp" "Installer.exe"  "\$PROGRAMFILES\Installer" "MyApp.exe" "1.0.0.0" "Installer.nsi" 

 这是输出的NSIS脚本示例


; 包含MUI宏文件
!include MUI2.nsh

; 设置安装程序图标(可选)

; 设置输出文件
OutFile "Installer.exe"

; 设置安装程序名称
Name "MyApp"

; 设置安装程序版本信息
VIProductVersion "1.0.0.0"

; 请求管理员权限运行
RequestExecutionLevel admin

; 设置默认安装目录
InstallDir "$PROGRAMFILES\Installer"

; 页面设置
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH

; 语言设置
!insertmacro MUI_LANGUAGE "SimpChinese"

; 安装程序段
Section "Main Program" SecMain
    SectionIn RO
    ; 添加安装文件
    SetOutPath $INSTDIR
    File "/home/leo/NSIS_example/example3/testDir/license.dat"
    File "/home/leo/NSIS_example/example3/testDir/MyApp.exe"
    SetOutPath $INSTDIR\qt-win64
    SetOutPath $INSTDIR\qt-win64\lib
    File "/home/leo/NSIS_example/example3/testDir/qt-win64/lib/Qt5Bluetooth.dll"
    SetOutPath $INSTDIR\qt-win64
    SetOutPath $INSTDIR\qt-win64\plugins
    SetOutPath $INSTDIR\qt-win64\plugins\audio
    File "/home/leo/NSIS_example/example3/testDir/qt-win64/plugins/audio/qtaudio_windows.dll"
    SetOutPath $INSTDIR\qt-win64\plugins
    SetOutPath $INSTDIR\qt-win64\plugins\bearer
    File "/home/leo/NSIS_example/example3/testDir/qt-win64/plugins/bearer/qgenericbearer.dll"
    SetOutPath $INSTDIR\qt-win64\plugins
    SetOutPath $INSTDIR\qt-win64
    SetOutPath $INSTDIR

    ; 创建快捷方式(可选)
    CreateShortCut "$DESKTOP\MyApp.lnk" "$INSTDIR\MyApp.exe" "" "$INSTDIR\MyApp.exe" 0 SW_SHOWNORMAL
    ; 写入卸载信息到注册表(如果需要的话)
    ; WriteRegStr HKLM "Software\YourCompany\MyApp" "UninstallString" "\uninst.exe"
SectionEnd

; 卸载程序段
Section "Uninstall"
    ; 设置该段的描述
    SectionIn RO

    ; 在这里添加你的卸载逻辑

    ; 例如,删除文件和目录
    Delete "$INSTDIR\Installer.exe"

    ; 删除快捷方式(如果创建了的话)
    ; Delete "\MyApp.lnk"

    ; 从注册表中删除卸载信息(如果写入了的话)
    ; DeleteRegKey HKLM "Software\YourCompany\MyApp"

    ; 删除安装目录(如果为空的话)
    ; RMDir /r ""
SectionEnd

Function .onInit
    ; 检查是否已经安装过,如果是则退出安装程序
    ; 可以通过检查注册表或其他方式来实现
FunctionEnd

Function un.onInit
    ; 卸载时的初始化操作,例如停止服务、关闭应用程序等
FunctionEnd

将整个打包过程结合到项目里,需要把这段执行逻辑加到项目整体的构建流程中,示例如下

#!/bin/bash


# 编译你的程序,生成执行文件和相关依赖
#...
#...
#...

#指定nsis生成脚本相关输入
NSIS_ARG_1="/home/leo"	#源路径/安装文件源目录
NSIS_ARG_2="MyApp"	#源程序名
NSIS_ARG_3="Installer.exe"	#安装程序输出文件(安装包exe)
NSIS_ARG_4="\$PROGRAMFILES\Installer"	#默认安装目录
NSIS_ARG_5="MyApp.exe"	 #快捷方式指向的文件基于NSIS_ARG_1的相对路径及文件名	
NSIS_ARG_6="1.0.0.0"	#版本号
NSIS_ARG_7="Installer.nsi"		#输出的nsis脚本名

# 调用shell生成NSIS脚本
bash ./makeNSIS.sh $NSIS_ARG_1 $NSIS_ARG_2 $NSIS_ARG_3  $NSIS_ARG_4 $NSIS_ARG_5 $NSIS_ARG_6 $NSIS_ARG_7 
# 调用NSIS脚本生成安装包
makensis ./$NSIS_ARG_7

# 结束构建脚本
exit 0

 在主流程脚本中,编译生成执行文件和依赖,指定好相关参数变量,执行指定shell脚本生成NSIS脚本文件,然后再执行生成的NSIS脚本生成对应的安装包程序,到此就实现了整个流程的自动化构建

  • 18
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
NSIS 是“Nullsoft 脚本安装系统”(Nullsoft Scriptable Installation System) 的缩写,它是一个Open Source的Windows系统下安装程序制作程序。它提供了安装、卸载、系统设置、文件解压缩等功能。NSIS通过它的脚本语言来描述安装程序的行为和逻辑的,因为它基于脚本文件,所以你可以完全控制你的安装程序的每个部分。它的脚本语言支持变量、函数、字串处理,就像是一个普通的程序语言——但它是为安装程序这类应用所设计的。 此增强版除了主程序的翻译之外还把主要的文档作了翻译并修正了官方版本里简体中文语言习惯用语不合适之处。 单纯的使用脚本来编写安装程序对于大多数人来说不仅困难而且容易出错,为此,增强版里集成了一个相当好用的脚本编辑器 – VNISEdit。只需要根据向导就能轻松的做出很酷的安装程序,甚至,你还可以在向导里给你的安装程序添加启动画面、让你的安装程序在安装过程中播放音乐,而这,只需要点几下鼠标即可。除此之外,VNISEdit 附带的注册表转换插件还可以把 .reg 文件一次性的转换为 NSIS 脚本。 此增强版还在官方版本的基础上集成了一些有用的插件。由于各个组件在使用时各自独立,所以强烈推荐安装全部组件。 NSIS 特点: 开销小,一个完整功能的安装程序仅需要34k的额外开销。 支持大多数Windows平台,包括:Windows 9.x、Windows NT、Windows 2000、Windows XP、Windows 2003、Windows 7。 支持三大压缩算法: Zlig、BZips、LZMA。 支持脚本。 支持多语言。 支持安装界面定制。 提供可扩展的插件接口。 支持网络安装、补丁。 支持无人值守的安装模式。 此外,NSIS的license允许任何用途免费使用NSIS 增强: 此版本主要进行了以下增强: 1、集成了网络上能够收集到的大部分插件及应用示例; 2、集成了 VNISEdit v2.03(.nsi默认)和 NotePad2 两个脚本编辑器(.nsi右键); 3、集成了 NSISDialogDesigner自定义页面设计工具; 4、集成了 NSIS用户手册和 NSIS图文教程集锦。
通用自动更新NSIS安装包程序 检查本地的配置版本与服务器配置的版本, 如果服务器比较新则进行下载并更新文件. 注意: 需要结合NSIS安装包进行安装. 升级时采用/S静默安装方式进行安装. 配置中, "name"属性指定的应用程序, 将最后被安装. 程序目前只支持更新一个主程序和一个插件程序, 其他功能自行完善 带源码, 带完整配置文件, 各项主要设置均可通过配置文件修改, 并包含程序逻辑简要描述说明文件. 功能不复杂, 主要是不想重复开发. 7. 程序逻辑: a. CommonAutoUpdate启动后, 将检查和加载本地配置文件, 加载成功后, 将判断"run"中指定的程序是否正在运行. 如果在运行, 则给出错误提示后, 退出更新程序; b. 如果"run"中的程序没有在运行, 则根据svrurl + "/commonAutoUpdate.xml" 地址, 加载服务器上的配置文件; c. 在加载配置文件过程中, 任何的异常, 均会提示"检查自动更新失败, 请稍后再试", 并退出; (不会启动"run"中配置的文件) d. 如果加载成功, 则会对比本地"version"中的版本号与服务器"cv"节点中的"v"属性的版本号; e. 如果服务器版本号小于或等于本地版本号, 则不进行更新, 直接运行"run"中指定的程序, 并传递"cau"参数作为标记; f. 如果服务器版本号大于本地版本号, 则会显示提示更新的界面, 在点击确定按钮后, 开始下载服务器"cv"节点中的"p"属性指定的文件; g. 待下载完成, 则会退出, 并运行下载的安装包进行安装.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值