pyapp.nsi 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. !define PRODUCT_NAME "[[ib.appname]]"
  2. !define PRODUCT_VERSION "[[ib.version]]"
  3. !define PY_VERSION "[[ib.py_version]]"
  4. !define PY_MAJOR_VERSION "[[ib.py_major_version]]"
  5. !define BITNESS "[[ib.py_bitness]]"
  6. !define ARCH_TAG "[[arch_tag]]"
  7. !define INSTALLER_NAME "[[ib.installer_name]]"
  8. !define PRODUCT_ICON "[[icon]]"
  9. ; Marker file to tell the uninstaller that it's a user installation
  10. !define USER_INSTALL_MARKER _user_install_marker
  11. SetCompressor lzma
  12. !if "${NSIS_PACKEDVERSION}" >= 0x03000000
  13. Unicode true
  14. ManifestDPIAware true
  15. !endif
  16. !define MULTIUSER_EXECUTIONLEVEL Highest
  17. !define MULTIUSER_INSTALLMODE_DEFAULT_CURRENTUSER
  18. !define MULTIUSER_MUI
  19. !define MULTIUSER_INSTALLMODE_COMMANDLINE
  20. !define MULTIUSER_INSTALLMODE_INSTDIR "[[ib.appname]]"
  21. [% if ib.py_bitness == 64 %]
  22. !define MULTIUSER_INSTALLMODE_FUNCTION correct_prog_files
  23. [% endif %]
  24. !include MultiUser.nsh
  25. !include FileFunc.nsh
  26. [% block modernui %]
  27. ; Modern UI installer stuff
  28. !include "MUI2.nsh"
  29. !define MUI_ABORTWARNING
  30. !define MUI_ICON "[[icon]]"
  31. !define MUI_UNICON "[[icon]]"
  32. ; UI pages
  33. [% block ui_pages %]
  34. !insertmacro MUI_PAGE_WELCOME
  35. [% if license_file %]
  36. !insertmacro MUI_PAGE_LICENSE [[license_file]]
  37. [% endif %]
  38. !insertmacro MULTIUSER_PAGE_INSTALLMODE
  39. !insertmacro MUI_PAGE_DIRECTORY
  40. !insertmacro MUI_PAGE_INSTFILES
  41. !insertmacro MUI_PAGE_FINISH
  42. [% endblock ui_pages %]
  43. !insertmacro MUI_LANGUAGE "English"
  44. [% endblock modernui %]
  45. Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
  46. OutFile "${INSTALLER_NAME}"
  47. ShowInstDetails show
  48. Var cmdLineInstallDir
  49. Section -SETTINGS
  50. SetOutPath "$INSTDIR"
  51. SetOverwrite ifnewer
  52. SectionEnd
  53. [% block sections %]
  54. Section "!${PRODUCT_NAME}" sec_app
  55. SetRegView [[ib.py_bitness]]
  56. SectionIn RO
  57. File ${PRODUCT_ICON}
  58. [% block install_pkgs %]
  59. [#
  60. Extend this block if you need to remove the pkgs directory if it already
  61. exists from previous installations (when upgrading without uninstalling).
  62. https://github.com/takluyver/pynsist/issues/66
  63. Example:
  64. [% block install_pkgs %]
  65. RMDir /r "$INSTDIR\pkgs"
  66. [[ super() ]]
  67. [% endblock install_pkgs %]
  68. #]
  69. ; Copy pkgs data
  70. SetOutPath "$INSTDIR\pkgs"
  71. File /r "pkgs\*.*"
  72. [% endblock install_pkgs %]
  73. SetOutPath "$INSTDIR"
  74. ; Marker file for per-user install
  75. StrCmp $MultiUser.InstallMode CurrentUser 0 +3
  76. FileOpen $0 "$INSTDIR\${USER_INSTALL_MARKER}" w
  77. FileClose $0
  78. SetFileAttributes "$INSTDIR\${USER_INSTALL_MARKER}" HIDDEN
  79. [% block install_files %]
  80. ; Install files
  81. [% for destination, group in grouped_files %]
  82. SetOutPath "[[destination]]"
  83. [% for file in group %]
  84. File "[[ file ]]"
  85. [% endfor %]
  86. [% endfor %]
  87. ; Install directories
  88. [% for dir, destination in ib.install_dirs %]
  89. SetOutPath "[[ pjoin(destination, dir) ]]"
  90. File /r "[[dir]]\*.*"
  91. [% endfor %]
  92. [% endblock install_files %]
  93. [% block install_shortcuts %]
  94. ; Install shortcuts
  95. ; The output path becomes the working directory for shortcuts
  96. SetOutPath "%HOMEDRIVE%\%HOMEPATH%"
  97. [% if single_shortcut %]
  98. [% for scname, sc in ib.shortcuts.items() %]
  99. CreateShortCut "$SMPROGRAMS\[[scname]].lnk" "[[sc['target'] ]]" \
  100. '[[ sc['parameters'] ]]' "$INSTDIR\[[ sc['icon'] ]]"
  101. [% endfor %]
  102. [% else %]
  103. [# Multiple shortcuts: create a directory for them #]
  104. CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
  105. [% for scname, sc in ib.shortcuts.items() %]
  106. CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\[[scname]].lnk" "[[sc['target'] ]]" \
  107. '[[ sc['parameters'] ]]' "$INSTDIR\[[ sc['icon'] ]]"
  108. [% endfor %]
  109. [% endif %]
  110. SetOutPath "$INSTDIR"
  111. [% endblock install_shortcuts %]
  112. [% block install_commands %]
  113. [% if has_commands %]
  114. DetailPrint "Setting up command-line launchers..."
  115. StrCmp $MultiUser.InstallMode CurrentUser 0 AddSysPathSystem
  116. ; Add to PATH for current user
  117. nsExec::ExecToLog '[[ python ]] -Es "$INSTDIR\_system_path.py" add_user "$INSTDIR\bin"'
  118. GoTo AddedSysPath
  119. AddSysPathSystem:
  120. ; Add to PATH for all users
  121. nsExec::ExecToLog '[[ python ]] -Es "$INSTDIR\_system_path.py" add "$INSTDIR\bin"'
  122. AddedSysPath:
  123. [% endif %]
  124. [% endblock install_commands %]
  125. ; Byte-compile Python files.
  126. DetailPrint "Byte-compiling Python modules..."
  127. nsExec::ExecToLog '[[ python ]] -m compileall -q "$INSTDIR\pkgs"'
  128. WriteUninstaller $INSTDIR\uninstall.exe
  129. ; Add ourselves to Add/remove programs
  130. WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
  131. "DisplayName" "${PRODUCT_NAME}"
  132. WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
  133. "UninstallString" '"$INSTDIR\uninstall.exe"'
  134. WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
  135. "InstallLocation" "$INSTDIR"
  136. WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
  137. "DisplayIcon" "$INSTDIR\${PRODUCT_ICON}"
  138. [% if ib.publisher is not none %]
  139. WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
  140. "Publisher" "[[ib.publisher]]"
  141. [% endif %]
  142. WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
  143. "DisplayVersion" "${PRODUCT_VERSION}"
  144. WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
  145. "NoModify" 1
  146. WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
  147. "NoRepair" 1
  148. ; Check if we need to reboot
  149. IfRebootFlag 0 noreboot
  150. MessageBox MB_YESNO "A reboot is required to finish the installation. Do you wish to reboot now?" \
  151. /SD IDNO IDNO noreboot
  152. Reboot
  153. noreboot:
  154. SectionEnd
  155. Section "Uninstall"
  156. SetRegView [[ib.py_bitness]]
  157. SetShellVarContext all
  158. IfFileExists "$INSTDIR\${USER_INSTALL_MARKER}" 0 +3
  159. SetShellVarContext current
  160. Delete "$INSTDIR\${USER_INSTALL_MARKER}"
  161. Delete $INSTDIR\uninstall.exe
  162. Delete "$INSTDIR\${PRODUCT_ICON}"
  163. RMDir /r "$INSTDIR\pkgs"
  164. ; Remove ourselves from %PATH%
  165. [% block uninstall_commands %]
  166. [% if has_commands %]
  167. nsExec::ExecToLog '[[ python ]] -Es "$INSTDIR\_system_path.py" remove "$INSTDIR\bin"'
  168. [% endif %]
  169. [% endblock uninstall_commands %]
  170. [% block uninstall_files %]
  171. ; Uninstall files
  172. [% for file, destination in ib.install_files %]
  173. Delete "[[pjoin(destination, file)]]"
  174. [% endfor %]
  175. ; Uninstall directories
  176. [% for dir, destination in ib.install_dirs %]
  177. RMDir /r "[[pjoin(destination, dir)]]"
  178. [% endfor %]
  179. [% endblock uninstall_files %]
  180. [% block uninstall_shortcuts %]
  181. ; Uninstall shortcuts
  182. [% if single_shortcut %]
  183. [% for scname in ib.shortcuts %]
  184. Delete "$SMPROGRAMS\[[scname]].lnk"
  185. [% endfor %]
  186. [% else %]
  187. RMDir /r "$SMPROGRAMS\${PRODUCT_NAME}"
  188. [% endif %]
  189. [% endblock uninstall_shortcuts %]
  190. RMDir $INSTDIR
  191. DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
  192. SectionEnd
  193. [% endblock sections %]
  194. ; Functions
  195. Function .onMouseOverSection
  196. ; Find which section the mouse is over, and set the corresponding description.
  197. FindWindow $R0 "#32770" "" $HWNDPARENT
  198. GetDlgItem $R0 $R0 1043 ; description item (must be added to the UI)
  199. [% block mouseover_messages %]
  200. StrCmp $0 ${sec_app} "" +2
  201. SendMessage $R0 ${WM_SETTEXT} 0 "STR:${PRODUCT_NAME}"
  202. [% endblock mouseover_messages %]
  203. FunctionEnd
  204. Function .onInit
  205. ; Multiuser.nsh breaks /D command line parameter. Parse /INSTDIR instead.
  206. ; Cribbing from https://nsis-dev.github.io/NSIS-Forums/html/t-299280.html
  207. ${GetParameters} $0
  208. ClearErrors
  209. ${GetOptions} '$0' "/INSTDIR=" $1
  210. IfErrors +2 ; Error means flag not found
  211. StrCpy $cmdLineInstallDir $1
  212. ClearErrors
  213. !insertmacro MULTIUSER_INIT
  214. ; If cmd line included /INSTDIR, override the install dir set by MultiUser
  215. StrCmp $cmdLineInstallDir "" +2
  216. StrCpy $INSTDIR $cmdLineInstallDir
  217. FunctionEnd
  218. Function un.onInit
  219. !insertmacro MULTIUSER_UNINIT
  220. FunctionEnd
  221. [% if ib.py_bitness == 64 %]
  222. Function correct_prog_files
  223. ; The multiuser machinery doesn't know about the different Program files
  224. ; folder for 64-bit applications. Override the install dir it set.
  225. StrCmp $MultiUser.InstallMode AllUsers 0 +2
  226. StrCpy $INSTDIR "$PROGRAMFILES64\${MULTIUSER_INSTALLMODE_INSTDIR}"
  227. FunctionEnd
  228. [% endif %]