用NSIS制作安装文件 | 学步园

1.前言

如果你是第一次制作安装程序,建议你使用 Setup Factory 或 CreateInstall
因为这两个安装程序是图形接口非常的适合初学者使用。笔者一开始也不会使用
NSIS 写脚本而是先从上面两套软件着手,了解安装程序的流程与基础才进而使用
Nullsoft Installation System 来制作安装程序。

同一个程序用这三套软件以最精简的流程制作出来的安装程序其大小如下

-----------------------------------------------
原始程序             248 KB
Setup Factory         488 KB
CreateInstall          156 KB
Nullsoft Installation System  134 KB
-----------------------------------------------

我本来是想直接用 CreateInstall 来制作安装程序就好因为它是图形接口简单
作出来的档案也很小。但是他作出来的安装程序在繁体中文系统底下有一个BUG
让我非放弃他不可。就是建立快捷方式在「开始」菜单 -> 程序集 里他会因为
BIG5 里面的 "功" 含有 "\" 而建立成 「开始」-> 能表 -> 程序集 少了一个
字作出来的快捷方式也不能用 >_<" 想办法跟作者联络但是我英文实在很破.......
前言到此结束底下开始是教学了

==========================================================

本教学以 KYO 网友所著的 ShellInfoTip 为例子,因为它需要做到下列三项

1.注册 DLL 档案
2.注册 REG 登录档案
3.在 WIN 路径里放置 STPlugin.ini

我先在这里简单的描述所需用到的参数在文章结尾处我会放上 ShellInfoTip.nsi
脚本档案我有写上详细的批注,这里以提出所需要的三项功能作为主要介绍。有
不知道不了解不清楚或我没提及的参数,你可以查找 NSIS 的使用说明书他写的
非常详细。

1.注册 DLL 档案
RegDLL "$INSTDIR\ShellTip4Rar.dll"

其中 $INSTDIR 是代表你安装的目录
如:你是装在 c:\emp\ShellInfoTip 底下,他的 $INSTDIR 就是这个目录会随着你的安装路径而变动。

2.注册 REG 登录档案
WriteRegStr HKCR ".rar\ShellEx\{ 00021500-0000-0000-c000-000000000046 }" "" "{ C34C25BE-9B2B-4A50-9D97-2658E0D8796B }"

WriteRegStr HKCR ".exe\ShellEx\{ 00021500-0000-0000-c000-000000000046 }" "" "{ C34C25BE-9B2B-4A50-9D97-2658E0D8796B }"

WriteRegStr HKCR ".001\ShellEx\{ 00021500-0000-0000-c000-000000000046 }" "" "{ C34C25BE-9B2B-4A50-9D97-2658E0D8796B }"

WriteRegStr 是写入类型为 REG_SZ 的数值
HKCR 是 HKEY_CLASSES_ROOT 的缩写

原始程序所要注册的登录档内容如下
-----------------------------------------------------------------------
REGEDIT4

[HKEY_CLASSES_ROOT\.rar\ShellEx]

[HKEY_CLASSES_ROOT\.rar\ShellEx\{ 00021500-0000-0000-c000-000000000046 }]
@="{ C34C25BE-9B2B-4A50-9D97-2658E0D8796B }"

[HKEY_CLASSES_ROOT\.exe\ShellEx]

[HKEY_CLASSES_ROOT\.exe\ShellEx\{ 00021500-0000-0000-c000-000000000046 }]
@="{ C34C25BE-9B2B-4A50-9D97-2658E0D8796B }"

[HKEY_CLASSES_ROOT\.001\ShellEx]

[HKEY_CLASSES_ROOT\.001\ShellEx\{ 00021500-0000-0000-c000-000000000046 }]
@="{ C34C25BE-9B2B-4A50-9D97-2658E0D8796B }"
-----------------------------------------------------------------------

3.在 WIN 路径里放置 STPlugin.ini
WriteINIStr "$WINDIR\STPlugin.ini" "Plugin" "Plugin1" "$INSTDIR\rar_txt.dll"

$WINDIR 是 Windows 系统的目录
WriteINIStr 是写入 INI 档案,按照顺序写入 ini 的文件名称、区域名称、变量名称、数值。

原始程序的 STPlugin.ini 档内容如下
-------------------------------------------------
[Plugin]
Plugin1=安装路径名\rar_txt.dll
-------------------------------------------------

三项主要的功能介绍就到此结束了底下开始是ShellInfoTip.nsi脚本档案的内容

==========================================================
; ShellInfoTip.nsi
; 本安装程序由 DC 编写制作
;

;宣告软件名称,后面可以利用 ${ NAME } 调用这个名字
!define NAME "ShellInfoTip"

;设定字型
SetFont 宋体 9

;使用 WindowsXP 视觉样式
XPstyle on

;安装窗口的标题名称
Caption /LANG=2052 "安装 Winrar Shell Info Tip 功能"

;替换预设的按钮文字
MiscButtonText /LANG=2052 "< 上一步" "下一步 >" "取消" "关闭"

;替换预设的按钮文字
InstallButtonText /LANG=2052 "安装"

;替换预设的按钮文字
UninstallButtonText /LANG=2052 "反安装"

;替换反安装程序的文字
DirText /LANG=2052 "欢迎您安装 Shell Info Tip 这是个自由软件版权归原作者 KYO 所有。此安装程序由∮Ω奥米加空间∮ 坛主 DC 提供制作。" "请选择欲安装 ${ NAME } 的目录:" "浏览..."

;替换反安装程序的文字
UninstallText /LANG=2052 "现在将从你的系统中反安装 ${ NAME } 。如果你触发了 ${ NAME } 的功能 ShellTip4Rar.dll 动态连结文件必须重开机之后才可以被删除。" "反安装目录:"

;替换反安装程序标题的文字
UninstallCaption /LANG=2052 "反安装 ${ NAME }"

;替换反安装程序的文字
DetailsButtonText /LANG=2052 "显示详细过程"

;替换反安装按钮的文字
UninstallButtonText /LANG=2052 "反安装"

;反安装程序显示方式 预设是隐藏
ShowUninstDetails hide

;替换空间的文字
SpaceTexts /LANG=2052 "所需的空间 " "可用的空间 "

;这个安装程序的名称
Name "ShellInfoTip"

;输出制作完成的安装程序档案
OutFile "ShellInfoTipchs.exe"

;预设的安装程序目录在 Program Files 里
InstallDir $PROGRAMFILES\${ NAME }

;底下开始是安装程序所要执行的
Section "ThisNameIsIgnoredSoWhyBother?"

;设定输出的路径在安装程序的目录
SetOutPath $INSTDIR

;贴上你所要包装在安装程序里的档案
File "C:\All Release\YingInstall\Files\rar_txt.dll"
File "C:\All Release\YingInstall\Files\ShellTip4Rar.dll"

;注册 DLL 档案
RegDLL "$INSTDIR\ShellTip4Rar.dll"

;写入欲注册的值在 HKEY_CLASSES_ROOT 里类型为 REG_SZ
WriteRegStr HKCR ".rar\ShellEx\{ 00021500-0000-0000-c000-000000000046 }" "" "{ C34C25BE-9B2B-4A50-9D97-2658E0D8796B }"

WriteRegStr HKCR ".exe\ShellEx\{ 00021500-0000-0000-c000-000000000046 }" "" "{ C34C25BE-9B2B-4A50-9D97-2658E0D8796B }"

WriteRegStr HKCR ".001\ShellEx\{ 00021500-0000-0000-c000-000000000046 }" "" "{ C34C25BE-9B2B-4A50-9D97-2658E0D8796B }"

;写入 INI 档
WriteINIStr "$WINDIR\STPlugin.ini" "Plugin" "Plugin1" "$INSTDIR\rar_txt.dll"

;在程序集里建立反安装程序的快捷方式
CreateDirectory "$SMPROGRAMS\${ NAME }"
CreateShortCut "$SMPROGRAMS\${ NAME }\反安装 ${ NAME }.lnk" \
"$INSTDIR\uninst.exe"

;写入建立反安装程序要跟上面所连结的档名一样
WriteUninstaller "$INSTDIR\uninst.exe"

SectionEnd
;安装程序过程到此结束

;反安装程序内容
Section "Uninstall"

;循环删除档案直到删除数据夹
UnRegDLL "$INSTDIR\ShellTip4Rar.dll"
Delete "$INSTDIR\*.*"
Delete "$WINDIR\STPlugin.ini"
RMDir "$SMPROGRAMS\${ NAME }"
RMDir "$INSTDIR"

;写入欲删除注册的值
DeleteRegKey HKCR ".rar\ShellEx"
DeleteRegKey HKCR ".exe\ShellEx"
DeleteRegKey HKCR ".001\ShellEx"
SectionEnd
;反安装程序过程到此结束

