最近工作中遇到一个需要打包程序的任务,学习了下NSIS和XML插件的使用,解决了工作中遇到的需要多组件可选安装和配置XML文件的问题。

基本的知识就不介绍了,可以去看NSIS的文档,我就把写的代码来出来分享下,供大家参考下。



;安装可选,卸载全部

; 导入插件

!include MUI.nsh

!include nsDialogs.nsh

!include LogicLib.nsh

!include xml.nsh



; 安装程序初始定义常量

!define PRODUCT_NAME "通用模块"

!define PRODUCT_VERSION "1.0"

!define PRODUCT_PUBLISHER "科技有限公司"

!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"

!define PRODUCT_UNINST_ROOT_KEY "HKLM"


SetCompressor lzma

XPStyle on


; MUI 预定义常量

!define MUI_ABORTWARNING

!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\arrow2-install.ico"

!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\arrow2-uninstall.ico"

BrandingText "科技有限公司"


;定义变量

Var Dialog

Var Label

Var  ip

Var  port

Var  sid

Var  isConfig


; 欢迎页面

!insertmacro MUI_PAGE_WELCOME

; 许可协议页面

!insertmacro MUI_PAGE_LICENSE "安装说明.txt"

; 组件选择页面

!insertmacro MUI_PAGE_COMPONENTS

; 安装目录选择页面

!insertmacro MUI_PAGE_DIRECTORY

; 安装过程页面

!insertmacro MUI_PAGE_INSTFILES

;调用数据库基本配置页面

Page custom ConfigDBPage

;调用数据导入配置页面

;Page custom impPage

;调用数据库导入程序

;Page custom executeImp

Page instfiles


; 安装完成页面

!insertmacro MUI_PAGE_FINISH


; 卸载欢迎页面

!insertmacro MUI_UNPAGE_WELCOME

; 卸载组件选择页面

;!insertmacro MUI_UNPAGE_COMPONENTS

; 卸载过程页面

!insertmacro MUI_UNPAGE_INSTFILES

; 卸载完成页面

!insertmacro MUI_UNPAGE_FINISH


; 安装界面包含的语言设置

!insertmacro MUI_LANGUAGE "SimpChinese"


; 安装预释放文件

!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS

; ------ MUI 现代界面定义结束 ------


Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"

OutFile "模块SetUp.exe"

InstallDir "$PROGRAMFILES\company\模块"

InstallDirRegKey HKLM "${PRODUCT_UNINST_KEY}" "UninstallString"

ShowInstDetails show

ShowUnInstDetails show


Section "模块1" SEC01

 SetOutPath "$INSTDIR\msgServer"

 SetOverwrite ifnewer

 File /r "E:\模块\MsgServer\msgServer\*.*"

SectionEnd


Section "模块2" SEC02

 SetOutPath "$INSTDIR\alarmReceiver"

 SetOverwrite ifnewer

 File /r "E:\模块\AlarmReceiver\adapter_alarmReceiver\*.*"

 StrCpy $isConfig "1"

SectionEnd


Section "模块3" SEC03

 SetOutPath "$INSTDIR\pref_receiver\"

 SetOverwrite ifnewer

 File /r "E:\模块\PrefReceiver\sdh_pref_receiver\*.*"

 StrCpy $isConfig "1"

SectionEnd


Section "模块4" SEC04

 SetOutPath "$INSTDIR\sysmonitor\"

 SetOverwrite ifnewer

 File /r "E:\模块\SysMonitor\sysmonitor\*.*"

 StrCpy $isConfig "1"

SectionEnd



Section -Post

 ;调用配置函数

 Call configXML

 WriteUninstaller "$INSTDIR\uninst.exe"

 WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"

 WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"

 WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"

 WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"

SectionEnd


#-- 根据 NSIS 脚本编辑规则,所有 Function 区段必须放置在 Section 区段之后编写,以避免安装程序出现未可预知的问题。--#


; 区段组件描述

!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN

 !insertmacro MUI_DESCRIPTION_TEXT ${SEC01} "模块1"

 !insertmacro MUI_DESCRIPTION_TEXT ${SEC02} "模块2"

 !insertmacro MUI_DESCRIPTION_TEXT ${SEC03} "模块3"

 !insertmacro MUI_DESCRIPTION_TEXT ${SEC04} "模块4"


!insertmacro MUI_FUNCTION_DESCRIPTION_END


/******************************

*  以下是安装程序的卸载部分  *

******************************/

;实现了可选组件卸载(但是写死的,不能安装实际安装情况进行显示需要卸载的组件)

;Section  Un.全部组件 SEC10

;  RMDir /r "$INSTDIR"

; SectionEnd


; Section Un.模块1 SEC11

;  RMDir /r "$INSTDIR\msgServer"

; SectionEnd


; Section Un.模块2 SEC12

