;----------------------------------------------------------------------- ; NSIS Installation Script ; ; Kyle Huckins ; ; khuckins@catalystdevworks.com ; ; This will be a guide to working with NSIS to create an installer. ; ; It is a heavily commented practice installer, basically. ; ; ; ; Comments are designated by # and ; ; ; # tends to be at the beginning of a line, while ; is ; ; primarilly used as end-of-line comments. However it's ; ; common to use just ; for comments as well. ; ; ; ;------------------------------------------------------------------------ ;================== ; Basic Information ;-------- ; Includes !include "MUI2.nsh" ;This enables the use of ModernUI, and must go at the top !include "x64.nsh" !include "defines.nsh" ;Definitions for our variables !include "LogicLib.nsh" ;Sparsly documented library, but necessary for any real logic !include "nsDialogs.nsh" ;Need this to create custom pages !include StrRep.nsh !include ReplaceInFile.nsh ;--------------------------------------------------------------- ; Add local copy of AccessControl plugin !addplugindir . ; Installer's filename Outfile "${APPNAME}-Installer-${FULLVERSION}.exe" RequestExecutionLevel admin ;----------------- ; Titlebar Content Name "${APPNAME}" ;================================== ; Page system !insertmacro MUI_PAGE_WELCOME !define MUI_PAGE_CUSTOMFUNCTION_PRE ValidateInstall !insertmacro MUI_PAGE_LICENSE "license.rtf" ;Loads licence.rtf to show license content !insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_FINISH !insertmacro MUI_LANGUAGE "English" ;------------------------------------- ; Code to verify if a user is an admin !macro VerifyUserIsAdmin UserInfo::GetAccountType pop $0 ${If} $0 != "admin" ;Require admin rights messageBox MB_OK|MB_ICONSTOP "Administrator rights required!" setErrorLevel 740 ;ERROR_ELEVATION_REQUIRED quit ${EndIf} !macroend function .onInit setShellVarContext all !insertmacro VerifyUserIsAdmin Return functionEnd ;----------------- ;Check our version function ValidateInstall ; Hatch Version Check ReadRegStr $1 HKLM "SOFTWARE\${COMPANYNAME}\${APPNAME}" "Version" StrCmp $1 "" INSTALL ${If} $1 S== ${FULLVERSION} ;Same version is installed MessageBox MB_OKCANCEL|MB_ICONINFORMATION "You already have this version of ${APPNAME} installed. You must uninstall the currently installed version to continue." /SD IDOK IDOK UNINSTALL IDCANCEL QUIT ${ElseIf} $1 S> ${FULLVERSION} ;Older version is installed MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "You are tring to install an older version of ${APPNAME} than the one you currently have installed. You must uninstall the currently installed verion to continue." /SD IDOK IDOK UNINSTALL IDCANCEL QUIT ${ElseIf} $1 S< ${FULLVERSION} ;Newer version is installed MessageBox MB_OKCANCEL|MB_ICONINFORMATION "You have a previous version of ${APPNAME} installed. The previous version will be uninrtalled so installation can continue." /SD IDOK IDOK UNINSTALL IDCANCEL QUIT ${EndIf} UNINSTALL: ReadRegStr $1 HKLM "SOFTWARE\${COMPANYNAME}\${APPNAME}" "Install Path" ; Manually copying the uninstaller like this allows the use of the _? param which is required for ExecWait while also allowing all files to be deleted. CopyFiles /SILENT "$1\Uninstall ${APPNAME}.exe" "$TEMP\Uninstall ${APPNAME}.exe" ExecWait '"$TEMP\Uninstall ${APPNAME}.exe" /S _?=$1' Delete /REBOOTOK "$TEMP\Uninstall ${APPNAME}.exe" Goto INSTALL QUIT: Quit INSTALL: Return functionEnd ;-------------------------- ; Where our install files go InstallDir "$PROGRAMFILES\${APPNAME}" ;This is where our variables come in. ;---------------------------------------------- section "install" ; Install directory files - keep these in the same directory ; as the script before compiling. SetOutPath $INSTDIR\ ;Sets output path to our InstallDir File /r ..\..\java-jdk-win File /r ..\..\javafx-sdk-win File /r ..\..\lib File /r ..\..\extension File ..\..\hatch.bat File ..\..\hatch.properties File ..\..\logging.properties ; Set path variable in org.ils_evergreen.hatch.*.json to $INSTDIR\hatch.bat ${StrRep} '$0' '$INSTDIR' '\' '\\' !insertmacro _ReplaceInFile "$INSTDIR\extension\host\org.evergreen_ils.hatch.chrome.json" "/path/to/hatch.sh" "$0\\hatch.bat" !insertmacro _ReplaceInFile "$INSTDIR\extension\host\org.evergreen_ils.hatch.firefox.json" "/path/to/hatch.sh" "$0\\hatch.bat" AccessControl::EnableFileInheritance "$INSTDIR\extension\host\org.evergreen_ils.hatch.chrome.json" AccessControl::EnableFileInheritance "$INSTDIR\extension\host\org.evergreen_ils.hatch.firefox.json" ; Set logging to be in ProgramData SetShellVarContext all ${IfNot} ${FileExists} "$APPDATA\${APPNAME}" CreateDirectory "$APPDATA\${APPNAME}" ${EndIf} !insertmacro _ReplaceInFile "$INSTDIR\hatch.properties" "#data.directory=/tmp/foo" "data.directory=C://ProgramData//${APPNAME}" !insertmacro _ReplaceInFile "$INSTDIR\logging.properties" "%h/.evergreen/hatch.log" "C://ProgramData//${APPNAME}//hatch.log" AccessControl::EnableFileInheritance "$INSTDIR\hatch.properties" AccessControl::EnableFileInheritance "$INSTDIR\logging.properties" ; Registry info for Add/Remove Programs WriteRegStr HKLM "SOFTWARE\${COMPANYNAME}\${APPNAME}" "Logging Path" $APPDATA SetShellVarContext current WriteRegStr HKLM "SOFTWARE\${COMPANYNAME}\${APPNAME}" "Install Path" $INSTDIR WriteRegStr HKLM "SOFTWARE\${COMPANYNAME}\${APPNAME}" "Version" "${FULLVERSION}" WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayName" "${COMPANYNAME} - ${APPNAME} - ${DESCRIPTION}" WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "UninstallString" "$INSTDIR\Uninstall ${APPNAME}.exe" WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "QuietUninstallString" "$INSTDIR\Uninstall ${APPNAME}.exe /S" WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "InstallLocation" "$INSTDIR" WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayIcon" "$INSTDIR\logo.ico" WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "Publisher" "${COMPANYNAME}" StrCmp "${HELPURL}" "" +2 WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "HelpLink" "${HELPURL}" StrCmp "${UPDATEURL}" "" +2 WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "URLUpdateInfo" "${UPDATEURL}" StrCmp "${ABOUTURL}" "" +2 WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "URLInfoAbout" "${ABOUTURL}" WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayVersion" "${VERSIONMAJOR}.${VERSIONMINOR}.${VERSIONBUILD}" WriteRegDWORD HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "VersionMajor" ${VERSIONMAJOR} WriteRegDWORD HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "VersionMinor" ${VERSIONMINOR} # There is no option for modifying or repairing the install WriteRegDWORD HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "NoModify" 1 WriteRegDWORD HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "NoRepair" 1 # Set the INSTALLSIZE constant (!defined at the top of this script) so Add/Remove Programs can accurately report the size WriteRegDWORD HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "EstimatedSize" ${INSTALLSIZE} ; Connect Hatch to Chrome and install the Hatch extension from the Chrome Web Store WriteRegStr HKLM "SOFTWARE\Google\Chrome\NativeMessagingHosts\org.evergreen_ils.hatch" "" "$INSTDIR\extension\host\org.evergreen_ils.hatch.chrome.json" WriteRegStr HKLM "Software\Google\Chrome\Extensions\${EXTENSIONID}" "update_url" "${EXTENSION_UPDATEURL}" ; Firefox won't check both the 32 and 64 bit views, so it's on us to put the key in the right place. ; Firefox doesn't allow automatic installation of remote extensions either, so there's no (good) auto-install option here. :-/ ; A link should be added to the web client to simplify locating the FF extension. (Links to both would likely be a good practice.) ${If} ${RunningX64} SetRegView 64 ${EndIf} WriteRegStr HKLM "SOFTWARE\Mozilla\NativeMessagingHosts\org.evergreen_ils.hatch" "" "$INSTDIR\extension\host\org.evergreen_ils.hatch.firefox.json" ${If} ${RunningX64} SetRegView 32 ${EndIf} ; Uninstaller writeUninstaller "$INSTDIR\Uninstall ${APPNAME}.exe" SectionEnd ############################# # Uninstaller code function un.onInit SetShellVarContext all # Verify uninstaller MessageBox MB_OKCANCEL "Permanently remove ${APPNAME}?" /SD IDOK IDOK next Abort next: !insertmacro VerifyUserIsAdmin functionEnd section "uninstall" # Remove the data log directory SetShellVarContext all ${If} ${FileExists} "$APPDATA\${APPNAME}" RmDir /r /REBOOTOK "$APPDATA\${APPNAME}" ${EndIf} SetShellVarContext current # Remove the actual files Delete /REBOOTOK "$INSTDIR\hatch.bat" Delete /REBOOTOK "$INSTDIR\hatch.properties" Delete /REBOOTOK "$INSTDIR\logging.properties" ; blindly using /r isn't ideal but the extreme unlikelyhood of there being \lib or \extension folders under $PROGRAMFILES makes it low risk. RmDir /r /REBOOTOK "$INSTDIR\extension" RmDir /r /REBOOTOK "$INSTDIR\lib" RmDir /r /REBOOTOK "$INSTDIR\java-jdk-win" RmDir /r /REBOOTOK "$INSTDIR\javafx-sdk-win" # Delete uninstaller last Delete /REBOOTOK "$INSTDIR\Uninstall ${APPNAME}.exe" # Remove installation directory RmDir /REBOOTOK "$INSTDIR" # Remove uninstaller info from registry DeleteRegKey HKLM "SOFTWARE\${COMPANYNAME}\${APPNAME}" DeleteRegKey HKLM "SOFTWARE\${COMPANYNAME}" DeleteRegKey HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" DeleteRegKey HKLM "SOFTWARE\Google\Chrome\NativeMessagingHosts\org.evergreen_ils.hatch" DeleteRegKey HKLM "SOFTWARE\Google\Chrome\Extensions\${EXTENSIONID}" ${If} ${RunningX64} SetRegView 64 ${EndIf} DeleteRegKey HKLM "SOFTWARE\Mozilla\NativeMessagingHosts\org.evergreen_ils.hatch" ${If} ${RunningX64} SetRegView 32 ${EndIf} IfRebootFlag 0 Done MessageBox MB_YESNO "A reboot is required to finish the installation. Do you wish to reboot now?" /SD IDNO IDNO Done Reboot Done: sectionEnd