2...
; NSIS Modern User Interface version 1.62
;
; NSIS 多语言脚本写作密技
;
; 这是 KA 实地用于 MDaemon 4.05 中文化的多语言安装,
; 环境: NSIS 2.0b1, Modern UI 1.62
;
; 为便于阅读,标明 (* 进阶) 者,较为困难,可先略过。
; 几乎是想办法用上 Modern UI 1.62 新版的所有技巧了。
; 如果注解写得太多,损害你的智商,请赶快写信骂我。
;
; 简体描述部分,因为在 BIG5 编码之下使用 GB2312 ,故
; 必定有乱码,还请见谅。如果需要在网页取得正确编码,
; 请储存为 BIG5 plain text ,再来处理。我会另外以
; attach file 的方式附在板上。
;
; 我没有使用任何类似 GUI 的工具。如果你之前已经有用
; 于 2.0a7 的 NSI 脚本,跨越版本时在 Modern UI 的写
; 法,会花一些工夫。比如新世纪精华板有人用的
; magiclime ,现在只能用 advsplash 以外挂程式方式载入。
; 不用怕,我在里面都写了。如果还嫌太麻烦,Joost 的英
; 文版HTML 入门,只有一页,建议先看。
;
; 记得,没人强迫你要使用多语言,没人强迫你要 Modern
; UI ,没人强迫你要欢迎对话方块。你一样可以做出一点也
; 不花俏的,很传统的安装程式。不要在那里废话什么 NSIS
; 愈做愈肥大。
;
; 这些都是自己决定的。
;

;=======================================================
; ■1.定义变数、安装目录、输出档案、图示
;=======================================================
; 只要在这里写好,其他的都按照定义的变数下去跑,就省力多了。
;
;==============================
; 1.1 版本号码/名称
;
!define VER_1 4 ;软体版本号码 1 ,如 Eudora 4.3.1.2 四位版本号码
!define VER_2 05 ;软体版本号码 2
;!define VER_3 xxx ;软体版本号码 3 (* 进阶)
;!define VER_4 yyy ;软体版本号码 4 (* 进阶)
;!define VER_R zzz ;中文化同版本第几更版 (* 进阶)
!define MUI_PRODUCT "MDaemon" ;程式名称 (可使用大小写)
!define PROGFNHEADER "mdaemon" ;中文化档案名称的主要部分 (全部小写)
!define PROGMAINEXE "mdaemon.exe" ;主程式执行档案名称 (含.exe)
;
;==============================
; 1.2 读我档案/输出档案
;
; 读我显示,包括 CHS/CHT/ENU 三个版本。如果你不需要制作
; 多语言中文化版本,只要考虑一个“读我”即可。这个读我,
; 通常拿来放“此中文化的描述档案”,而非一般软体的 readme 。
;
; 档案命名: (全部小写)。
; (cpatch) c + ${ PROGFNHEADER } + 版本号码 _(底线) 第几中文化版本 . 副档名
; (hanzify) ha _(底线) ${ PROGFNHEADER } + 版本号码 _(底线) 作者名 . 扩展名
;
;!define README "c${ PROGFNHEADER }${ VER_1 }${ VER_2 }.txt"
!define README_CHS "c${ PROGFNHEADER }${ VER_1 }${ VER_2 }_gb.txt"
!define README_CHT "c${ PROGFNHEADER }${ VER_1 }${ VER_2 }.txt"
!define README_ENU "c${ PROGFNHEADER }${ VER_1 }${ VER_2 }.txt"
OUTFILE "c${ PROGFNHEADER }${ VER_1 }${ VER_2 }.exe"

;==============================
; 1.3 预设安装目录 (尾端不加 \)
;
; 通常会出现在 "C:\Program Files\xxxx " 这种目录。
; 也可以使用 ${ AppPath } 在注册表寻找旧版安装目录。
; 如果注册表的安装目录 (尾端 \) 出现,不要使用,以免发生错误。

;InstallDir "$PROGRAMFILES\${ MUI_PRODUCT }"
;InstallDir "${ AppPath }"
InstallDir "C:\MDaemon"

;==============================
; 1.4 版权影像
;
; 只需要一个就够 (一定要 bmp 格式),第二个是拿来花俏用的。
; 可以只使用一个,或完全不使用。

!define SPLASH1 "mdaeomon4_cht.bmp"
!define SPLASH2 "mdaeomon4_chs.bmp"

;==============================
; 1.5 安装程式型态
;
; 中文化/直接安装版/还是补缀补丁?安装时出现在 caption 部分。
; 解除安装时,也会出现在注册表。

!define PATCHTYPE_ENU "(CN+TW) localized"
!define PATCHTYPE_CHT "(CN+TW) 中文化"
!define PATCHTYPE_CHS "(CN+TW) 笢恅赵"

;=======================================================
; ■2.使用者介面
;=======================================================
; 这一段的用途,在于强制覆写 system.nsh 的英文预设设定值,
; 通常只有变更 “字型”“图示”
;==============================
; 2.1 字型

; 安装介面的字型预设大小 8,一定要改掉,否则在 win98 中文不好看。
; 如下。双语言中文化,使用 "Tahoma" 即可。
; 不需要特别指定“新宋体”或“宋体”。

;!define MUI_FONT "MS Shell Dlg"
;!define MUI_FONTSIZE "8"
;!define MUI_FONT_HEADER "MS Sans Serif"
;!define MUI_FONTSIZE_HEADER "8"
;
; 上列: NSIS 字型“预设值”,下列: 字型“建议修改值”。
;
!define MUI_FONT "Tahoma"
!define MUI_FONTSIZE "9"
!define MUI_FONT_HEADER "Tahoma"
!define MUI_FONTSIZE_HEADER "9"

;==============================
; 2.2 图示

; 安装程式图示: 通常我使用主程式的图示,另外用 VC 抽取出来。
; 解除安装图示: 为了让 [控制台 &line; 新增/移除程式] 出现正确图示,还是用同一个图示。
; 有时候则使用它附的图示 (因为看起来不错)。
;!define MUI_ICON "${ NSISDIR }\Contrib\Icons\modern-install.ico"
;!define MUI_UNICON "${ NSISDIR }\Contrib\Icons\modern-uninstall.ico"
;
; 上列: NSIS 图示“预设值”,风格有点像 InstallShield 6 ,也不错。
; 下列: 自订图示,请指定正确名称

!define MUI_ICON "mdaemon4.ico"
!define MUI_UNICON "mdaemon4.ico"

;==============================
; 2.3 其他 (* 进阶)

!define MUI_UI "${ NSISDIR }\Contrib\UIs\modern2.exe"
!define MUI_CHECKBITMAP "${ NSISDIR }\Contrib\Icons\modern.bmp"
!define MUI_FONTstyle_HEADER "700"
!define MUI_FONT_TITLE "Verdana"
!define MUI_FONTSIZE_TITLE "12"
!define MUI_FONTstyle_TITLE "700"
!define MUI_INSTALLCOLORS "/windows"
!define MUI_PROGRESSBAR "smooth"
!define MUI_SPECIALINI "${ NSISDIR }\Contrib\Modern UI\ioSpecial.ini"
!define MUI_SPECIALBITMAP "${ NSISDIR }\Contrib\Icons\modern-wizard.bmp"
!define MUI_BGCOLOR "0xFFFFFF"

;=======================================================
; ■3.多语言系统
;=======================================================
; 载入 Modern UI\System.nsh 之用。
;==========================
; 3.1 前置相同变数,视需要而定。
;
; 通常出现在更换版本时,原脚本的变数校正。

!define MUI_VERSION "${ VER_1 }.${ VER_2 }"
;!define NAME "${ MUI_PRODUCT }"

;显示中文化标题,依 ENU/CHT/CHS 语言的不同。

CAPTION /LANG=1033 "${ MUI_PRODUCT } ${ MUI_VERSION } ${ PATCHTYPE_ENU }"
CAPTION /LANG=1028 "${ MUI_PRODUCT } ${ MUI_VERSION } ${ PATCHTYPE_CHT }"
CAPTION /LANG=2052 "${ MUI_PRODUCT } ${ MUI_VERSION } ${ PATCHTYPE_CHS }"

;==========================
; 3.2 载入 Modern UI 系统

!include "${ NSISDIR }\Contrib\Modern UI\System.nsh"

;==========================
; 3.3 使用者介面
;
; 如果不要这些对话方块,不做 define ,就不会出现。

!define MUI_WELCOMEPAGE ;欢迎页面
!define MUI_LICENSEPAGE ;授权页面
!define MUI_COMPONENTSPAGE ;元件页面
!define MUI_DIRECTORYPAGE ;目录选择
!define MUI_ABORTWARNING ;中止警告
!define MUI_UNINSTALLER ;解除安装程式
!define MUI_UNCONFIRMPAGE ;不做确认页面
; !define MUI_STARTMENUPAGE ;选择开始功能表
!define MUI_FINISHPAGE ;出现完成页面,执行程式和读我。
!define MUI_FINISHPAGE_RUN "$INSTDIR\app\${ PROGMAINEXE }"
!define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\${ README_CHT }"
; !define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\$(README)"

