How To Create an Installer with NSIS
Nullsoft Scriptable Installer Service is a tool you can use to generate installers. It’s farily popular - you’ve probably used an installer generated by it - the one I can think of first would be WinAmp, but I don’t think anyone has installed WinAmp since 2003, so it’s not a good example.
I downloaded the NSIS installer from SourceForge. I downloaded the most recent version which is 3.03.
My goal here is to create a graphical installer which will encapsulate all of the files which are part of a Py2Exe-generated Python Executable and install them to a folder in the root of the C: drive on a PC.
Installation Steps
- Double click the installer to start it.
- On the first screen, click ‘Next’:
- Click ‘I agree’ on the next screen:
- The ‘Full’ install is the default and is acceptable. Click ‘Next’:
- The default installation path is acceptable. Click ‘Install’:
- The installation will proceed:
- When finished you will be presented with a new screen. I de-selected viewing the release notes and left starting NSIS selected, then clicked ‘Finish’:
Creating an Installer
This is the screen presented to you when you start NSIS.:
Turns out that the basis of an NSIS installer is a script. Just a plan ol’ text file.
A good one is this:
This script assumes a Python script turned into an executable with the output files bing in ./dist.
#NSIS Example Install Script
#Basic definitions
!define APPNAME "Sample App"
!define COMPANYNAME "Steves Toolbox LLC"
!define DESCRIPTION "Basic Python Application"
!define APPSHORTNAME "pyApp"
#Ask for administrative rights
RequestExecutionLevel admin
#Other options include:
#none
#user
#highest
#Default installation location - let's clutter up our root directory!
InstallDir "C:\${APPSHORTNAME}"
#Text (or RTF) file with license information. The text file must be in DOS end line format (\r\n)
LicenseData "..\docs\license.md"
#'Name' goes in the installer's title bar
Name "${COMPANYNAME}-${APPSHORTNAME}"
#Icon for the installer - this is the default icon
#Icon "logo.ico"
#The following lines replace the default icons
!include "MUI2.nsh"
#The name of the installer executable
outFile "${APPSHORTNAME}-inst.exe"
#...Not certain about this one
!include LogicLib.nsh
#Defines installation pages - these are known to NSIS
#Shows the license
Page license
#Allows user to pick install path
Page directory
#Installs the files
Page instfiles
#A macro to verify that administrator rights have been acquired
!macro VerifyUserIsAdmin
UserInfo::GetAccountType
pop $0
${If} $0 != "admin" ;Require admin rights on NT4+
messageBox mb_iconstop "Administrator rights required!"
setErrorLevel 740 ;ERROR_ELEVATION_REQUIRED
quit
${EndIf}
!macroend
#This ensures the administrator check is performed at startup?
function .onInit
setShellVarContext all
!insertmacro VerifyUserIsAdmin
functionEnd
# Files for the install directory - to build the installer, these should be in the same directory as the install script (this file)
section "install"
setOutPath $INSTDIR
# Files added here should be removed by the uninstaller (see section "uninstall")
file /r ..\dist\*.*
# Add any other files for the install directory (license files, app data, etc) here
#This creates a shortcut to the executable on the desktop - the second set of options in quotes are for command-line arguments
CreateShortcut "$desktop\Link to pyApp.lnk" "$instdir\pyApp.exe" "-c cfg\default.cfg"
sectionEnd
Creating a Directory
Most of my Python apps use a ‘logs’ directory to store logs, but I wouldn’t want the installer to package up my logs directory from a working directory structure - that would add all of my log files to the installer. No bueno.
Instead, I need the NSIS script to create the logs directory in the appropriate place.
NSIS can do that, here’s the documentation of CreateDirectory.
Here’s a modified ‘install’ section with the directive to create the log subdirectory:
# Files for the install directory - to build the installer, these should be in the same directory as the install script (this file)
section "install"
setOutPath $INSTDIR
# Files added here should be removed by the uninstaller (see section "uninstall")
file /r ..\dist\*.*
#Add a directory for logfiles
CreateDirectory $INSTDIR\logs
# Add any other files for the install directory (license files, app data, etc) here
#This creates a shortcut to the executable on the desktop - the second set of options in quotes are for command-line arguments
CreateShortcut "$desktop\pyApp.lnk" "$instdir\pyApp.exe"
sectionEnd