;  RMDir /r "$INSTDIR\alarmReceiver"

; SectionEnd


;Section Un.模块3 SEC13

;  RMDir /r "$INSTDIR\pref_receiver\"

;SectionEnd


;Section Un.模块4 SEC14

;  RMDir /r "$INSTDIR\sysmonitor\"

;SectionEnd




Section Uninstall


 RMDir /r "$INSTDIR"


 DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"

 SetAutoClose true

SectionEnd


#-- 根据 NSIS 脚本编辑规则,所有 Function 区段必须放置在 Section 区段之后编写,以避免安装程序出现未可预知的问题。--#

Function un.onInit

 MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "您确实要完全移除 $(^Name) ,及其所有的组件?" IDYES +2

 Abort

FunctionEnd


Function un.onUninstSuccess

 HideWindow

 MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) 已成功地从您的计算机移除。"

FunctionEnd



;配置数据库相关信息的页面

Function ConfigDBPage

${if} $isConfig == "1"


nsDialogs::Create /NOUNLOAD 1018

Pop $Dialog


${If} $Dialog == error

Abort

${EndIf}


;配置数据库IP地址

${NSD_CreateLabel} 0 0 100% 12u "请输入数据库ip地址:"

Pop $Label


${NSD_CreateText} 0 13u 100% 12u ""

Pop $ip


${NSD_SetText} $ip $R1


 ${NSD_OnChange} $ip IPChange


;配置数据库端口号

 ${NSD_CreateLabel} 0 26u 100% 12u "请输入数据库端口号:"

Pop $Label



${NSD_CreateText} 0 39u 100% 12u ""

Pop $port


${NSD_SetText} $port $R2


${NSD_OnChange} $port PortChange


;配置数据库sid

${NSD_CreateLabel} 0 52u 100% 12u "请输入数据库sid:"



${NSD_CreateText} 0 65u 100% 12u ""

Pop $sid


${NSD_SetText} $sid $R3


${NSD_OnChange} $sid SidChange


nsDialogs::Show


Call CheckPage

${EndIf}

FunctionEnd


Function ConfigXML

;依次修改beans.xml文件的中strDBHostIP,strDBHostPort,strDBServerSID

 ${xml::LoadFile} "$INSTDIR\模块1\conf\Beans.xml" $6

 ${xml::GotoPath} "/beans/bean/property[1]/value" $0

 ${xml::SetText} $R1 $0

 ${xml::GotoPath} "/beans/bean/property[2]/value" $0

 ${xml::SetText} $R2 $0

 ${xml::GotoPath} "/beans/bean/property[3]/value" $0

 ${xml::SetText} $R3 $0

 ${xml::SaveFile} "$INSTDIR\模块1\conf\Beans.xml" $6


 ${xml::LoadFile} "$INSTDIR\模块2\conf\Beans.xml" $6

 ${xml::GotoPath} "/beans/bean/property[1]/value" $0

 ${xml::SetText} $R1 $0

 ${xml::GotoPath} "/beans/bean/property[2]/value" $0

 ${xml::SetText} $R2 $0

 ${xml::GotoPath} "/beans/bean/property[3]/value" $0

 ${xml::SetText} $R3 $0

 ${xml::SaveFile} "$INSTDIR\模块2\conf\Beans.xml" $6


 ${xml::LoadFile} "$INSTDIR\模块3\conf\Beans.xml" $6

 ${xml::GotoPath} "/beans/bean/property[1]/value" $0

 ${xml::SetText} $R1 $0

 ${xml::GotoPath} "/beans/bean/property[2]/value" $0

 ${xml::SetText} $R2 $0

 ${xml::GotoPath} "/beans/bean/property[3]/value" $0

 ${xml::SetText} $R3 $0

 ${xml::SaveFile} "$INSTDIR\模块3\conf\Beans.xml" $6

FunctionEnd


;校验输入的配置信息

Function checkPage

 ${if} $R1 == ""

MessageBox MB_ICONINFORMATION|MB_OK  "Ip地址不能为空!"

;退回到数据库配置信息页面

call ConfigDBPage

${endif}


${if} $R2 == ""

MessageBox MB_ICONINFORMATION|MB_OK  "数据库端口号不能为空!"

;退回到数据库配置信息页面

call ConfigDBPage

${endif}


${if} $R3 == ""

MessageBox MB_ICONINFORMATION|MB_OK  "数据库Sid不能为空!"

;退回到数据库配置信息页面

call ConfigDBPage

${endif}

FunctionEnd


Function IPChange

;将ip的值存入到$R1中

 ${NSD_GetText} $ip $R1

FunctionEnd


Function PortChange

;将port的值存入到$R2中

 ${NSD_GetText} $port $R2

FunctionEnd


Function SidChange

;将sid的值存入到$R3中

 ${NSD_GetText} $sid $R3

FunctionEnd