; LangString README ${ LANG_ENGLISH } "${ README_ENU }"
; LangString README ${ LANG_TRADCHINESE } "${ README_CHT }"
; LangString README ${ LANG_SIMPCHINESE } "${ README_CHS }"
; 上面这段 LangString 并不能套用在 SHOWREADME ,真奇怪。

!insertmacro MUI_SYSTEM ;使用者介面系统

;==============================
; 3.4 各国语言

!insertmacro MUI_LANGUAGE "English"
!insertmacro MUI_LANGUAGE "SimpChinese"
!insertmacro MUI_LANGUAGE "TradChinese"

;==============================
; 3.5 授权文字 (* 进阶)
;
; 这些档案没有出现在 NSIS 预设包内。如果你手上没有 license 档案,
; 请直接 remark 掉。
; 这些东西会先被解压缩出来。保留这几行在任何 File 指令之前!)
; 只能用于 BZIP2 压缩

LicenseData /LANG=${ LANG_ENGLISH } "${ NSISDIR }\Examples\Modern UI\license_enu.rtf"

LicenseData /LANG=${ LANG_SIMPCHINESE } "${ NSISDIR }\Examples\Modern UI\license_chs.rtf"

LicenseData /LANG=${ LANG_TRADCHINESE } "${ NSISDIR }\Examples\Modern UI\license_cht.rtf"

!insertmacro MUI_RESERVEFILE_LANGDLL

;=======================================================
; ■4.安装程式,安装开始的前置动作 (* 进阶)
;=======================================================
; 如果不需要,你可以全部 remark。
Function .onInit

;==============================
; 4.1 显示版权影像
;
; 旧版可使用 magiclime 做淡入淡出。不过这一版没了,改成
; advsplash ,外挂方式。解压缩到临时目录,显示 splash ,然后删掉。
; 注意: nsis 2.0a0 有 magicsplash 档案。不过 2.0b1 居然又不见了。

SetOutPath $TEMP
File /oname=splash1.bmp ${ SPLASH1 }
File /oname=splash2.bmp ${ SPLASH2 }
; File /oname=spltmp.exe "${ NSISDIR }\bin\magiclime.exe"
; ExecWait '"$TEMP\spltmp.exe" splash1.bmp'
; ExecWait '"$TEMP\spltmp.exe" splash2.bmp'

advsplash::show 1000 600 400 -1 $TEMP\splash1
advsplash::show 1000 600 400 -1 $TEMP\splash2

Pop $0 ; $0 has '1' if the user closed the splash screen early,
; '0' if everything closed normal, and '-1' if some error occured.

Delete $TEMP\spltmp.exe
Delete $TEMP\splash1.bmp
Delete $TEMP\splash2.bmp

;==============================
; 4.2 字型选择 (* 进阶)
;
; 只影响安装程式的语言选择 dialog ,因此不要使用中文字型名称。
Push Verdana
Push 9

;==============================
; 4.3 语言 (* 进阶)
;
; 塞了 ENU/CHT/CHS 三个语言。你要 18 个语言全塞,也不反对。大小大概增加 20 kb 左右。
; 如果不是多语言中文化安装,你可以全部 remark 掉。

!insertmacro MUI_LANGDLL_PUSH "English"
!insertmacro MUI_LANGDLL_PUSH "SimpChinese"
!insertmacro MUI_LANGDLL_PUSH "TradChinese"

Push 3F ;3 = 语言数目, F = 变更字型

LangDLL::LangDialog "Installer Language" "Please select a language."

; 上面这一句,不要中文化。除非你想让老外看到乱码。

Pop $LANGUAGE
StrCmp $LANGUAGE "cancel" 0 +2
Abort

;==============================
; 4.4 安装前置动作 (修改注册表) (* 进阶)
;
; 视你需要,可以偷偷做一些动作。

; DeleteRegKey HKLM "SOFTWARE\Classes\CLSID\{ b5eedee0-c06e-11cf-8c56-444553540000 }\InProcServer32"

; DeleteRegKey HKLM "SOFTWARE\Classes\CLSID\{ b5eedee0-c06e-11cf-8c56-444553540000 }"

;==============================
; 4.5 寻找旧版已安装的目录。 (* 进阶)
;
; 如果 AppPath 读出的尾端有 \ 符号,请不要直接使用于 INSTDIR 指令,以免发生错误。

; ReadRegStr $AppPath HKLM "SOFTWARE\Alt-N Technologies\MDaemon" "AppPath"

FunctionEnd

;=======================================================
; ■5.安装程式,安装完成后置动作 (* 进阶)
;=======================================================
; 如果不需要,你可以全部 remark。
;==============================
; 5.1 函式定义开始
Function .onInstSuccess

;==============================
; 5.2 安装完成后,执行 ExecShell
;
; 视个人需要而定,我只用在 Eudora 安装而已。
; ;------------------------------------------
; !macro MUI_INSTSUCCESS1 LANGID TEXT
;
; StrCmp $LANGUAGE ${ LANGID } "" +3
; MessageBox MB_YESNO&line;MB_ICONQUESTION "${ TEXT }" IDNO Nomapi
; ExecShell open '$INSTDIR\SWMAPI.EXE'
; !macroend
; ;------------------------------------------;

; 下列是 ENU/CHT/CHS 三个语言的动作。
;
; !insertmacro MUI_INSTSUCCESS1 1033 "Do you want to install ${ NAME } as a default mailer? It will excute MAPI installer."

; !insertmacro MUI_INSTSUCCESS1 1028 "你想要安装 ${ NAME } 做为预设信件程式吗?将执行外部 MAPI 安装程式。"

; !insertmacro MUI_INSTSUCCESS1 2052 "斓砑猁假蚾 ${ NAME } 酕峈苏?;蛔璃最唗镉ˋ蔚堍俴俋窒 MAPI 假蚾最唗﹝"

; Nomapi:

;==============================
; 5.3 安装后,要求使用者读取 README 档案

; ;------------------------------------------
; !macro MUI_INSTSUCCESS2 LANGID TEXT README

; StrCmp $LANGUAGE ${ LANGID } "" +3
; MessageBox MB_YESNO&line;MB_ICONQUESTION "${ TEXT }" IDNO NoReadme
; ExecShell open notepad '$INSTDIR\${ README }'
; !macroend
; ;------------------------------------------

; 下列是 ENU/CHT/CHS 三个语言的动作。

; !insertmacro MUI_INSTSUCCESS2 1033 "Setup has been completed successfully . Press [Yes] to continue README file." "${ README_ENU }"

; !insertmacro MUI_INSTSUCCESS2 1028 "安装已成功地完成。按下 [Yes] 继续读取 README 档案。" "${ README_CHT }"

; !insertmacro MUI_INSTSUCCESS2 2052 "假蚾眒伧髡华俇伧﹝偌狟 [Yes] 樟哿黍?; README 恅璃﹝" "${ README_CHS }"

; NoReadme:

;==============================
; 5.4 函式定义结束
FunctionEnd

;=======================================================
; ■6.安装的所有档案
;=======================================================

;==============================
; 6.1 安装类型

; 两种应该很够了。

InstType "Minimum"
InstType "Standard"

SetOverwrite on

;==============================
; 6.3 安装的各个节段

Section "MDaemon" SecMDaemon
SectionIn 1 2

; 6.3.1 中文化的读我
; 通常塞在安装的主目录。

SetOutPath $INSTDIR
File "${ README_CHT }"
File "${ README_CHS }"

; 6.3.2 中文化的程式档案

; 通常不使用 *.* 型态,而个别指定,以免包装错误。
; 常常是 *.DLL *.EXE *.AX 等类型。我都把这类放在 cht 为首的工作目录。

SetOutPath $INSTDIR\app
File "cht\AccountPrune.exe"
File "cht\CFILTER.EXE"
File "cht\IMPORTNT.EXE"
File "cht\ListPrune.exe"
File "cht\MD3CONV.EXE"
File "cht\MDAEMON.EXE"
File "cht\MDCONFIG.EXE"
File "cht\MDLAUNCH.EXE"
File "cht\MDSTATS.EXE"
File "cht\MDUSER.DLL"
File "cht\MDUserLdap.dll"
File "cht\MigrateUsers.exe"
File "cht\ROBOEX32.DLL"
File "cht\UninstallSurvey.exe"
File "cht\UNWISE.EXE"
File "cht\WCIMPORT.EXE"
File "cht\XCEEDZIP.DLL"

; 6.3.3 中文化的文字档案
;
; 通常是 (*.cnt, *.txt *.dat *.ini) 类型。
; 无语言区分者,仍放在 pack 为首的工作目录。
; 有语言区分者,放在 text/cht 与 text/chs 为首的工作目录。

; 6.3.3.1 如果有旧版,会有一些“一定”要删除的旧版档案。然后再由安装程式补上新版。

SetOutPath $INSTDIR\app
Delete "$INSTDIR\app\HELP.DAT"
Delete "$INSTDIR\app\MDAEMON.CNT"
Delete "$INSTDIR\app\acctinfo.dat"

File "pack405\app\CFILTER.INI"
File "pack405\app\MDSTATS.INI"

