用nsis制作安装程序

nsis安装程序是free的,通常制作一个简单的安装程序稍微熟悉学习一下够用了。

首先你需要下载 nsis基本程序,推荐到 这里 下载 。

学习模板

下面这个是利用HM nis edit 软件自动生成模板然后做了一些修改,放在下面方便学习。

; Script generated by the HM NIS Edit Script Wizard.

; HM NIS Edit Wizard helper defines
!define PRODUCT_NAME "timer"
!define PRODUCT_VERSION "1.3.1"
!define PRODUCT_PUBLISHER "wanze"
!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\timer.exe"
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
!define PRODUCT_UNINST_ROOT_KEY "HKLM"

; MUI 1.67 compatible ------
!include "MUI2.nsh"

; MUI Settings
!define MUI_ABORTWARNING
!define MUI_ICON "dist\timer\timer.ico"
!define MUI_UNICON "dist\timer\timer.ico"

; Welcome page
!insertmacro MUI_PAGE_WELCOME
; License page
!insertmacro MUI_PAGE_LICENSE "LICENSE.txt"
; Directory page
!insertmacro MUI_PAGE_DIRECTORY
; Instfiles page
!insertmacro MUI_PAGE_INSTFILES
; Finish page
!define MUI_FINISHPAGE_RUN "$INSTDIR\timer.exe"
!insertmacro MUI_PAGE_FINISH

; Uninstaller pages
!insertmacro MUI_UNPAGE_INSTFILES

; Language files
!insertmacro MUI_LANGUAGE "English"

; MUI end ------

Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
OutFile "timer_setup.exe"
InstallDir "$PROGRAMFILES\Timer"
InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""
ShowInstDetails show
ShowUnInstDetails show

Section "MainSection" SEC01
  SetOutPath "$INSTDIR"
  SetOverwrite try
  File "dist\timer\*.dll"
  File "dist\timer\base_library.zip"
  File "dist\timer\timer.ico"
  File "dist\timer\*.pyd"
  File /r "dist\timer\PySide2"
  File /r "dist\timer\shiboken2"
  File "dist\timer\timer.exe"
  CreateDirectory "$SMPROGRAMS\timer"
  CreateShortCut "$SMPROGRAMS\timer\timer.lnk" "$INSTDIR\timer.exe" "" "$INSTDIR\timer.ico"
  CreateShortCut "$DESKTOP\timer.lnk" "$INSTDIR\timer.exe" "" "$INSTDIR\timer.ico"
  File "dist\timer\timer.exe.manifest"
SectionEnd

Section -AdditionalIcons
  CreateShortCut "$SMPROGRAMS\timer\Uninstall.lnk" "$INSTDIR\uninst.exe"
SectionEnd

Section -Post
  WriteUninstaller "$INSTDIR\uninst.exe"
  WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\timer.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}" "DisplayIcon" "$INSTDIR\timer.exe"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
SectionEnd


Function un.onUninstSuccess
  HideWindow
  MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) was successfully removed from your computer."
FunctionEnd

Function un.onInit
  MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "Are you sure you want to completely remove $(^Name) and all of its components?" IDYES +2
  Abort
FunctionEnd

Section Uninstall
  Delete "$INSTDIR\uninst.exe"
  Delete "$INSTDIR\*.pyd"
  Delete "$INSTDIR\*.dll"
  Delete "$INSTDIR\timer.exe.manifest"
  Delete "$INSTDIR\timer.exe"
  RMDir /r "$INSTDIR\shiboken2"
  RMDir /r "$INSTDIR\PySide2"
  Delete "$INSTDIR\timer.ico"
  Delete "$INSTDIR\base_library.zip"
  Delete "$SMPROGRAMS\timer\Uninstall.lnk"
  Delete "$DESKTOP\timer.lnk"
  Delete "$SMPROGRAMS\timer\timer.lnk"

  RMDir "$SMPROGRAMS\timer"
  RMDir "$INSTDIR"

  DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
  DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}"
  SetAutoClose true
SectionEnd

一些基本信息

下面是定义软件名,软件版本号和软件出版人这些基本信息。

!define PRODUCT_NAME "yaogua"
!define PRODUCT_VERSION "0.1.1"
!define PRODUCT_PUBLISHER "wanze"

界面语言选择

之前如下这样设置是可行的:

!insertmacro MUI_LANGUAGE "SimpChinese"

繁体中文是 TradChinese

但是最近我将我的win10系统全局设置为UTF8编码之后,其安装界面成乱码了。可能nsis的中文编码默认不是utf8的。稳妥起见还是选择英语吧,这肯定不会出现恼人的乱码问题:

; Language files
!insertmacro MUI_LANGUAGE "English"

快捷方式加图标

用上面提到的工具自动生成的nsi脚本,默认的快捷方式向导是没有加上图标的,你可以如下加上图标:

  CreateShortCut "$SMPROGRAMS\timer\timer.lnk" "$INSTDIR\timer.exe" "" "$INSTDIR\myapp.ico"

第三个参数是可选的,命令行参数,没啥好填的。最后一个参数就是设置图标的,具体图标注意要填在文件复制到目的地操作之后,填写的值也是复制的目的地那边的哪里。

PRODUCT_DIR_REGKEY

这个应该是向windows系统注册本软件的安装目录:

!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\yaogua"

默认的输出似乎有时exe会指错。

OutFile

