pyapp.nsi 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  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. SetOutPath "$INSTDIR\pkgs"
  59. File /r "pkgs\*.*"
  60. SetOutPath "$INSTDIR"
  61. ; Marker file for per-user install
  62. StrCmp $MultiUser.InstallMode CurrentUser 0 +3
  63. FileOpen $0 "$INSTDIR\${USER_INSTALL_MARKER}" w
  64. FileClose $0
  65. SetFileAttributes "$INSTDIR\${USER_INSTALL_MARKER}" HIDDEN
  66. [% block install_files %]
  67. ; Install files
  68. [% for destination, group in grouped_files %]
  69. SetOutPath "[[destination]]"
  70. [% for file in group %]
  71. File "[[ file ]]"
  72. [% endfor %]
  73. [% endfor %]
  74. ; Install directories
  75. [% for dir, destination in ib.install_dirs %]
  76. SetOutPath "[[ pjoin(destination, dir) ]]"
  77. File /r "[[dir]]\*.*"
  78. [% endfor %]
  79. [% endblock install_files %]
  80. [% block install_shortcuts %]
  81. ; Install shortcuts
  82. ; The output path becomes the working directory for shortcuts
  83. SetOutPath "%HOMEDRIVE%\%HOMEPATH%"
  84. [% if single_shortcut %]
  85. [% for scname, sc in ib.shortcuts.items() %]
  86. CreateShortCut "$SMPROGRAMS\[[scname]].lnk" "[[sc['target'] ]]" \
  87. '[[ sc['parameters'] ]]' "$INSTDIR\[[ sc['icon'] ]]"
  88. [% endfor %]
  89. [% else %]
  90. [# Multiple shortcuts: create a directory for them #]
  91. CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
  92. [% for scname, sc in ib.shortcuts.items() %]
  93. CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\[[scname]].lnk" "[[sc['target'] ]]" \
  94. '[[ sc['parameters'] ]]' "$INSTDIR\[[ sc['icon'] ]]"
  95. [% endfor %]
  96. [% endif %]
  97. SetOutPath "$INSTDIR"
  98. [% endblock install_shortcuts %]
  99. [% block install_commands %]
  100. [% if has_commands %]
  101. DetailPrint "Setting up command-line launchers..."
  102. StrCmp $MultiUser.InstallMode CurrentUser 0 AddSysPathSystem
  103. ; Add to PATH for current user
  104. nsExec::ExecToLog '[[ python ]] -Es "$INSTDIR\_system_path.py" add_user "$INSTDIR\bin"'
  105. GoTo AddedSysPath
  106. AddSysPathSystem:
  107. ; Add to PATH for all users
  108. nsExec::ExecToLog '[[ python ]] -Es "$INSTDIR\_system_path.py" add "$INSTDIR\bin"'
  109. AddedSysPath:
  110. [% endif %]
  111. [% endblock install_commands %]
  112. ; Byte-compile Python files.
  113. DetailPrint "Byte-compiling Python modules..."
  114. nsExec::ExecToLog '[[ python ]] -m compileall -q "$INSTDIR\pkgs"'
  115. WriteUninstaller $INSTDIR\uninstall.exe
  116. ; Add ourselves to Add/remove programs
  117. WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
  118. "DisplayName" "${PRODUCT_NAME}"
  119. WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
  120. "UninstallString" '"$INSTDIR\uninstall.exe"'
  121. WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
  122. "InstallLocation" "$INSTDIR"
  123. WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
  124. "DisplayIcon" "$INSTDIR\${PRODUCT_ICON}"
  125. [% if ib.publisher is not none %]
  126. WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
  127. "Publisher" "[[ib.publisher]]"
  128. [% endif %]
  129. WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
  130. "DisplayVersion" "${PRODUCT_VERSION}"
  131. WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
  132. "NoModify" 1
  133. WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
  134. "NoRepair" 1
  135. ; Check if we need to reboot
  136. IfRebootFlag 0 noreboot
  137. MessageBox MB_YESNO "A reboot is required to finish the installation. Do you wish to reboot now?" \
  138. /SD IDNO IDNO noreboot
  139. Reboot
  140. noreboot:
  141. SectionEnd
  142. Section "Uninstall"
  143. SetRegView [[ib.py_bitness]]
  144. SetShellVarContext all
  145. IfFileExists "$INSTDIR\${USER_INSTALL_MARKER}" 0 +3
  146. SetShellVarContext current
  147. Delete "$INSTDIR\${USER_INSTALL_MARKER}"
  148. Delete $INSTDIR\uninstall.exe
  149. Delete "$INSTDIR\${PRODUCT_ICON}"
  150. RMDir /r "$INSTDIR\pkgs"
  151. ; Remove ourselves from %PATH%
  152. [% block uninstall_commands %]
  153. [% if has_commands %]
  154. nsExec::ExecToLog '[[ python ]] -Es "$INSTDIR\_system_path.py" remove "$INSTDIR\bin"'
  155. [% endif %]
  156. [% endblock uninstall_commands %]
  157. [% block uninstall_files %]
  158. ; Uninstall files
  159. [% for file, destination in ib.install_files %]
  160. Delete "[[pjoin(destination, file)]]"
  161. [% endfor %]
  162. ; Uninstall directories
  163. [% for dir, destination in ib.install_dirs %]
  164. RMDir /r "[[pjoin(destination, dir)]]"
  165. [% endfor %]
  166. [% endblock uninstall_files %]
  167. [% block uninstall_shortcuts %]
  168. ; Uninstall shortcuts
  169. [% if single_shortcut %]
  170. [% for scname in ib.shortcuts %]
  171. Delete "$SMPROGRAMS\[[scname]].lnk"
  172. [% endfor %]
  173. [% else %]
  174. RMDir /r "$SMPROGRAMS\${PRODUCT_NAME}"
  175. [% endif %]
  176. [% endblock uninstall_shortcuts %]
  177. RMDir $INSTDIR
  178. DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
  179. SectionEnd
  180. [% endblock sections %]
  181. ; Functions
  182. Function .onMouseOverSection
  183. ; Find which section the mouse is over, and set the corresponding description.
  184. FindWindow $R0 "#32770" "" $HWNDPARENT
  185. GetDlgItem $R0 $R0 1043 ; description item (must be added to the UI)
  186. [% block mouseover_messages %]
  187. StrCmp $0 ${sec_app} "" +2
  188. SendMessage $R0 ${WM_SETTEXT} 0 "STR:${PRODUCT_NAME}"
  189. [% endblock mouseover_messages %]
  190. FunctionEnd
  191. Function .onInit
  192. ; Multiuser.nsh breaks /D command line parameter. Parse /INSTDIR instead.
  193. ; Cribbing from https://nsis-dev.github.io/NSIS-Forums/html/t-299280.html
  194. ${GetParameters} $0
  195. ClearErrors
  196. ${GetOptions} '$0' "/INSTDIR=" $1
  197. IfErrors +2 ; Error means flag not found
  198. StrCpy $cmdLineInstallDir $1
  199. ClearErrors
  200. !insertmacro MULTIUSER_INIT
  201. ; If cmd line included /INSTDIR, override the install dir set by MultiUser
  202. StrCmp $cmdLineInstallDir "" +2
  203. StrCpy $INSTDIR $cmdLineInstallDir
  204. FunctionEnd
  205. Function un.onInit
  206. !insertmacro MULTIUSER_UNINIT
  207. FunctionEnd
  208. [% if ib.py_bitness == 64 %]
  209. Function correct_prog_files
  210. ; The multiuser machinery doesn't know about the different Program files
  211. ; folder for 64-bit applications. Override the install dir it set.
  212. StrCmp $MultiUser.InstallMode AllUsers 0 +2
  213. StrCpy $INSTDIR "$PROGRAMFILES64\${MULTIUSER_INSTALLMODE_INSTDIR}"
  214. FunctionEnd
  215. [% endif %]