; 6.3.3.2 如果有旧版,也会有一些“不能删除”的旧版档案。

; 这段是使用在 UltraEdit ,把 windows 目录的 INI 移动过来。MDaemon 不用这一段。
;
; IfFileExists "$WINDIR\UEdit32.ini" DO1 DO2
; DO1: ;把 $WINDIR 的移动到安装目录
; Rename "$WINDIR\UEdit32.ini" "$INSTDIR\Uedit32.ini"
; DO2: ;如果没有,则写入一个假的 INI,以修正 HTMLTIDY 的功能。如果安装目录已有,则不盖掉。

SetOverwrite off ;停用强制覆写
File "pack405\app\MDAEMON.INI"
SetOverwrite on ;判断完毕之后,启用强制覆写

; 6.3.3.3 搞一些好玩的,比如塞入自动使软体注册的资料
; 正式版本就不要这样做,以免太嚣张,反而不好。
;
; WriteINIStr "$INSTDIR\app\mdaemon.ini" "Registration" "Name" "My_reg_Name"
; WriteINIStr "$INSTDIR\app\mdaemon.ini" "Registration" "Company" "My_reg_Company"

; WriteINIStr "$INSTDIR\app\mdaemon.ini" "Registration" "4XKey" "GDPFFMF-QAWLYFJ-XQDIYAO"

; 6.3.3.4 补上新版档案
;
; 依照各种语言,自动执行,分配正确的档案。使用者不必再选择。
; 先写一个巨集,自动判断作业系统语言。 1033 enu, 1028 cht, 2052 chs
;------------------------------------------
!macro MUI_COPYTEXTFILE LANGID ACTION_COPYTEXTFILE

StrCmp $LANGUAGE ${ LANGID } "" +3
${ ACTION_COPYTEXTFILE }

!macroend

; !insertmacro MUI_COPYTEXTFILE 1033 'File "text405\enu\Help.dat"'
; !insertmacro MUI_COPYTEXTFILE 1033 'File "text405\enu\MDaemon.cnt"'
;
; 英文的不动,只做为对照组。注意单引号和双引号。
; 这种脚本写法其实蛮笨的,应该有更好的方法。

!insertmacro MUI_COPYTEXTFILE 1028 'File "text405\cht\Help.dat"'
!insertmacro MUI_COPYTEXTFILE 1028 'File "text405\cht\MDaemon.cnt"'
!insertmacro MUI_COPYTEXTFILE 2052 'File "text405\chs\Help.dat"'
!insertmacro MUI_COPYTEXTFILE 2052 'File "text405\chs\MDaemon.cnt"'

; 6.3.4 非中文化档案 (不用修改的部分)

; 可使用 *.* 这种型态。 我都把这类放在 pack 为首的工作目录。

SetOutPath $INSTDIR\app
File "pack405\app\AccountPrune.txt"
File "pack405\app\bwcc32.dll"
File "pack405\app\ADDUSER.SMP"
File "pack405\app\CFAPP.ICO"
File "pack405\app\CFILTER.DLL"
File "pack405\app\DEDUPE.EXE"
File "pack405\app\DIRREORG.EXE"
File "pack405\app\DomainPOP.dsc"
File "pack405\app\EDITUSER.SMP"
File "pack405\app\FILELIST.DAT"
File "pack405\app\INETWH32.DLL"
File "pack405\app\INSTALL.LOG"
File "pack405\app\MailboxSize.exe"
File "pack405\app\MailboxSize.txt"
File "pack405\app\MDAEMON.DSC"
File "pack405\app\MDAEMON.HLP"
File "pack405\app\NTUTIL.DLL"
File "pack405\app\ULREPAIR.EXE"
File "pack405\app\WISECHCK.EXE"
File "pack405\app\WISEUPDT.EXE"
File "pack405\app\WP2WC.EXE"
File "pack405\app\XCDSFX32.BIN"

SetOutPath $INSTDIR\cgi
File "pack405\cgi\*.*"
SectionEnd

Section "MDaemon Docs" SecMDaemonDocs
SectionIn 2
SetOutPath $INSTDIR\docs
File "pack405\docs\*.*"
SetOutPath $INSTDIR\docs\api
File "pack405\docs\api\*.*"
SectionEnd

Section "World Client" SecWorldClient
SectionIn 2
SetOutPath $INSTDIR\wcstandard
File "pack405\wcstandard\*.*"
; 底下为需要中文化的部分
File "cht\wcstandard\WCStandard.exe"
File "cht\wcstandard\WorldClient.dll"
File "cht\wcstandard\XceedZip.dll"

SetOutPath $INSTDIR\wcstandard\html
File "pack405\wcstandard\html\*.*"
SetOutPath $INSTDIR\wcstandard\html\help
File "pack405\wcstandard\html\help\*.*"
SetOutPath $INSTDIR\wcstandard\templates
File "pack405\wcstandard\templates\*.*"
SectionEnd

Section "Web Config" SecWebConfig
SectionIn 2
SetOutPath $INSTDIR\webconfig
File "pack405\webconfig\*.*"
; 底下为需要中文化的部分
File "cht\webconfig\WebConfig.exe"

SetOutPath $INSTDIR\webconfig\html
File "pack405\webconfig\html\*.*"
SetOutPath $INSTDIR\webconfig\templates
File "pack405\webconfig\templates\*.*"
SectionEnd

;==============================
; 6.4 加入到“开始选单”
;

Section "Add shortcut to Start Menu" SecStartMenu
SectionIn 1 2
SetOutPath "$INSTDIR"

CreateDirectory "$SMPROGRAMS\${ MUI_PRODUCT }"
; 有时候 CreateShortCut 会出问题,不如用这个动作
; 直接强制 installer 建立目录。这样比较贱。

CreateShortCut "$SMPROGRAMS\${ MUI_PRODUCT }\MDaemon.lnk" \
"$INSTDIR\app\mdaemon.exe"
CreateShortCut "$SMPROGRAMS\${ MUI_PRODUCT }\MDConfig.lnk" \
"$INSTDIR\app\MDConfig.exe"
CreateShortCut "$SMPROGRAMS\${ MUI_PRODUCT }\Uninstall ${ MUI_PRODUCT }.lnk" \
"$INSTDIR\Uninstall.exe"
SectionEnd

;==============================
; 6.5 加入到“快速启动”
;
; 不是每个程式都要加入“快速启动”列,视需要而定。
;
;Section "Add shortcut to Quicklaunch" SecQuicklaunch
; SectionIn 1 2
; CreateShortCut "$QUICKLAUNCH\${ MUI_PRODUCT }.lnk" \
; "$INSTDIR\app\${ PROGMAINEXE }"
;SectionEnd

;==============================
; 6.6 加入到“桌面”
;

Section "Add shortcut to Desktop" SecDesktop
SectionIn 1 2
CreateShortCut "$DESKTOP\${ MUI_PRODUCT }.lnk" \
"$INSTDIR\app\${ PROGMAINEXE }"
SectionEnd

;==============================
; 6.6 加入到“滑鼠右键” (* 进阶)
;
; 只用在 UltraEdit

;Section "Add to Right mouse button" SecRightMouse
; SectionIn 1 2
; WriteRegStr HKLM "SOFTWARE\Classes\*\shellex\ContextMenuHandlers\UltraEdit-32" "" "{ b5eedee0-c06e-11cf-8c56-444553540000 }"

; WriteRegStr HKLM "SOFTWARE\Classes\CLSID\{ b5eedee0-c06e-11cf-8c56-444553540000 }" "" "UltraEdit-32"

; WriteRegStr HKLM "SOFTWARE\Classes\CLSID\{ b5eedee0-c06e-11cf-8c56-444553540000 }\InProcServer32" "" "$INSTDIR\ue32ctmn.dll"

; WriteRegStr HKLM "SOFTWARE\Classes\CLSID\{ b5eedee0-c06e-11cf-8c56-444553540000 }\InProcServer32" "ThreadingModel" "Apartment"

;SectionEnd

;=======================================================
; ■7.写入解除安装程式
;=======================================================
; 如果你嫌太难,可以不写解除安装程式,全部 remark 掉。
;==============================
; 7.1 节段开始

Section "Create Uninstaller" SecCreateUninst
SectionIn 1 2

;==============================
; 7.2 写入到“注册表”(基础)
;
; 一般只有写下面这一段,指定安装目录。

WriteRegStr HKLM "SOFTWARE\${ MUI_PRODUCT }" "Install_Dir" "$INSTDIR"
WriteRegStr HKLM "SOFTWARE\${ MUI_PRODUCT }" "Installer Language" $LANGUAGE

;==============================
; 7.3 写入到“注册表” (* 进阶)
;
; 下面这段注册表值,只是在 { 控制台 &line; 新增移除程式] 花俏用的。
; 如果看不懂,可以全部不使用。
;
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${ MUI_PRODUCT }" \

"DisplayIcon" "$INSTDIR\app\${ PROGMAINEXE }"
; "DisplayIcon" "$INSTDIR\${ PROGMAINEXE }" ; 一般使用这个型态。只有 MDaemon 例外。
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${ MUI_PRODUCT }" \

