NSIS学习笔记(以Qt4程序打包为例)

33 篇文章 8 订阅

一个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 admin

section
setOutPath $INSTDIR
file sample.exe
file ${QTDIR}/bin/QtCore4.dll
file ${QTDIR}/bin/QtGui4.dll

setOutPath $INSTDIR/imageformats
file ${QTDIR}/plugins/imageformats/qjpeg4.dll
sectionEnd

将该文件和我们的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 directory
Page 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 admin

Page directory
Page instfiles

section
setOutPath $INSTDIR
file sample.exe
file ${QTDIR}/bin/QtCore4.dll
file ${QTDIR}/bin/QtGui4.dll

setOutPath $INSTDIR/imageformats
file ${QTDIR}/plugins/imageformats/qjpeg4.dll

createShortCut "$DESKTOP/sample.lnk" "$INSTDIR/sample.exe"
createShortCut "$SMPROGRAMS/sample.lnk" "$INSTDIR/sample.exe"

writeUninstaller $INSTDIR/uninstaller.exe
sectionEnd

section "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"

section
setOutPath $INSTDIR
file sample.exe
file ${QTDIR}/bin/QtCore4.dll
file ${QTDIR}/bin/QtGui4.dll

setOutPath $INSTDIR/imageformats
file ${QTDIR}/plugins/imageformats/qjpeg4.dll

createShortCut "$DESKTOP/sample.lnk" "$INSTDIR/sample.exe"
createShortCut "$SMPROGRAMS/sample.lnk" "$INSTDIR/sample.exe"

writeUninstaller $INSTDIR/uninstaller.exe
sectionEnd

section "Uninstall"
rmDir /r "$INSTDIR"
delete "$DESKTOP/sample.lnk"
delete "$SMPROGRAMS/sample.lnk"
sectionEnd

函数

前一个已经工作的很好了,但是我们可能有其他的要求。接下来我们只看代码片段和重要的概念:

前面一直没涉及nsis的另一个重要的概念:函数(functions)。

  • 函数和我们前面的段比较相似,都是包含需要执行的指令,不同之处在于section会被直接执行。而函数则需要调用。
  • 按调用方式它可分两类,一是被直接调用的函数,另一类则称为回调函数。

直接调用

很简单,我们看下面的代码片段即可。

Function func
  ;some commands
FunctionEnd

Section
  Call func
SectionEnd

回调

回调函数在特定的时候被安装程序调用,比如 .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!"
   Abort
FunctionEnd

这儿用到了一个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 done
StrCmp $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)。

  • 2
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
### 回答1: 将Qt程序打包成安装包的过程可以分为以下几个步骤: 1. 准备好Qt程序的可执行文件和所需的依赖文件。确保程序可以在目标机器上独立运行,并且没有缺失的依赖项。 2. 创建一个安装目录,用于存放将要打包的文件。可以自定义目录结构,例如bin目录用于存放可执行文件,lib目录用于存放依赖库等。 3. 将Qt程序的可执行文件和依赖文件复制到安装目录中。确保文件路径与原本程序的路径一致。 4. 创建一个安装脚本或者使用Qt提供的打包工具,例如Qt Installer Framework。安装脚本可以定义安装过程中需要执行的操作,例如创建快捷方式、添加环境变量等。如果使用Qt Installer Framework,可以使用其提供的界面编辑器创建安装向导界面。 5. 对安装目录进行压缩,生成安装包。可以选择使用zip、tar或者其他的压缩格式。确保生成的安装包可以在目标机器上解压缩。 6. 将安装包进行测试,在目标机器上进行安装和运行测试,确保打包程序能够正常工作。 总结起来,将Qt程序打包成安装包的过程包括准备程序和依赖文件、创建安装目录、复制文件到安装目录、编写安装脚本或使用打包工具、压缩安装目录并进行测试。 ### 回答2: Qt是一个跨平台的C++开发框架,可以方便地开发出图形界面应用程序Qt程序可以通过打包成安装包的方式进行分发和安装,以便用户可以方便地安装和使用。 Qt提供了一个工具Qt Installer Framework来创建安装包。使用该工具,我们可以按照以下步骤打包Qt程序成安装包: 1. 首先,我们需要创建一个安装包项目。在创建项目的过程中,我们需要提供一些基本信息,例如程序名称、版本号、制造商等等。这些信息都会在安装包中显示。 2. 接下来,我们需要定义安装包的组织结构。这包括安装目录、文件和文件夹的布局,以及依赖关系。我们可以自定义安装目录的结构,将文件和文件夹放置在适当的位置。 3. 然后,我们可以添加预定义的安装步骤,例如许可协议的接受、安装路径选择、组件选择等等。这些步骤将在安装过程中显示给用户。 4. 我们还可以自定义安装包的界面。Qt Installer Framework提供了一个XML文件来定义安装包的界面,我们可以根据需要进行修改和定制。 5. 完成以上步骤后,我们可以使用Qt Installer Framework提供的工具将安装包编译为可执行文件。这个可执行文件就是我们最终生成的安装包。 最后,我们可以将生成的安装包分发给用户,让用户可以方便地进行安装和使用。 总而言之,通过使用Qt Installer Framework,我们可以方便地将Qt程序打包成安装包,以方便用户进行安装和使用。 ### 回答3: 要将 Qt 程序打包成安装包,可以按照以下步骤进行操作: 1. 确保在 Qt Creator 中配置好项目的构建工具,如编译器和目标平台。 2. 在 Qt Creator 中选择“发布”或“构建”选项,进入构建设置页面。 3. 在构建设置页面中,选择正确的构建配置,如Release。 4. 在构建设置页面中,选择“Windeployqt”工具,并勾选“启用”。 5. 确保 Qt Creator 能够找到 “windeployqt” 工具。通过“工具”菜单 -> “选项” -> “Kits” 设置页面,查看当前配置是否有正确的路径。 6. 点击“构建”按钮开始构建应用程序。 7. 构建完成后,进入构建输出目录,应该会有生成的可执行文件以及一些依赖的 Qt 动态链接库。 8. 运行 “windeployqt” 工具,该工具会自动查找可执行文件中使用到的 Qt 动态链接库,并将它们拷贝到一个指定目录中。 9. 拷贝完所有依赖文件后,可以将生成的这个目录压缩成一个 ZIP 文件,或者使用其他打包工具(如Inno Setup,NSIS等)制作一个安装包,按照安装包制作工具的指引进行操作。 10. 安装包制作完成后,用户可以通过安装包安装程序,并在目标机器上运行 Qt 程序。 总之,将 Qt 程序打包成安装包的关键是使用 “windeployqt” 工具自动查找和拷贝依赖的 Qt 动态链接库,然后使用打包工具将生成的文件打包成一个安装包,方便用户安装和使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值