OutFile会控制你的输出exe的名字。

Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
OutFile "yaogua_Setup.exe"
InstallDir "$PROGRAMFILES\yaogua"
InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""

设置安装图标和删除图标

!define MUI_ICON "app.ico"
!define MUI_UNICON "app.ico"

这个应该是那个安装程序和那个删除程序 uninst.exe 的图标,前面提到的 CreateShortCut 是一些快捷方式的图标,比如桌面快捷方式。

!define

定义了一个全局变量,后面可以通过 ${what} 这样的格式来引用。

使用Modern UI

!include "MUI2.nsh"

具体看它的 文档 ,这里做了一下修改,现在是版本2了。

MUI_ABORTWARNING

当用户想要关闭安装程式则弹出一个页面。

!define MUI_ABORTWARNING

MUI_ICON

设置安装程式的图标

!define MUI_ICON "dist\timer\timer.ico"

MUI_UNICON

设置卸载时程序的图标

!define MUI_UNICON "dist\timer\timer.ico"

插入页面

如下插入页面,程序将会按照写入的顺序来展示页面。

; Welcome page
!insertmacro MUI_PAGE_WELCOME
; License page
!insertmacro MUI_PAGE_LICENSE "LICENSE.txt"
; Directory page
!insertmacro MUI_PAGE_DIRECTORY
; Instfiles page
!insertmacro MUI_PAGE_INSTFILES
; Finish page
!define MUI_FINISHPAGE_RUN "$INSTDIR\timer.exe"
!insertmacro MUI_PAGE_FINISH
!define MUI_FINISHPAGE_RUN "$INSTDIR\timer.exe"

这一行定义了用户最后完成页面选择打开程序具体是打开的那个程序。

; Uninstaller pages
!insertmacro MUI_UNPAGE_INSTFILES

这一行说明卸载程序只有一个页面。

设置语言

!insertmacro MUI_LANGUAGE "English"

可以设置多语言,后面再讨论,这里就采用默认的英语。

Name

设置安装程序的名字,后面可以使用 $(^Name) 来引用这个变量。

Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"

OutFile

设置安装程序的输出文件名。

InstallDir

设置默认的安装路径。

InstallDir "$PROGRAMFILES\Timer"

InstallDirRegKey

试着从注册表来查找这个值,找到则会以该值为新的InstallDir。

InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""

ShowInstDetails

设置是否显示安装细节。

ShowInstDetails show

ShowUnInstDetails

设置是否显示卸载细节。

ShowUnInstDetails show

Section

Section "MainSection" SEC01
  SetOutPath "$INSTDIR"
  SetOverwrite try
  File "dist\timer\*.dll"
  File "dist\timer\base_library.zip"
  File "dist\timer\timer.ico"
  File "dist\timer\*.pyd"
  File /r "dist\timer\PySide2"
  File /r "dist\timer\shiboken2"
  File "dist\timer\timer.exe"
  CreateDirectory "$SMPROGRAMS\timer"
  CreateShortCut "$SMPROGRAMS\timer\timer.lnk" "$INSTDIR\timer.exe" "" "$INSTDIR\timer.ico"
  CreateShortCut "$DESKTOP\timer.lnk" "$INSTDIR\timer.exe" "" "$INSTDIR\timer.ico"
  File "dist\timer\timer.exe.manifest"
SectionEnd

Section -AdditionalIcons
  CreateShortCut "$SMPROGRAMS\timer\Uninstall.lnk" "$INSTDIR\uninst.exe"
SectionEnd

Section -Post
  WriteUninstaller "$INSTDIR\uninst.exe"
  WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\timer.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}" "DisplayIcon" "$INSTDIR\timer.exe"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
SectionEnd

这个Section...SectionEnd定义了一个Section区块,具体来说就是安装动作的不同安装部分,上面这个是简单的情况,虽然分成了几个Section,但后面两个因为section_name前面加上了- ,那么这个section是默认安装,用户不可控制的,所以只剩下一个section为主Section了,然后section_name名字都是随意的,包括这里的 MainSection 也只是一个惯例,section_name唯一的例外就是 Uninstall 必然表示卸载动作Section。

SetOutPath

设置安装的输出路径

SetOutPath "$INSTDIR"

File

将某些文件移过去,支持如下的 * 通配选择。

File "dist\timer\*.dll"

CreateDirectory

新建一个文件夹。下面这个 $SMPROGRAMS 是你的程序在应用程序开始菜单上的位置,比如下面这个具体对应的文件夹是:

C:\Users\wz-game\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\timer
CreateDirectory "$SMPROGRAMS\timer"

CreateShortCut

新建一个快捷方式,具体链接到那个文件,第三个参数是启动该程序时额外的一些参数,第四个参数是设置图标。

  CreateShortCut "$SMPROGRAMS\timer\timer.lnk" "$INSTDIR\timer.exe" "" "$INSTDIR\timer.ico"

WriteUninstaller

输出卸载的exe文件。

  WriteUninstaller "$INSTDIR\uninst.exe"

WriteRegStr

这里进行了一些注册表的填写工作。

  WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\timer.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}" "DisplayIcon" "$INSTDIR\timer.ico"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
  WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"

Delete

卸载删除文件

RMDir

卸载删除文件夹,可以加上 /r 参数递归删除该文件夹所有内容。

  RMDir /r "$INSTDIR\shiboken2"

DeleteRegKey

注册表字段删除

  DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"