"DisplayName" "${ MUI_PRODUCT } ${ VER_1 }.${ VER_2 } ${ PATCHTYPE_ENU }"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${ MUI_PRODUCT }" \

"DisplayVersion" "${ VER_1 }.${ VER_2 }"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${ MUI_PRODUCT }" \

"UninstallString" "$INSTDIR\uninstall.exe"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${ MUI_PRODUCT }" \

"URLInfoAbout" "http://www.altn.com/Products/Default.asp?product_id=MDaemon"

WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${ MUI_PRODUCT }" \

"Contact" "kiiali@cpatch.org"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${ MUI_PRODUCT }" \

"HelpLink" "http://www.altn.com/Support/Default.asp?product_id=MDaemon"

WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${ MUI_PRODUCT }" \

"URLUpdateInfo" "http://www.altn.com/Download/Default.asp"

WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${ MUI_PRODUCT }" \

"Readme" "$INSTDIR\${ README_CHT }"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${ MUI_PRODUCT }" \

"Comments" "Chinese (P.R.C.) and Chinese (Taiwan) ${ MUI_PRODUCT } localized version by Kii Ali, for Mailer Daemon with win32 plateform."

WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${ MUI_PRODUCT }" \

"Publisher" "Copyright (c) 2002, Alt-N Technology."

;==============================
; 7.4 依照各种语言,自动写入不同的注册表值 (* 进阶)
; 包括 ENU/CHT/CHS
;------------------------------------------
!macro MUI_REGMUI1 LANGID TEXT

StrCmp $LANGUAGE ${ LANGID } "" +3
${ TEXT }

!macroend

!insertmacro MUI_REGMUI1 1033 'WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${ MUI_PRODUCT }" "Comments" "Chinese (P.R.C.) and Chinese (Taiwan) ${ MUI_PRODUCT } localized version by Kii Ali, for Mailer Daemon with win32 plateform."
'
!insertmacro MUI_REGMUI1 1028 'WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${ MUI_PRODUCT }" "Comments" "中文 (中国大陆) 与 中文 (台湾) ${ MUI_PRODUCT } 本地化版本,由 Kii Ali 制作,用于 win32 平台架设个人或公司的信件伺服器。" '

!insertmacro MUI_REGMUI1 2052 'WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${ MUI_PRODUCT }" "Comments" "笢恅 (笢弊湮翻) 迵 笢恅 (怢俜) ${ MUI_PRODUCT } 挂华赵唳挂ㄛ蚕 Kii Ali 秶钎ㄛ蚚衾 win32 Ⅸ;怢殇扢跺?;么鼠侗腔蛔璃督昢け;﹝" '

;==============================
; 7.5 依照各种语言,自动写入不同的注册表值 (* 进阶)
; 包括 ENU/CHT/CHS
;------------------------------------------
!macro MUI_REGMUI2 LANGID TEXT

StrCmp $LANGUAGE ${ LANGID } "" +3
${ TEXT }

!macroend
!insertmacro MUI_REGMUI2 1033 'WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${ MUI_PRODUCT }" "Publisher" "Copyright (c) 2002, Alt-N Technology." '

!insertmacro MUI_REGMUI2 1028 'WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${ MUI_PRODUCT }" "Publisher" "版权所有 (c) 2002, Alt-N Technology. " '

!insertmacro MUI_REGMUI2 2052 'WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${ MUI_PRODUCT }" "Publisher" "唳?;垀衄 (c) 2002, Alt-N Technology." '

;------------------------------------------

;==============================
; 7.6 现在写入“解除安装程式”

; 写入语言名称到注册表 (用于解除安装程式)
WriteRegStr HKLM "Software\${ MUI_PRODUCT }" "Installer Language" $LANGUAGE
WriteUninstaller "$INSTDIR\Uninstall.exe"

SectionEnd

;==============================
; 7.8 显示“完成”标头

;如果不想使用“完成”页面,在这个巨集之后插入。

!insertmacro MUI_SECTIONS_FINISHHEADER

;=======================================================
; ■8.描述功能
;=======================================================
;==============================
; 8.1 描述功能的巨集 (* 进阶)
;
; 如果有描述,最好一个一个加入巨集。
; 这一段要在所有的 section 之后,否则会出现“变数名称没有找到”。
; 如果 MUI_FUNCTIONS_DESCRIPTION_BEGIN 拆成两段,会变成重覆呼叫,而导致错误。

!insertmacro MUI_FUNCTIONS_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${ SecMDaemon } $(DESC_SecMDaemon)
!insertmacro MUI_DESCRIPTION_TEXT ${ SecMDaemonDocs } $(DESC_SecMDaemonDocs)
!insertmacro MUI_DESCRIPTION_TEXT ${ SecWorldClient } $(DESC_SecWorldClient)
!insertmacro MUI_DESCRIPTION_TEXT ${ SecWebConfig } $(DESC_SecWebConfig)
!insertmacro MUI_DESCRIPTION_TEXT ${ SecStartMenu } $(DESC_SecStartMenu)
; !insertmacro MUI_DESCRIPTION_TEXT ${ SecQuicklaunch } $(DESC_SecQuicklaunch)
!insertmacro MUI_DESCRIPTION_TEXT ${ SecDesktop } $(DESC_SecDesktop)
!insertmacro MUI_DESCRIPTION_TEXT ${ SecCreateUninst } $(DESC_SecCreateUninst)
; !insertmacro MUI_DESCRIPTION_TEXT ${ SecRightMouse } $(DESC_SecRightMouse)
!insertmacro MUI_FUNCTIONS_DESCRIPTION_END
;
;==============================
; 8.2 每个节段的描述文字,直接使用各国语言 (* 进阶)
;
; 这是让滑鼠移动到安装项目上时,自动出现的描述功能。
; 我使用 ENU/CHT/CHS 三个语言。如果嫌麻烦,可以只使用一个语言,甚至不使用描述。

LangString DESC_SecMDaemon ${ LANG_ENGLISH } "MDaemon Server Main Prog"
LangString DESC_SecMDaemonDocs ${ LANG_ENGLISH } "Related Documents, manuals"
LangString DESC_SecWorldClient ${ LANG_ENGLISH } "Server: reading your emails on browser"

LangString DESC_SecWebConfig ${ LANG_ENGLISH } "config server on browser"
LangString DESC_SecStartMenu ${ LANG_ENGLISH } "Add icon to Start Menu"
LangString DESC_SecQuicklaunch ${ LANG_ENGLISH } "Add icon to QuickLaunch"
LangString DESC_SecDesktop ${ LANG_ENGLISH } "Add icon to Desktop"
LangString DESC_SecRightMouse ${ LANG_ENGLISH } "Add function of mouse right-click"

LangString DESC_SecCreateUninst ${ LANG_ENGLISH } "Create Uninstaller"

LangString DESC_SecMDaemon ${ LANG_TRADCHINESE } "MDaemon 伺服器主程式"
LangString DESC_SecMDaemonDocs ${ LANG_TRADCHINESE } "相关的文件、手册"
LangString DESC_SecWorldClient ${ LANG_TRADCHINESE } "浏览器网页读取信件的伺服器"
LangString DESC_SecWebConfig ${ LANG_TRADCHINESE } "在浏览器组态伺服器"
LangString DESC_SecStartMenu ${ LANG_TRADCHINESE } "加入图示到开始功能表"
LangString DESC_SecQuicklaunch ${ LANG_TRADCHINESE } "加入图示到快速启动列"
LangString DESC_SecDesktop ${ LANG_TRADCHINESE } "加入图示到桌面"
LangString DESC_SecRightMouse ${ LANG_TRADCHINESE } "加入滑鼠右键功能"
LangString DESC_SecCreateUninst ${ LANG_TRADCHINESE } "建立解除安装程式"

LangString DESC_SecMDaemon ${ LANG_SIMPCHINESE } "MDaemon 督昢け;翋最唗"
LangString DESC_SecMDaemonDocs ${ LANG_SIMPCHINESE } "眈寿腔恅璃﹜忒聊"
LangString DESC_SecWorldClient ${ LANG_SIMPCHINESE } "銡拟け;厍珜黍?;蛔璃腔督昢け;"
LangString DESC_SecWebConfig ${ LANG_SIMPCHINESE } "婓銡拟け;餍离督昢け;"
LangString DESC_SecStartMenu ${ LANG_SIMPCHINESE } "氖楼芞梓善※羲宎§粕等"
LangString DESC_SecQuicklaunch ${ LANG_SIMPCHINESE } "氖楼芞梓善办厒ぎ;雄蹈"
LangString DESC_SecDesktop ${ LANG_SIMPCHINESE } "氖楼芞梓善袤拨"
LangString DESC_SecRightMouse ${ LANG_SIMPCHINESE } "氖楼扷梓衵莹髡夔"
LangString DESC_SecCreateUninst ${ LANG_SIMPCHINESE } "斐膘贱壶假蚾最唗"

