最近工作中遇到一个需要打包程序的任务,学习了下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