NSIS : 一个windows上开源安装包制作脚本工具,一次编写,随时编译。
今天分享一个自己写成的打包脚本的源码,仅供参考。
一、示例
1. 先上编译脚本
; 此脚本文件用于NSIS自动生成安装包程序 created at 2022-3-2 by jeady
; 此脚本一般不做修改,只需要在配套的nsh配置文件中修改相关项即可
; 导入配置文件,命令相关头文件
!include config.nsh
!include "FileFunc.nsh"
!include "WordFunc.nsh"
; 定义一些可选常量
!define PRODUCT_PUBLISHER "my compony"
!define PRODUCT_WEB_SITE "http://www.xxx.com.cn/"
!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\${PRODUCT_NAME}"
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
!define PRODUCT_ROOT_KEY "HKLM"
SetCompressor lzma
!include "MUI.nsh"
; MUI 预定义常量
!define MUI_ABORTWARNING
!define MUI_ICON "${INSTALLER_ICON}"
!define MUI_UNICON "${INSTALLER_ICON}"
!define MUI_LANGDLL_REGISTRY_ROOT "${PRODUCT_ROOT_KEY}"
!define MUI_LANGDLL_REGISTRY_KEY "${PRODUCT_UNINST_KEY}"
!define MUI_LANGDLL_REGISTRY_VALUENAME "NSIS:Language"
; 欢迎页面, 如果需要,可将以下两行取消注释;
; !define MUI_WELCOMEPAGE_TEXT ${
UPDATE_LOG}
; !insertmacro MUI_PAGE_WELCOME
; 许可协议页面; 如有需要可取消注释
; !define MUI_LICENSEPAGE_CHECKBOX
; !define MUI_LICENSEPAGE_TEXT_TOP "程序更新日志"
; !insertmacro MUI_PAGE_LICENSE "${EXEC_APP_DIR}\license.txt"
; 组件选择页面; 如需要可自定义
; Page components
; 安装目录选择页面;如不需要,可以注释掉 / 执行静默安装模式
!define MUI_DIRECTORYPAGE_TEXT_TOP "安装程序将把 ${INSTALLER_NAME} ${PRODUCT_VERSION} 安装到以下目录。请不要更换安装目录。点击[安装(I)]开始安装。"
!insertmacro MUI_PAGE_DIRECTORY
; 安装过程页面
!insertmacro MUI_PAGE_INSTFILES
; 安装完成页面; 如不要可以注释掉
; 添加是否显示更新日志选项
!define MUI_FINISHPAGE_SHOWREADME $INSTDIR\${
README_FILE}
!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED
!define MUI_FINISHPAGE_SHOWREADME_TEXT "显示软件更新日志"
; 添加启动选项
!define MUI_FINISHPAGE_RUN $INSTDIR\${
EXEC_APP_NAME}
!insertmacro MUI_PAGE_FINISH
; 安装卸载过程页面
!insertmacro MUI_UNPAGE_INSTFILES
; 安装界面包含的语言设置
!insertmacro MUI_LANGUAGE "SimpChinese"
; 安装预释放文件
!insertmacro MUI_RESERVEFILE_LANGDLL
!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
; ------ MUI 现代界面定义结束 ------
; 安装界面的标题文本
Name "${DISPLAY_NAME} ${PRODUCT_VERSION}"
; 最终输出的安装包的名称
OutFile "${INSTALLER_NAME}_${PRODUCT_VERSION}-${UPDATE_LOG}.exe"
; 默认的安装路径
InstallDir "${DEFAULT_INSTALL_PATH}"
; 卸载信息要写入的注册表路径
InstallDirRegKey HKLM "${PRODUCT_UNINST_KEY}" "UninstallString"
; 是否执行静默安装,即不显示安装界面
SilentInstall ${
INSTALL_TYPE}
; 展示安装细节
ShowInstDetails show
; 展示卸载细节
ShowUnInstDetails show
; 展示在安装界面上的公司名称
BrandingText "我的公司名称"
; 提供三种备份方式,复制,移动,压缩(依赖于`7za.exe`)
Section -bakSection
SetOutPath "$TEMP"
; 该文件是执行压缩解压的文件, 用于压缩备份源文件,可以取消掉; 如有需要也可以手动搜索下载,放到此文件同目录下
File "7za.exe"
${
GetTime} "" "L" $0 $1 $2 $3 $4 $5 $6
DetailPrint '安装日期为 $2/$1/$0 $4:$5:$6'
StrCmp ${
NEED_BAK} "true" 0 bakdone
StrCmp ${
BAK_TYPE} "compress" compress 0
StrCmp ${
BAK_TYPE} "copy" 0 move
CopyFiles $INSTDIR\* "$INSTDIR\..\${BAK_DIR}-$2$1$0t$4$5$6z"
Goto bakdone
move:
Rename "$INSTDIR\" "$INSTDIR\..\${
BAK_DIR}-$2$1$0t$4$5$6z"
Goto bakdone
compress:
ExecWait '$TEMP\7za.exe a "$INSTDIR\..\${BAK_DIR}-$2$1$0t$4$5$6z.7z" $INSTDIR'
bakdone:
SectionEnd
Var isNewer ; 0 相同版本 1 已装新版 2 此为新版
; 在
Section MainSection
; 设置安装包的释放目录,即安装路径
SetOutPath "$INSTDIR"
${
If} $isNewer == 2
SetOverwrite ifnewer
DetailPrint "Set overwrite ifnewer"
${
Else}
SetOverwrite ifdiff
DetailPrint "Set overwrite ifdiff"
${
EndIf}
File /r "${EXEC_APP_DIR}\*"
CreateDirectory "$SMPROGRAMS\${DISPLAY_NAME}"
CreateShortCut "$SMPROGRAMS\${DISPLAY_NAME}\${DISPLAY_NAME}.lnk" "$INSTDIR\${EXEC_APP_NAME}"
CreateShortCut "$DESKTOP\${DISPLAY_NAME}.lnk" "$INSTDIR\${EXEC_APP_NAME}"
StrCmp ${
BOOT_START} 'true' 0 +2
CreateShortCut "$SMSTARTUP\${DISPLAY_NAME}.lnk" "$INSTDIR\${EXEC_APP_NAME}"
SectionEnd
; 添加卸载程序,添加网站信息
Section -AdditionalInfo
WriteUninstaller "$INSTDIR\uninst.exe"
CreateShortCut "$SMPROGRAMS\${DISPLAY_NAME}\Uninstall.lnk" "$INSTDIR\uninst.exe"
StrCmp ${
GENERATE_WEBSITE} "true" 0 +3
WriteIniStr "$INSTDIR\${PRODUCT_PUBLISHER}.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}"
CreateShortCut "$SMPROGRAMS\${DISPLAY_NAME}\Website.lnk" "$INSTDIR\${PRODUCT_PUBLISHER}.url"
SectionEnd
; 添加软件相关信息记录到注册表
Section -writeReg
WriteRegStr ${
PRODUCT_ROOT_KEY} "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\${EXEC_APP_NAME}"
WriteRegStr ${
PRODUCT_ROOT_KEY} "${PRODUCT_DIR_REGKEY}" "updateLog" "${UPDATE_LOG}"
WriteRegStr ${
PRODUCT_ROOT_KEY} "${PRODUCT_DIR_REGKEY}" "installerName" "${INSTALLER_NAME}Update_${PRODUCT_VERSION}-${UPDATE_LOG}"
WriteRegStr ${
PRODUCT_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "${DISPLAY_NAME}"
WriteRegStr ${
PRODUCT_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
WriteRegStr ${
PRODUCT_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\uninst.exe"
WriteRegStr ${
PRODUCT_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
WriteRegStr ${
PRODUCT_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
WriteRegStr ${
PRODUCT_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
CALL rebootDialog
SectionEnd
Function checkVersion
Var /GLOBAL lastVersion
ReadRegStr $lastVersion HKLM "${PRODUCT_UNINST_KEY}" "DisplayVersion"
${
VersionCompare} "$lastVersion" "${PRODUCT_VERSION}" $0
${
Switch} $0
${
Case} 0
MessageBox MB_YESNO "当前版本已经安装了, 是否停止安装?" IDNO continue1
Quit
continue1:
StrCpy $isNewer 0
Goto finishcheck
${
Case} 1
MessageBox MB_YESNO "已安装了新的版本 $lastVersion,是否停止当前版本的安装?" IDNO continue2
Quit
continue2:
StrCpy $isNewer 1
Goto finishcheck
${
Case} 2
StrCpy $isNewer 2
${
EndSwitch}
finishcheck:
FunctionEnd
; 提示重启的函数
Function rebootDialog
StrCmp ${
NEED_REBOOT} "true" 0 ret
MessageBox MB_YESNO "是否立即重启" IDNO ret
Reboot
ret:
DetailPrint "安装完成"
FunctionEnd
; 初始化;检测目标程序是否正在运行
Function .onInit
; 检查版本信息
Call checkVersion
; 检查进程是否在运行
NsProcessW::_FindProcess "${PRODUCT_NAME}.exe"
Pop $R0
IntCmp $R0 0 0 done done
MessageBox MB_ICONQUESTION|MB_YESNO "安装程序检测到 ${DISPLAY_NAME} 正在运行,是否自动关闭后继续安装?" IDYES done IDNO 0
Abort
done:
NsProcessW::_KillProcess "${PRODUCT_NAME}.exe"
FunctionEnd
Function .onInstSuccess
StrCmp ${
USER_DEFINED_CMD} "null" doneInst 0
Exec "${USER_DEFINED_CMD}"
doneInst:
${
If} ${
INSTALL_TYPE} == "silent"
Exec "$INSTDIR\${EXEC_APP_NAME}"
${
EndIf}
FunctionEnd
/******************************
* 以下是安装程序的卸载部分 *
******************************/
Section Uninstall
; 删除安装目录、开始菜单及桌面快捷方式
RMDir /r /REBOOTOK "$INSTDIR"
RMDir /r /REBOOTOK "$SMPROGRAMS\${DISPLAY_NAME}"
Delete "$DESKTOP\${DISPLAY_NAME}.lnk"
; 删除相关注册表项
DeleteRegKey ${
PRODUCT_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}"
SetAutoClose true
SectionEnd
Function un.onInit
!insertmacro MUI_UNGETLANGUAGE
MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "您确实要完全移除 ${DISPLAY_NAME} ${PRODUCT_VERSION} 及其所有的组件?" IDYES +2
Abort
FunctionEnd
Function un.onUninstSuccess
HideWindow
MessageBox MB_ICONINFORMATION|MB_OK "${DISPLAY_NAME} ${PRODUCT_VERSION} 已成功地从您的计算机移除。"
FunctionEnd
2. 对应的配置文件
# 本配置文件/nsis头文件用于NSIS自动生成安装包程序 created at 2022-2-15 by jeady
; 源程序信息
!define EXEC_APP_DIR ".\MyApp" ; 要打包的目录,执行文件前应删除目录下的非必需文件,如日志等
!define EXEC_APP_NAME "startApp.exe" ; 可执行程序相对于打包目录的路经
!define PRODUCT_VERSION "v1.0.0.release" ; 应用程序的版本号
!define UPDATE_LOG "测试打包用的可执行文件" ; 本次更新的简要描述
; 安装目标信息
!define DEFAULT_INSTALL_PATH "D:\MyApp" ; 默认安装目录; 字符串最后不带反斜杠
!define PRODUCT_NAME "MyAppName" ; 可运行程序的的名字; 将用于注册表和进程检测
!define DISPLAY_NAME "打包测试程序" ; 开始菜单中/桌面快捷方式/开机启动项要显示的名字
!define README_FILE "UpdateLog.txt" ; 安装完成后要显示的更新日志
; 备份信息
!define NEED_BAK "false" ; 是否需要安装程序执行备份
!define BAK_DIR "MyApp-bak" ; 程序安装前的备份目录,该目录与安装目录在相同文件夹;执行时会自动添加时间戳
!define BAK_TYPE "copy" ; 可选备份模式, 拷贝copy, 移动move, 压缩compress
; 安装包文件信息
!define INSTALLER_NAME "MyAppInstaller" ; 安装包的前缀名字
!define INSTALLER_ICON ".\logo.ico" ; 安装包的图标; 如需替换,请修改文件路径
; 其他选项
!define BOOT_START "true" ; 是否创建软件开机自启动链接
!define INSTALL_TYPE "normal" ; 安装方式 normal | silent
!define NEED_REBOOT "false" ; 安装完成后是否需要提示重新启动计算机
!define GENERATE_WEBSITE "false" ; 安装目录下是否创建公司官网链接
!define USER_DEFINED_CMD "null" ; 安装完成后要执行的自定义指令,不执行则为空null
二、其他
1. 备份时如果需要排除文件夹,可以使用windows自带的xcopy
命令, 如下示例所示
Var /GLOBAL exclude_file
FileOpen $exclude_file "$TEMP\exclude.txt" w
FileWrite $exclude_file "node_modules$\r$\nlogs$\r$\ndata$\r$\n/.git$\r$\n.rar$\r$\n.7z$\r$\n.zip"
FileClose $exclude_file
ExecWait 'xcopy $INSTDIR "$INSTDIR\..\${BAK_DIR}-$2-$1-$0 $4.$5.$6\" /e /y /exclude:$TEMP\exclude.txt'
2. 如果需要执行pm2命令,请执行nsis的ExecWaite
命令,如:
ExecShellWait "" "pm2" "restart all"