;=======================================================
; ■9.解除安装程式,真正的动作
;=======================================================
; 这个部分,和前面的建立 CreateUninst ,意味不一样喔。
; 前者: 把 uninstaller 程式做出来。
; 后者: 指定这个程式,要删除那些档案/目录/注册表项。
;==============================
; 9.1 节段开始

Section "Uninstall"

; 要移除掉解除安装程式
Delete "$INSTDIR\Uninstall.exe"
; 移除档案
Delete "$INSTDIR\App\*.*"
Delete "$INSTDIR\Logs\*.*"
Delete "$INSTDIR\docs\api\CreateUser\*.*"
Delete "$INSTDIR\docs\api\IterateUsers\*.*"
Delete "$INSTDIR\docs\api\Sample COM\MDUserEdit\*.*"
Delete "$INSTDIR\docs\api\Sample COM\*.*"
Delete "$INSTDIR\docs\api\*.*"
Delete "$INSTDIR\docs\*.*"
Delete "$INSTDIR\cgi\*.*"
Delete "$INSTDIR\ARCHIVES\*.*"
Delete "$INSTDIR\BACKUP\*.*"
Delete "$INSTDIR\BADMSGS\*.*"
Delete "$INSTDIR\CFILTER\*.*"
Delete "$INSTDIR\DIGESTS\*.*"
Delete "$INSTDIR\GATEWAYS\*.*"
Delete "$INSTDIR\LOCALQ\LNDOMAIN\*.*"
Delete "$INSTDIR\LOCALQ\*.*"
Delete "$INSTDIR\LOGS\*.*"
Delete "$INSTDIR\PUBLIC~1\*.*"
Delete "$INSTDIR\RAWFILES\*.*"
Delete "$INSTDIR\REMOTEQ\RETRY\*.*"
Delete "$INSTDIR\REMOTEQ\*.*"
Delete "$INSTDIR\SMTPIN\*.*"
Delete "$INSTDIR\WCstandard\HTML\help\*.*"
Delete "$INSTDIR\WCstandard\HTML\*.*"
Delete "$INSTDIR\WCstandard\Temp\*.*"
Delete "$INSTDIR\WCstandard\Templates\*.*"
Delete "$INSTDIR\WCstandard\*.*"
Delete "$INSTDIR\webconfig\HTML\*.*"
Delete "$INSTDIR\webconfig\Temp\*.*"
Delete "$INSTDIR\webconfig\Templates\*.*"
Delete "$INSTDIR\webconfig\*.*"
Delete "$INSTDIR\*.*"

; 移除开始功能表、桌面、快递启动等捷径。
Delete "$SMPROGRAMS\${ MUI_PRODUCT }\*.*"
Delete "$DESKTOP\${ MUI_PRODUCT }.lnk"
Delete "$QUICKLAUNCH\${ MUI_PRODUCT }.lnk"
RMDir "$SMPROGRAMS\${ MUI_PRODUCT }"

; 移除使用过的目录。
RMDir "$INSTDIR\App"
RMDir "$INSTDIR\Logs"
RMDir "$INSTDIR\docs\api\CreateUser"
RMDir "$INSTDIR\docs\api\IterateUsers"
RMDir "$INSTDIR\docs\api\Sample COM\MDUserEdit"
RMDir "$INSTDIR\docs\api\Sample COM"
RMDir "$INSTDIR\docs\api"
RMDir "$INSTDIR\docs"
RMDir "$INSTDIR\cgi"
RMDir "$INSTDIR\ARCHIVES"
RMDir "$INSTDIR\BACKUP"
RMDir "$INSTDIR\BADMSGS"
RMDir "$INSTDIR\CFILTER"
RMDir "$INSTDIR\DIGESTS"
RMDir "$INSTDIR\GATEWAYS"
RMDir "$INSTDIR\LOCALQ\LNDOMAIN"
RMDir "$INSTDIR\LOCALQ"
RMDir "$INSTDIR\LOGS"
RMDir "$INSTDIR\PUBLIC~1"
RMDir "$INSTDIR\RAWFILES"
RMDir "$INSTDIR\REMOTEQ\RETRY"
RMDir "$INSTDIR\REMOTEQ"
RMDir "$INSTDIR\SMTPIN"
RMDir "$INSTDIR\WCstandard\HTML\help"
RMDir "$INSTDIR\WCstandard\HTML"
RMDir "$INSTDIR\WCstandard\Temp"
RMDir "$INSTDIR\WCstandard\Templates"
RMDir "$INSTDIR\WCstandard"
RMDir "$INSTDIR\webconfig\HTML"
RMDir "$INSTDIR\webconfig\Temp"
RMDir "$INSTDIR\webconfig\Templates"
RMDir "$INSTDIR\webconfig"
RMDir "$INSTDIR"

; 删除 windows 注册表之中的安装路径
DeleteRegKey HKLM SOFTWARE\${ MUI_PRODUCT }

; 删除 windows 注册表的解除安装
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${ MUI_PRODUCT }"

; 删除 uninstaller 使用的语言名称 (* 进阶)
DeleteRegvalue HKLM "Software\${ MUI_PRODUCT }" "Installer Language"

;显示“完成”标头 (* 进阶)
!insertmacro MUI_UNFINISHHEADER

SectionEnd

;==============================
; 9.2 解除安装程式,初始化函式动作 (* 进阶)

Function un.onInit

;从注册表取得语言名称
ReadRegStr $LANGUAGE HKLM "Software\${ MUI_PRODUCT }" "Installer Language"

FunctionEnd

;=======================================================
; ■eof 档案结尾

3...
NSIS 确实是一个不错的安装程序制作软件。新版本 2.0a7 真正实现了中文支持和支持 WinXP 的安装对话框。不过要用它实现漂亮的安装界面和完美的安装功能就必须好好的写脚本。而 NSIS 的脚本指令是在是太多了,有时候觉得好像又回到了学习 C 语言的年代。他丰富而起强大的功能甚至可以编译出一些小而使用的软件(例如查找窗口句柄,然后...)好了,不多说。我在这里着重介绍关于 NSIS 的一些使用问题以及新界面安装程序的制作过程,中间会附上一个示例脚本。

这里只说单语言的简体中文

1. NSIS的运行问题
2.0a7 的 NSIS 安装在长文件名的目录中好像会有问题(Win2k 和 WinXP 下,Win98 下好像没问题)。你若是将NSIS 安装在类似于“E:\System\Installer\NSIS 的目录中”(其中的“Installer”是超过了 8 个字符的长文件名),运行 makensisw 或是直接在命令提示符中使用 makensis 可能会非法操作。

解决的办法是:在命令提示符下使用如下指令:

cd E:\System\Instal~1\NSIS
进入 NSIS 安装目录后使用命令行:

makensis /CD /X"Compressor bzip2" "f:\1.nsi"

你可以在脚本文件中使用了“SetCompressor bzip2”指令,这样就可以去掉“/X"Compressor bzip2"”参数。使用 makensisw 的朋友我就不多说了,你可以从我上面的分析中得到点启发。自己设置一下它的运行参数吧!不过 makensisw 也有 Bug,若用 makensisw 编译时发现脚本错误,程序就立马非法操作。

2. 关于脚本的整体布局
说 NSIS 有些象高级语言的语法一点没错。NSIS 的语法非常注重先后顺序(我曾经为了一个指令的先后顺序来回 Ctrl+C & Ctrl+V 了 N 次)。例如象它的帮助文件中提到的“SetFont”指令必须在“AddBrandingImage”指令之前等。我在这里要说的而是关于如何正确的对脚本进行整体布局,使其能更加合理、高效的被使用,这样才有利于日后的安装程序更新

你可以用我后面的示例脚本为模板制作自己的 NSIS 脚本。

大体布局如下:

//////////////////////////////////////////////////////////////

预设参数(包括外部压缩器选择、编译选项、宏定义以及文件包含等)

普通安装设置

自定义函数

安装程序区域内容

安装程序回调函数及其相关函数定义

卸载程序区域内容

卸载程序回调函数及其相关函数定义

//////////////////////////////////////////////////////////////

3. 关于安装程序 Logo 画面的说明:
先前版本的 NSIS 使用 splash.exe 制作 logo画面,但若您使用 2.0a7,
我建议您使用(好像也只能使用)magiclime.exe,它在 Win2k 和 WinXP
下显示 logo画面时会有淡入淡出的效果。超 Cool....

4. 关于标牌位图(即显示在安装程序对话框中的自定义位图)的说明:
2.0a7 提供了宏指令用于在安装程序的对话框中显示标牌位图。当然你也可以用标准的 NSIS 指令。

5. 关于使用新的 Modern UI 界面的说明:
2.0a7 同样提供了宏指令使你可以使用全新的安装界面:
首先你需要安装 NSIS v2.0a7 简体中文补丁(汉化新世纪有下载):
然后打开安装目录下的 Examples\Modern UI\ModernUI.nsh 文件,将从
!macro MUI_INTERFACE UI ICON UNICON CHECKS PROGRESSBAR
到第一个
!macroend
之间的注释符(即分号)删除(若没有这步究省了)。保存。
接下来就可以在你自己的脚本中使用形式对话框了,并且支持 WinXP 的新的视觉效果样式。

