NSIS学习笔记(以Qt4程序打包为例)
来源:互联网 发布:ih5软件下载 编辑:程序博客网 时间:2024/04/28 15:19
一个Qt4程序安装(发布)后它应该有如下的结构(可参考 Qt 程序在 windows 下的发布 ):
|-- sample.exe|-- QtCore4.dll|-- QtGui4.dll|-- imageformats/| |-- qjpeg4.dll
接下来我们使用nsis,来制作一个实现这个功能的安装程序(并稍作完善)
如果你还没有安装nsis,不妨马上去下载一个。
第一个脚本
要使用nsis,只需要编写一个简单的 xxx.nsi 文件:
;A simple nsis script file: sample.nsi!define QTDIR "D:/Qt/4.7.0"outfile "sample-installer.exe"installDir "$PROGRAMFILES/sample" RequestExecutionLevel adminsectionsetOutPath $INSTDIRfile sample.exefile ${QTDIR}/bin/QtCore4.dllfile ${QTDIR}/bin/QtGui4.dllsetOutPath $INSTDIR/imageformatsfile ${QTDIR}/plugins/imageformats/qjpeg4.dllsectionEnd
将该文件和我们的sample.exe 放到同一个文件夹,然后点右键,选择"编译NSIS脚本"。稍等片刻,一个安装程序 sample-installer.exe 就生成了。
知识点
- 注释
- 以分号";"或井号"#"开头的行都是注释,也可以使用C语言中的"/* */"
- 编译期命令(Compile Time Commands)
以叹号"!"开始的命令叫做编译期命令(名字比较怪,但我们将其理解成C、C++中的宏 )
- 一定要理清这一点,它只是一种扩展。
- outfile
- 给安装程序指定个名字
- installDir
- 默认将文件安装到何处
RequestExecutionLevel
- 对Vista及Win7用户,安装程序工作时需要申请执行权限
- section
- 每一个nsis脚本至少要有一个section段。段内执行我们需要的安装操作
- setOutPath
- 指定文件输出到何处
- file
- 安装哪些文件
有没有疑问?我们一开始设置了 installDir,后面使用的却是INSTDIR。installDir 和 INSTDIR 什么关系?!
INSTDIR 的值获得方式:
- 如果脚本编译时通过 /D 选项指定了路径,将使用该路径。否则,
如果从注册表读取路径到 InstallDirRegKey,将使用该路径。否则,
- 才使用installDir 指定的路径
注意:用户可以通过界面选择安装路径,也是影响的INSTDIR的值
第二个脚本
前面的脚本功能太弱了:
- 用户不能选择安装目录
- 只有安装,没有卸载功能
- 不能创建快捷方式
改进一下
安装路径
安装程序相当于是一个wizard多页面程序,我们只要添加相应的页面即可。直接在第一个section的上面添加两行:
Page directoryPage instfiles
这些都是nsis提供的标准页面。
添加卸载功能
添加卸载功能也就是要生成一个卸载程序,这个程序时安装程序安装时自动生成的。要实现这个,我们只需要在前面的section中添加一句
writeUninstaller $INSTDIR/uninstaller.exe
那么该卸载程序执行什么动作呢?这需要我们添加一个新的段:
section "Uninstall"rmDir /r "$INSTDIR"sectionEnd
快捷方式
常见的两类:
一个是在桌面上
createShortCut "$DESKTOP/sample.lnk" "$INSTDIR/sample.exe"
一个是在开始菜单的"程序"中。
createShortCut "$SMPROGRAMS/sample.lnk" "$INSTDIR/sample.exe"
很直观,直接放到section段中即可。程序卸载时需要删除快捷方式,故在uninstall段中需要添加形影的删除指令。
关于createShortCut的详细信息看Manual:
link.lnk target.file [parameters [icon.file [icon_index_number [start_options [keyboard_shortcut [description]]]]]]
可以设置图标、命令行参数、快捷键、描述等等。
完整代码
!define QTDIR "D:/Qt/4.7.0"outfile "sample-installer.exe"installDir "$PROGRAMFILES/sample" RequestExecutionLevel adminPage directoryPage instfilessectionsetOutPath $INSTDIRfile sample.exefile ${QTDIR}/bin/QtCore4.dllfile ${QTDIR}/bin/QtGui4.dllsetOutPath $INSTDIR/imageformatsfile ${QTDIR}/plugins/imageformats/qjpeg4.dllcreateShortCut "$DESKTOP/sample.lnk" "$INSTDIR/sample.exe"createShortCut "$SMPROGRAMS/sample.lnk" "$INSTDIR/sample.exe"writeUninstaller $INSTDIR/uninstaller.exesectionEndsection "Uninstall"rmDir /r "$INSTDIR"delete "$DESKTOP/sample.lnk"delete "$SMPROGRAMS/sample.lnk"sectionEnd
知识点
page
- 用来添加页面
- 还有一个灵活一些的 pageEx 命令
- 卸载程序的页面可以使用uninstPage 命令指定
section
- 每一个NSIS安装脚本包含至少一个section
- 每一个section包含0条或多条指令
- 各个section按顺序执行(运行中可以禁用启用某些section)
- 名字为"Uninstall"或者以"un."为前缀的section,属于卸载程序
第三个脚本
第二个例子可以工作了,但是有很不爽的一点,我们还一直没提:界面好丑,好老土啊!
尽管nsis 原始自带的界面不好看,但是它也提供了新式的安装界面 (它是通过宏扩展来实现的)。使用起来也是很方便,我们看看如何做:
包含新式的头文件(我们一开始就说了,叹号开头的可以类比C、C++的宏)
!include "MUI2.nsh"
插入新式页面
!insertmacro MUI_PAGE_DIRECTORY!insertmacro MUI_PAGE_INSTFILES
卸载页面类似(PAGE和UNPAGE的区别)
!insertmacro MUI_UNPAGE_CONFIRM!insertmacro MUI_UNPAGE_INSTFILES
由于新式页面提供了友好的多语言支持,我们选择简体中文
!insertmacro MUI_LANGUAGE "SimpChinese"
完整代码
!include "mui2.nsh"!define QTDIR "D:/Qt/4.7.0"outfile "sample-installer.exe"installDir "$PROGRAMFILES/sample" RequestExecutionLevel admin;Page directory;Page instfiles!insertmacro MUI_PAGE_DIRECTORY!insertmacro MUI_PAGE_INSTFILES!insertmacro MUI_LANGUAGE "SimpChinese"sectionsetOutPath $INSTDIRfile sample.exefile ${QTDIR}/bin/QtCore4.dllfile ${QTDIR}/bin/QtGui4.dllsetOutPath $INSTDIR/imageformatsfile ${QTDIR}/plugins/imageformats/qjpeg4.dllcreateShortCut "$DESKTOP/sample.lnk" "$INSTDIR/sample.exe"createShortCut "$SMPROGRAMS/sample.lnk" "$INSTDIR/sample.exe"writeUninstaller $INSTDIR/uninstaller.exesectionEndsection "Uninstall"rmDir /r "$INSTDIR"delete "$DESKTOP/sample.lnk"delete "$SMPROGRAMS/sample.lnk"sectionEnd
函数
前一个已经工作的很好了,但是我们可能有其他的要求。接下来我们只看代码片段和重要的概念:
前面一直没涉及nsis的另一个重要的概念:函数(functions)。
- 函数和我们前面的段比较相似,都是包含需要执行的指令,不同之处在于section会被直接执行。而函数则需要调用。
- 按调用方式它可分两类,一是被直接调用的函数,另一类则称为回调函数。
直接调用
很简单,我们看下面的代码片段即可。
Function func ;some commandsFunctionEndSection Call funcSectionEnd
回调
回调函数在特定的时候被安装程序调用,比如 .onInit 在初始化时会被调用。
这时我们可以弹出一个对话框
Function .onInit MessageBox MB_YESNO "This will install. Continue?" IDYES NoAbort Abort ; NoAbort: FunctionEnd
提示用户是否继续。
更有用的一点可能是,我们希望同一时刻只有一个安装程序在运行
Function .onInit System::Call 'kernel32::CreateMutexA(i 0, i 0, t "SAMPLE_MUTEX") i .r1 ?e' Pop $R0 StrCmp $R0 0 +3 MessageBox MB_OK|MB_ICONEXCLAMATION "Another Installer is Running!" AbortFunctionEnd
这儿用到了一个system::call,这是什么东西?
插件
在前面,我们调用了系统的api来创建一个Windows的内核对象(互斥量)。调用系统api使用的是nsis的System插件(由于不需要额外的操作,你可能没意识到它是插件)。
我们看一下Call如何使用的:
Call PROC [( PARAMS ) [RETURN [? OPTIONS]]]
对照一下!
i 0, i 0, t "SAMPLE_MUTEX"
PARAMS
函数参数(类型和值)
i .r1
RETURN
返回值
?e
? OPTIONS
选项e,可执行程序的路径
注意,参数和返回值,其实都是3个值一组(类型、(source)值、(destination)值)。返回值中的.代表忽略source值。
除了system插件,nsis自带的还有进行数学运算的math,自定义界面的nsDialog插件等等。
LogicLib
我们前面涉及到了 StrCmp $R0 0 +3 ,这是神马用法??
流程控制真的让人头疼,用标签和相对位置进行跳转,给人一种汇编语言的感觉。看看下面的例子:
StrCmp $0 'some value' 0 +3 MessageBox MB_OK '$$0 is some value' Goto doneStrCmp $0 'some other value' 0 +3 MessageBox MB_OK '$$0 is some other value' Goto done# else MessageBox MB_OK '$$0 is "$0"'done:
一不小心数错行,或者增减语句,可都不是小事情了。
幸好,nsis可以通过类似宏的机制扩展,而且也提供了一个 logiclib.nsh 文件。这样一来,我们处理分支或循环就简单多了(尽管语法少多有点别扭,没办法,毕竟不是内置支持的东西)
${If} $0 == 'some value' MessageBox MB_OK '$$0 is some value'${ElseIf} $0 == 'some other value' MessageBox MB_OK '$$0 is some other value'${Else} MessageBox MB_OK '$$0 is "$0"'${EndIf}
其他
文本只是一个学习笔记,很多东西都没有涉及(manual中很详细哈,遇到问题应该首先去查manual)。
http://nsis.sourceforge.net/Docs/
转自:http://blog.csdn.net/dbzhang800/article/details/6411870
- NSIS学习笔记(以Qt4程序打包为例)
- NSIS学习笔记(以Qt4程序打包为例)
- NSIS学习笔记(以Qt4程序打包为例)
- NSIS学习笔记(以Qt4程序打包为例)
- NSIS 封装打包程序 学习笔记 (一)
- NSIS 封装打包程序 学习笔记 (三)
- Qt学习 使用NSIS打包程序
- NSIS 封装打包程序 学习笔记 (二)NSIS常见问题集锦 推荐新手参考学习 (转)
- nsis打包安装程序
- 使用NSIS 打包程序
- 使用nsis打包程序
- NSIS打包发布Qt程序
- 程序打包 之 NSIS脚本
- 如何用NSIS打包程序
- 关于NSIS脚本打包程序
- NSIS打包应用学习记
- NSIS学习笔记
- NSIS学习笔记
- TCP/IP协议分析--数据链路
- Servlet的Request.getInputStream()只能读取一次问题
- 分析一个文本文件中各个词出现的频率,并把频率最高的十个单词打印出来。
- android第一次
- android基础之html
- NSIS学习笔记(以Qt4程序打包为例)
- ASIHTTPRequest实现https双向认证请求
- Mybatis事务详细配置 (SqlSessionDaoSupport方式, 已经经过验证 )
- android基础之css
- Android 和 iOS 各有千秋
- 好老师 (湖南省第九届大学生计算机程序设计竞赛)
- 二叉树的生成与遍历
- Segmentation fault到底是何方妖孽
- 三色旗