【源码】编写的NSIS脚本示例分享

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"

猜你喜欢

转载自blog.csdn.net/downanddusk/article/details/126164601