6. 以下是我的示例脚本:

////////////////////////////////////////////////////////////////////////////
; study.nsi
;
; 以下脚本用以生成 study.exe 文件
; 它包含有授权协议
;
; 安装时若发现应用程序正在运行,安装程序会提示并替用户关闭应用程序
; 安装成功后会自动运行应用程序
;
; 启用新的 Modern UI 的宏指令语法,原先的部分指令将被禁止以防止重复
; 我会尽量展示如何基本指令的用法。当然宏指令也会与一些基本指令发生重
; 复定义的情况,不过 NSIS 照样能编译成功.
; 其中的一些路径、文件你可以根据需要更改

; 启用外部压缩工具(这里我们不用,原因看第 10 步)
;!define HAVE_UPX

; 若启用了外部压缩工具,这进行可执行文件头的压缩
!ifdef HAVE_UPX
; 用 UPX 压缩可执行文件头(用其他的相关工具也行)
!packhdr tmp.dat "E:UPX\upx --best tmp.dat"
!endif

; 编译选项

; 设置覆盖标记
SetOverwrite on
; 设置压缩选项
SetCompress auto
; 选择压缩方式
SetCompressor bzip2
; 设置数据块优化
SetDatablockOptimize on
; 设置数据写入时间
SetDateSave on

; 相关数据预设

; 软件的名字,后面的${ NAME }调用这个名字
!define NAME "NSIS"
!define NAME_FULL "全方位掌握 NSIS 的使用"
!verbose 3
; 包含窗口消息定义文件
!include "${ NSISDIR }\Examples\WinMessages.nsh"
; 包含新界面的宏指令文件
!include "${ NSISDIR }\Examples\Modern UI\ModernUI.nsh"
; 包含标牌位图宏指令文件
!include "${ NSISDIR }\Examples\branding.nsh"
!verbose 4
!define CURRENTPAGE $9
!define TEMP1 $R0
!define TEMP2 $R1

; 插入安装界面宏定义(这里我禁用了,启用也没问题。编译照样通过。后面我都定义过了)
;!insertmacro MUI_INTERFACE "modern2.exe" "adni18-installer-C-no48xp.ico" "adni18-uninstall-C-no48xp.ico" "modern.bmp" "smooth"

; 安装程序设置

; 输出文件
OutFile "F:\study.exe"
; 安装程序名称
Name /LANG=2052 "NSIS"
; 替换对话框样式
ChangeUI all "${ NSISDIR }\Contrib\UIs\modern2.exe"
; 启用 WindowsXP 的视觉样式
XPstyle on
;设置字体
SetFont 宋体 9
; 标题名称
Caption /LANG=2052 "全方位掌握 NSIS 的使用"
; 标牌的内容
BrandingText /LANG=2052 /TRIMCENTER "Shao Hao"
; 安装程序图标
Icon "F:\12\QCDIcon.ico"
; 安装程序显示标题
WindowIcon on
; 添加标牌位图(放在顶部用 TOP 参数。后面接高度)
AddBrandingImage LEFT 105
; 设定渐变背景
BGGradient off
; 设置安静安装模式
;SilentInstall normal
; 设置安静卸载模式
;SilentUnInstall normal
; 执行 CRC 检查(最好用 on 打开。关闭是因为还要修改安装程序,看第 10 步)
CRCCheck off
; 加载相应的语言文件
LoadLanguageFile "${ NSISDIR }\Contrib\Language files\SimpChinese.nlf"
; 替换各个对话框标题的文字
SubCaption /LANG=2052 0 "授权协议"
SubCaption /LANG=2052 1 "安装选项"
SubCaption /LANG=2052 2 "安装目录"
SubCaption /LANG=2052 3 "正在安装"
SubCaption /LANG=2052 4 "完成安装"
; 替换默认按钮的文字
MiscButtonText /LANG=2052 "< 上一步" "下一步 >" "取消" "关闭"
; 替换“安装”按钮的文字
;InstallButtonText /LANG=2052 "安装"
; 替换当文件无法被写入时的警告窗的文字
FileErrorText /LANG=2052 "无法写入文件$\r$\n$0$\r$\n请确认文件属性不是只读且未被使用中!"

; 默认的安装目录
InstallDir "$PROGRAMFILES\QCD 3"
; 如果可能的化从注册表中监测安装路径
InstallDirRegKey HKLM \
"Software\Microsoft\Windows\CurrentVersion\Uninstall\NSIS" \
"UninstallString"

; 授权协议页面
LicenseText /LANG=2052 "NSIS 是免费软件。安装前请先阅读以下协议条款" "我同意"
; 使用授权协议文本
LicenseData /LANG=2052 "F:\12\License.txt"
; 设置授权协议页面的背景色
;LicenseBkColor 000000

; 选择要按安装的组件
ComponentText /LANG=2052 "现在将安装 ${ NAME_FULL }到您的计算机:" "请选择安装类型" "或选择您希望安装的组件"
InstType "完全安装(都在了)"
InstType "典型安装"
InstType /LANG=2052 /CUSTOMSTRING=自定义
;InstType /LANG=2052 /NOCUSTOM
;InstType /COMPONENTSONLYONCUSTOM
CheckBitmap "${ NSISDIR }\Contrib\Icons\modern.bmp"
; 替换显示磁盘空间信息的文字
SpaceTexts /LANG=2052 "所需空间:" "可用空间:"

; 提示用户输入目录的文本
; DirShow hide
; 替换显示选择安装目录的文字
DirText /LANG=2052 "请选择 ${ NAME } 的安装路径:" "选择目录用以安装 ${ NAME }:" "浏览..."
; 是否允许安装在根目录下
AllowRootDirInstall false

; 安装信息的颜色
;InstallColors 000000 FFFFFF
; 安装进度条显示方式
InstProgressFlags smooth colored
; 完成后自动关闭安装程序
AutoCloseWindow true
; 显示“显示详细细节”对话框
ShowInstDetails hide
; 替换“显示细节”按钮的文字
DetailsButtonText /LANG=2052 "显示细节"
; 替换“完成”按钮的文字
CompletedText /LANG=2052 "已完成"

; 卸载程序设置

; 替换卸载程序的文字
UninstallText /LANG=2052 "现在将从你的系统中卸载 ${ NAME }:" "卸载目录:"
; 卸载程序图标
UninstallIcon "F:\12\UnQCDIcon.ico"
; 替换卸载程序标题的文字
UninstallCaption /LANG=2052 "卸载 ${ NAME }"
; 替换卸载程序每页按钮的文字
UninstallSubCaption /LANG=2052 0 ":确认"
UninstallSubCaption /LANG=2052 1 ":正在删除文件"
UninstallSubCaption /LANG=2052 2 ":完成"
; 卸载程序显示方式
ShowUninstDetails hide
; 替换“卸载”按钮的文字
UninstallButtonText /LANG=2052 "卸载"

; 安装程序内容及其相关的回调函数

; 安装程序内容
Section /e "!主要程序(必须安装)" SecCore
SectionIn 1 2 RO
; 设置输出路径,每次使用都会改变
SetOutPath $INSTDIR
; 循环包含目录下全部内容
File /r "F:\12\1\*.*"
; 只包含一个文件
File "F:\12\gf.gif"
; 处理动态连接库文件
IfFileExists "$INSTDIR\1.dll" 0 NoFile1
; 取消组件注册
UnRegDll "$INSTDIR\1.dll"
Delete "$INSTDIR\1.dll"
NoFile1:
File "F:\12\1.dll"
; 注册组件
RegDLL "$INSTDIR\QCDIconMgr.dll"
; 写入软件注册键值
WriteRegStr HKLM "Software\NSIS\NSIS" "" "$INSTDIR"
; 为 Windows 卸载程序写入键值
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\NSIS" "DisplayName" "NSIS(只用于移除)"

WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\NSIS" "UninstallString" '"$INSTDIR\uninst.exe"'

; 写入生成卸载程序(可多次使用)
WriteUninstaller "$INSTDIR\uninst.exe"
SectionEnd

Section /e "扩展(可选)" SecUpdate
SectionIn 1
SetOutPath "$INSTDIR\Plugins"
File "F:\12\qcdplus\Plugins\2.dll"
File /r "F:\12\qcdplus\Plugins\3"
SectionEnd

SubSection /e "选项" SecOptions
Section /e "创建桌面图标" SecDesktopShortCut
SectionIn 1 2
SetOutPath "$INSTDIR\Plugins"
CreateShortCut "$DESKTOP\NSIS.lnk" "$INSTDIR\gf.gif"
WriteUninstaller "$INSTDIR\uninst.exe"
SectionEnd

Section /e "创建快速启动栏图标" SecQuickbarShortCut
SectionIn 1 2
SetOutPath "$INSTDIR\Plugins"
CreateShortCut "$QUICKLAUNCH\NSIS.lnk" "$INSTDIR\gf.gif"
WriteUninstaller "$INSTDIR\uninst.exe"
SectionEnd

