installUtil.nsh 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. !macro moveFile FROM TO
  2. ClearErrors
  3. Rename `${FROM}` `${TO}`
  4. ${if} ${errors}
  5. # not clear - can NSIS rename on another drive or not, so, in case of error, just copy
  6. ClearErrors
  7. !insertmacro copyFile `${FROM}` `${TO}`
  8. Delete `${FROM}`
  9. ${endif}
  10. !macroend
  11. !macro copyFile FROM TO
  12. ${StdUtils.GetParentPath} $R5 `${TO}`
  13. CreateDirectory `$R5`
  14. ClearErrors
  15. CopyFiles /SILENT `${FROM}` `${TO}`
  16. !macroend
  17. Function GetInQuotes
  18. Exch $R0
  19. Push $R1
  20. Push $R2
  21. Push $R3
  22. StrCpy $R2 -1
  23. IntOp $R2 $R2 + 1
  24. StrCpy $R3 $R0 1 $R2
  25. StrCmp $R3 "" 0 +3
  26. StrCpy $R0 ""
  27. Goto Done
  28. StrCmp $R3 '"' 0 -5
  29. IntOp $R2 $R2 + 1
  30. StrCpy $R0 $R0 "" $R2
  31. StrCpy $R2 0
  32. IntOp $R2 $R2 + 1
  33. StrCpy $R3 $R0 1 $R2
  34. StrCmp $R3 "" 0 +3
  35. StrCpy $R0 ""
  36. Goto Done
  37. StrCmp $R3 '"' 0 -5
  38. StrCpy $R0 $R0 $R2
  39. Done:
  40. Pop $R3
  41. Pop $R2
  42. Pop $R1
  43. Exch $R0
  44. FunctionEnd
  45. !macro GetInQuotes Var Str
  46. Push "${Str}"
  47. Call GetInQuotes
  48. Pop "${Var}"
  49. !macroend
  50. Function GetFileParent
  51. Exch $R0
  52. Push $R1
  53. Push $R2
  54. Push $R3
  55. StrCpy $R1 0
  56. StrLen $R2 $R0
  57. loop:
  58. IntOp $R1 $R1 + 1
  59. IntCmp $R1 $R2 get 0 get
  60. StrCpy $R3 $R0 1 -$R1
  61. StrCmp $R3 "\" get
  62. Goto loop
  63. get:
  64. StrCpy $R0 $R0 -$R1
  65. Pop $R3
  66. Pop $R2
  67. Pop $R1
  68. Exch $R0
  69. FunctionEnd
  70. Var /GLOBAL isTryToKeepShortcuts
  71. !macro setIsTryToKeepShortcuts
  72. StrCpy $isTryToKeepShortcuts "true"
  73. !ifdef allowToChangeInstallationDirectory
  74. ${ifNot} ${isUpdated}
  75. StrCpy $isTryToKeepShortcuts "false"
  76. ${endIf}
  77. !endif
  78. !macroend
  79. # https://nsis-dev.github.io/NSIS-Forums/html/t-172971.html
  80. !macro readReg VAR ROOT_KEY SUB_KEY NAME
  81. ${if} "${ROOT_KEY}" == "SHELL_CONTEXT"
  82. ReadRegStr "${VAR}" SHELL_CONTEXT "${SUB_KEY}" "${NAME}"
  83. ${elseif} "${ROOT_KEY}" == "HKEY_CURRENT_USER"
  84. ReadRegStr "${VAR}" HKEY_CURRENT_USER "${SUB_KEY}" "${NAME}"
  85. ${elseif} "${ROOT_KEY}" == "HKEY_LOCAL_MACHINE"
  86. ReadRegStr "${VAR}" HKEY_LOCAL_MACHINE "${SUB_KEY}" "${NAME}"
  87. ${else}
  88. MessageBox MB_OK "Unsupported ${ROOT_KEY}"
  89. ${endif}
  90. !macroend
  91. Function handleUninstallResult
  92. Var /GLOBAL rootKey_uninstallResult
  93. Exch $rootKey_uninstallResult
  94. ${if} "$rootKey_uninstallResult" == "SHELL_CONTEXT"
  95. !ifmacrodef customUnInstallCheck
  96. !insertmacro customUnInstallCheck
  97. Return
  98. !endif
  99. ${elseif} "$rootKey_uninstallResult" == "HKEY_CURRENT_USER"
  100. !ifmacrodef customUnInstallCheckCurrentUser
  101. !insertmacro customUnInstallCheckCurrentUser
  102. Return
  103. !endif
  104. ${endif}
  105. IfErrors 0 +3
  106. DetailPrint `Uninstall was not successful. Not able to launch uninstaller!`
  107. Return
  108. ${if} $R0 != 0
  109. MessageBox MB_OK|MB_ICONEXCLAMATION "$(uninstallFailed): $R0"
  110. DetailPrint `Uninstall was not successful. Uninstaller error code: $R0.`
  111. SetErrorLevel 2
  112. Quit
  113. ${endif}
  114. FunctionEnd
  115. !macro handleUninstallResult ROOT_KEY
  116. Push "${ROOT_KEY}"
  117. Call handleUninstallResult
  118. !macroend
  119. # http://stackoverflow.com/questions/24595887/waiting-for-nsis-uninstaller-to-finish-in-nsis-installer-either-fails-or-the-uni
  120. Function uninstallOldVersion
  121. Var /GLOBAL uninstallerFileName
  122. Var /Global uninstallerFileNameTemp
  123. Var /GLOBAL installationDir
  124. Var /GLOBAL uninstallString
  125. Var /GLOBAL rootKey
  126. ClearErrors
  127. Exch $rootKey
  128. Push 0
  129. Pop $R0
  130. !insertmacro readReg $uninstallString "$rootKey" "${UNINSTALL_REGISTRY_KEY}" UninstallString
  131. ${if} $uninstallString == ""
  132. !ifdef UNINSTALL_REGISTRY_KEY_2
  133. !insertmacro readReg $uninstallString "$rootKey" "${UNINSTALL_REGISTRY_KEY_2}" UninstallString
  134. !endif
  135. ${if} $uninstallString == ""
  136. ClearErrors
  137. Return
  138. ${endif}
  139. ${endif}
  140. # uninstaller should be copied out of app installation dir (because this dir will be deleted), so, extract uninstaller file name
  141. !insertmacro GetInQuotes $uninstallerFileName "$uninstallString"
  142. !insertmacro readReg $installationDir "$rootKey" "${INSTALL_REGISTRY_KEY}" InstallLocation
  143. ${if} $installationDir == ""
  144. ${andIf} $uninstallerFileName != ""
  145. # https://github.com/electron-userland/electron-builder/issues/735#issuecomment-246918567
  146. Push $uninstallerFileName
  147. Call GetFileParent
  148. Pop $installationDir
  149. ${endif}
  150. ${if} $installationDir == ""
  151. ${andIf} $uninstallerFileName == ""
  152. ClearErrors
  153. Return
  154. ${endif}
  155. ${if} $installMode == "CurrentUser"
  156. ${orIf} $rootKey == "HKEY_CURRENT_USER"
  157. StrCpy $0 "/currentuser"
  158. ${else}
  159. StrCpy $0 "/allusers"
  160. ${endif}
  161. !insertMacro setIsTryToKeepShortcuts
  162. ${if} $isTryToKeepShortcuts == "true"
  163. !insertmacro readReg $R5 "$rootKey" "${INSTALL_REGISTRY_KEY}" KeepShortcuts
  164. # if true, it means that old uninstaller supports --keep-shortcuts flag
  165. ${if} $R5 == "true"
  166. ${andIf} ${FileExists} "$appExe"
  167. StrCpy $0 "$0 --keep-shortcuts"
  168. ${endIf}
  169. ${endIf}
  170. ${if} ${isDeleteAppData}
  171. StrCpy $0 "$0 --delete-app-data"
  172. ${else}
  173. # always pass --updated flag - to ensure that if DELETE_APP_DATA_ON_UNINSTALL is defined, user data will be not removed
  174. StrCpy $0 "$0 --updated"
  175. ${endif}
  176. StrCpy $uninstallerFileNameTemp "$PLUGINSDIR\old-uninstaller.exe"
  177. !insertmacro copyFile "$uninstallerFileName" "$uninstallerFileNameTemp"
  178. # Retry counter
  179. StrCpy $R5 0
  180. UninstallLoop:
  181. IntOp $R5 $R5 + 1
  182. ${if} $R5 > 5
  183. MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION "$(appCannotBeClosed)" /SD IDCANCEL IDRETRY OneMoreAttempt
  184. Return
  185. ${endIf}
  186. OneMoreAttempt:
  187. ExecWait '"$uninstallerFileNameTemp" /S /KEEP_APP_DATA $0 _?=$installationDir' $R0
  188. ifErrors TryInPlace CheckResult
  189. TryInPlace:
  190. # the execution failed - might have been caused by some group policy restrictions
  191. # we try to execute the uninstaller in place
  192. ExecWait '"$uninstallerFileName" /S /KEEP_APP_DATA $0 _?=$installationDir' $R0
  193. ifErrors DoesNotExist
  194. CheckResult:
  195. ${if} $R0 == 0
  196. Return
  197. ${endIf}
  198. Sleep 1000
  199. Goto UninstallLoop
  200. DoesNotExist:
  201. SetErrors
  202. FunctionEnd
  203. !macro uninstallOldVersion ROOT_KEY
  204. Push "${ROOT_KEY}"
  205. Call uninstallOldVersion
  206. !macroend