Section /e "创建 NSIS 程序组" SecShortCutGroup
SectionIn 1 2
SetOutPath "$INSTDIR\Plugins"
CreateDirectory "$SMPROGRAMS\NSIS"
CreateShortCut "$SMPROGRAMS\QCD Player\gf.lnk" "$INSTDIR\gf.gif"
WriteUninstaller "$INSTDIR\uninst.exe"
SectionEnd
SubSectionEnd

Section "-Run"; 运行
ExecWait '"$INSTDIR\2.exe" -p'
WriteINIStr "$INSTDIR\NSIS.ini" "2" "Language" "Chinese"
Exec "$INSTDIR\2.exe"
ExecShell open "$INSTDIR\汉化说明.htm"
SectionEnd

Section ""
;Invisible section to display the Finish header
!insertmacro MUI_FINISHHEADER SetHeader
SectionEnd

; 安装程序初始化设置
Function .onInit
; 发现有程序正在运行时提示退出后继续运行
loop:
FindWindow $R0 "NSIS"
IntCmp $R0 0 done
MessageBox MB_OKCANCEL \
"NSIS 正在运行。$\n点击“确定”按钮会关闭 NSIS 然后继续安装,点击“取消”按钮将退出安装程序" \
IDOK NoAbort
Abort
NoAbort:
SendMessage $R0 1029 0 0
; 稍等后继续检测直至检测不到或用户选择取消
Sleep 444
Goto loop
done:
; 显示 Logo 画面
SetOutPath $TEMP
File /oname=qcd_logo.bmp "F:\12\logo.bmp"
File /oname=magiclime.exe "${ NSISDIR }\Bin\magiclime.exe"
ExecWait '"$TEMP\magiclime.exe" qcd_logo.bmp'
Delete "$TEMP\magiclime.exe"
Delete "$TEMP\qcd_logo.bmp"
; 初始化标牌位图
!insertmacro BI_INIT $R0
FunctionEnd

; 安装程序主界面的相关文本
Function SetHeader
!insertmacro MUI_HEADER_INIT
!insertmacro MUI_HEADER_START 1
!insertmacro MUI_HEADER_TEXT 2052 "授权协议" "安装 ${ NAME } 之前,请认真阅读一下授权条款."
!insertmacro MUI_HEADER_STOP 1
!insertmacro MUI_HEADER_START 2
!insertmacro MUI_HEADER_TEXT 2052 "选择组件" "请选择你要安装的组件."
!insertmacro MUI_HEADER_STOP 2
!insertmacro MUI_HEADER_START 3
!insertmacro MUI_HEADER_TEXT 2052 "选择安装位置" "为 ${ NAME } 选择一个安装目录."
!insertmacro MUI_HEADER_STOP 3
!insertmacro MUI_HEADER_START 4
!insertmacro MUI_HEADER_TEXT 2052 "安装" "${ NAME } 已经安装,请等待."
!insertmacro MUI_HEADER_STOP 4
!insertmacro MUI_HEADER_START 5
!insertmacro MUI_HEADER_TEXT 2052 "完成" "安装顺利完成."
!insertmacro MUI_HEADER_STOP 5
!insertmacro MUI_HEADER_END
FunctionEnd

; 初始化安装程序对话框的显示文本
Function .onInitDialog
!insertmacro MUI_INNERDIALOG_INIT
!insertmacro MUI_INNERDIALOG_START 1
!insertmacro MUI_INNERDIALOG_TEXT 2052 1040 "如果你同意协议中的所有条款,选择“我同样”继续安装,如果你选择了“取消”,安装程序将终止,只有接受条款才能安装 ${ NAME }."

!insertmacro MUI_INNERDIALOG_STOP 1
!insertmacro MUI_INNERDIALOG_START 2
!insertmacro MUI_INNERDIALOG_TEXT 2052 1042 "描述"
!insertmacro MUI_INNERDIALOG_TEXT 2052 1043 "移动你的鼠标到组件上,便可以见到相关的描述."
!insertmacro MUI_INNERDIALOG_STOP 2
!insertmacro MUI_INNERDIALOG_START 3
!insertmacro MUI_INNERDIALOG_TEXT 2052 1041 "目标文件夹"
!insertmacro MUI_INNERDIALOG_STOP 3
!insertmacro MUI_INNERDIALOG_END
FunctionEnd

; 转到下页面时的处理
Function .onNextPage
!insertmacro MUI_NEXTPAGE_OUTER
!insertmacro MUI_NEXTPAGE SetHeader
; 标牌位图设置
!insertmacro BI_NEXT
FunctionEnd

; 转到上一页面时的处理
Function .onPrevPage
!insertmacro MUI_PREVPAGE
; 标牌位图设置
!insertmacro BI_PREV
FunctionEnd

; 鼠标移到指定组件时的显示处理
Function .onMouseOverSection
; 用宏指令设置安装自己的注释文本
!insertmacro MUI_DESCRIPTION_INIT
!insertmacro MUI_DESCRIPTION_TEXT 2052 ${ SecCore } "安装主应用程序"
!insertmacro MUI_DESCRIPTION_TEXT 2052 ${ SecUpdate } "安装 NSIS 的更新或新增插件"
!insertmacro MUI_DESCRIPTION_TEXT 2052 ${ SecOptions } "选择 NSIS 的其他安装选项,例如:创建快捷方式和应用程序组的"

!insertmacro MUI_DESCRIPTION_TEXT 2052 ${ SecDesktopShortCut } "在用户的桌面上创建 NSIS 的快捷方式"

!insertmacro MUI_DESCRIPTION_TEXT 2052 ${ SecQuickbarShortCut } "在用户的快速栏里创建 NSIS 快捷方式"

!insertmacro MUI_DESCRIPTION_TEXT 2052 ${ SecShortCutGroup } "在用户的开始菜单的程序中创建 NSIS 的快捷方式组"

!insertmacro MUI_DESCRIPTION_END
FunctionEnd

; 安装成功完成后的设置
Function .onInstSuccess
; 自己加吧:)
FunctionEnd

; 放弃安装时警告窗口的显示信息
Function .onUserAbort
!insertmacro MUI_ABORTWARNING 2052 "你确定要推出 ${ NAME } 的安装吗?"
!insertmacro MUI_ABORTWARNING_END
FunctionEnd

; 安装程序标牌位图列表
!insertmacro BI_LIST
!insertmacro BI_LIST_ADD "F:\12\Brand1.bmp" /RESIZETOFIT
!insertmacro BI_LIST_ADD "F:\12\Brand2.bmp" /RESIZETOFIT
!insertmacro BI_LIST_ADD "F:\12\Brand3.bmp" /RESIZETOFIT
!insertmacro BI_LIST_END

; 卸载程序及其相关回调函数

; 卸载程序内容
Section "Uninstall"
ExecWait '"$INSTDIR\12.exe" /un'
; 循环删除文件直至删除文件夹
RMDir /r "$SMPROGRAMS\NSIS"
UnRegDLL "$INSTDIR\2.dll"
Delete "$INSTDIR\QCDIconMgr.dll"
Delete "$INSTDIR\*.*"
DeleteRegKey HKLM "Software\NSIS"
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\NSIS"
MessageBox MB_YESNO&line;MB_ICONQUESTION \
"是否连插件目录也要删除?$\n(若您要保留这些文件,请点击下面的“否”按钮)" \
IDNO NoDelete
; 全删光!!!
RMDir /r "$INSTDIR"
NoDelete:
SectionEnd

; 定义卸载程序标牌位图
!define BI_UNINSTALL
!include "${ NSISDIR }\Examples\branding.nsh"

; 初始化卸载程序对话框的设置
Function un.onInit
; 初始化标牌位图
!insertmacro BI_INIT $R0
FunctionEnd

; 卸载程序主界面的相关文本
Function un.SetHeader
!insertmacro MUI_HEADER_INIT
!insertmacro MUI_HEADER_START 1
!insertmacro MUI_HEADER_TEXT 2052 "卸载 ${ NAME }" "${ NAME_FULL } 将从你的系统里移除."
!insertmacro MUI_HEADER_STOP 1
!insertmacro MUI_HEADER_START 2
!insertmacro MUI_HEADER_TEXT 2052 "卸载" "${ NAME } 正在被卸载,请等待."
!insertmacro MUI_HEADER_STOP 2
!insertmacro MUI_HEADER_START 3
!insertmacro MUI_HEADER_TEXT 2052 "完成" "${ NAME_FULL } 已从你的系统中移除."
!insertmacro MUI_HEADER_STOP 3
!insertmacro MUI_HEADER_END
FunctionEnd

; 初始化卸载程序对话框时的处理
Function un.onInitDialog
; 自己加:)
FunctionEnd

; 卸载程序转到下一页时的处理
Function un.onNextPage
!insertmacro MUI_NEXTPAGE_OUTER
!insertmacro MUI_NEXTPAGE un.SetHe

(0)

相关推荐