_tauri-installer-template.nsi 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000
  1. Unicode true
  2. ManifestDPIAware true
  3. ; Add in `dpiAwareness` `PerMonitorV2` to manifest for Windows 10 1607+ (note this should not affect lower versions since they should be able to ignore this and pick up `dpiAware` `true` set by `ManifestDPIAware true`)
  4. ; Currently undocumented on NSIS's website but is in the Docs folder of source tree, see
  5. ; https://github.com/kichik/nsis/blob/5fc0b87b819a9eec006df4967d08e522ddd651c9/Docs/src/attributes.but#L286-L300
  6. ; https://github.com/tauri-apps/tauri/pull/10106
  7. ManifestDPIAwareness PerMonitorV2
  8. !if "{{compression}}" == "none"
  9. SetCompress off
  10. !else
  11. ; Set the compression algorithm. We default to LZMA.
  12. SetCompressor /SOLID "{{compression}}"
  13. !endif
  14. ; Keep above !include to stay ahead of any plugin command
  15. ; see https://github.com/tauri-apps/tauri/pull/15422#discussion_r3289239624
  16. {{#if signed_plugins_path}}
  17. !addplugindir "{{signed_plugins_path}}"
  18. {{/if}}
  19. !include MUI2.nsh
  20. !include FileFunc.nsh
  21. !include x64.nsh
  22. !include WordFunc.nsh
  23. !include "utils.nsh"
  24. !include "FileAssociation.nsh"
  25. !include "Win\COM.nsh"
  26. !include "Win\Propkey.nsh"
  27. !include "StrFunc.nsh"
  28. ${StrCase}
  29. ${StrLoc}
  30. {{#if installer_hooks}}
  31. !include "{{installer_hooks}}"
  32. {{/if}}
  33. !define WEBVIEW2APPGUID "{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"
  34. !define MANUFACTURER "{{manufacturer}}"
  35. !define PRODUCTNAME "{{product_name}}"
  36. !define VERSION "{{version}}"
  37. !define VERSIONWITHBUILD "{{version_with_build}}"
  38. !define HOMEPAGE "{{homepage}}"
  39. !define INSTALLMODE "{{install_mode}}"
  40. !define LICENSE "{{license}}"
  41. !define INSTALLERICON "{{installer_icon}}"
  42. !define SIDEBARIMAGE "{{sidebar_image}}"
  43. !define HEADERIMAGE "{{header_image}}"
  44. !define UNINSTALLERICON "{{uninstaller_icon}}"
  45. !define UNINSTALLERHEADERIMAGE "{{uninstaller_header_image}}"
  46. !define MAINBINARYNAME "{{main_binary_name}}"
  47. !define MAINBINARYSRCPATH "{{main_binary_path}}"
  48. !define BUNDLEID "{{bundle_id}}"
  49. !define COPYRIGHT "{{copyright}}"
  50. !define OUTFILE "{{out_file}}"
  51. !define ARCH "{{arch}}"
  52. !define ADDITIONALPLUGINSPATH "{{additional_plugins_path}}"
  53. !define ALLOWDOWNGRADES "{{allow_downgrades}}"
  54. !define DISPLAYLANGUAGESELECTOR "{{display_language_selector}}"
  55. !define INSTALLWEBVIEW2MODE "{{install_webview2_mode}}"
  56. !define WEBVIEW2INSTALLERARGS "{{webview2_installer_args}}"
  57. !define WEBVIEW2BOOTSTRAPPERPATH "{{webview2_bootstrapper_path}}"
  58. !define WEBVIEW2INSTALLERPATH "{{webview2_installer_path}}"
  59. !define MINIMUMWEBVIEW2VERSION "{{minimum_webview2_version}}"
  60. !define UNINSTKEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCTNAME}"
  61. !define MANUKEY "Software\${MANUFACTURER}"
  62. !define MANUPRODUCTKEY "${MANUKEY}\${PRODUCTNAME}"
  63. !define UNINSTALLERSIGNCOMMAND "{{uninstaller_sign_cmd}}"
  64. !define ESTIMATEDSIZE "{{estimated_size}}"
  65. !define STARTMENUFOLDER "{{start_menu_folder}}"
  66. !define INSTALLDIRNAME "QMaiWrite"
  67. Var PassiveMode
  68. Var UpdateMode
  69. Var NoShortcutMode
  70. Var WixMode
  71. Var OldMainBinaryName
  72. Name "${PRODUCTNAME}"
  73. BrandingText "${COPYRIGHT}"
  74. OutFile "${OUTFILE}"
  75. ; We don't actually use this value as default install path,
  76. ; it's just for nsis to append the product name folder in the directory selector
  77. ; https://nsis.sourceforge.io/Reference/InstallDir
  78. !define PLACEHOLDER_INSTALL_DIR "placeholder\${INSTALLDIRNAME}"
  79. InstallDir "${PLACEHOLDER_INSTALL_DIR}"
  80. VIProductVersion "${VERSIONWITHBUILD}"
  81. VIAddVersionKey "ProductName" "${PRODUCTNAME}"
  82. VIAddVersionKey "FileDescription" "${PRODUCTNAME}"
  83. VIAddVersionKey "LegalCopyright" "${COPYRIGHT}"
  84. VIAddVersionKey "FileVersion" "${VERSION}"
  85. VIAddVersionKey "ProductVersion" "${VERSION}"
  86. # additional plugins
  87. !addplugindir "${ADDITIONALPLUGINSPATH}"
  88. ; Uninstaller signing command
  89. !if "${UNINSTALLERSIGNCOMMAND}" != ""
  90. !uninstfinalize '${UNINSTALLERSIGNCOMMAND}'
  91. !endif
  92. ; Handle install mode, `perUser`, `perMachine` or `both`
  93. !if "${INSTALLMODE}" == "perMachine"
  94. RequestExecutionLevel admin
  95. !endif
  96. !if "${INSTALLMODE}" == "currentUser"
  97. RequestExecutionLevel user
  98. !endif
  99. !if "${INSTALLMODE}" == "both"
  100. !define MULTIUSER_MUI
  101. !define MULTIUSER_INSTALLMODE_INSTDIR "${INSTALLDIRNAME}"
  102. !define MULTIUSER_INSTALLMODE_COMMANDLINE
  103. !if "${ARCH}" == "x64"
  104. !define MULTIUSER_USE_PROGRAMFILES64
  105. !else if "${ARCH}" == "arm64"
  106. !define MULTIUSER_USE_PROGRAMFILES64
  107. !endif
  108. !define MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY "${UNINSTKEY}"
  109. !define MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME "CurrentUser"
  110. !define MULTIUSER_INSTALLMODEPAGE_SHOWUSERNAME
  111. !define MULTIUSER_INSTALLMODE_FUNCTION RestorePreviousInstallLocation
  112. !define MULTIUSER_EXECUTIONLEVEL Highest
  113. !include MultiUser.nsh
  114. !endif
  115. ; Installer icon
  116. !if "${INSTALLERICON}" != ""
  117. !define MUI_ICON "${INSTALLERICON}"
  118. !endif
  119. ; Installer sidebar image
  120. !if "${SIDEBARIMAGE}" != ""
  121. !define MUI_WELCOMEFINISHPAGE_BITMAP "${SIDEBARIMAGE}"
  122. !endif
  123. ; Enable header images for installer and uninstaller pages when either image is configured.
  124. !if "${HEADERIMAGE}" != ""
  125. !define MUI_HEADERIMAGE
  126. !else if "${UNINSTALLERHEADERIMAGE}" != ""
  127. !define MUI_HEADERIMAGE
  128. !endif
  129. ; Installer header image
  130. !if "${HEADERIMAGE}" != ""
  131. !define MUI_HEADERIMAGE_BITMAP "${HEADERIMAGE}"
  132. !endif
  133. ; Uninstaller header image
  134. !if "${UNINSTALLERHEADERIMAGE}" != ""
  135. !define MUI_HEADERIMAGE_UNBITMAP "${UNINSTALLERHEADERIMAGE}"
  136. !endif
  137. ; Uninstaller icon
  138. !if "${UNINSTALLERICON}" != ""
  139. !define MUI_UNICON "${UNINSTALLERICON}"
  140. !endif
  141. ; Define registry key to store installer language
  142. !define MUI_LANGDLL_REGISTRY_ROOT "HKCU"
  143. !define MUI_LANGDLL_REGISTRY_KEY "${MANUPRODUCTKEY}"
  144. !define MUI_LANGDLL_REGISTRY_VALUENAME "Installer Language"
  145. ; Installer pages, must be ordered as they appear
  146. ; 1. Welcome Page
  147. !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive
  148. !insertmacro MUI_PAGE_WELCOME
  149. ; 2. License Page (if defined)
  150. !if "${LICENSE}" != ""
  151. !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive
  152. !insertmacro MUI_PAGE_LICENSE "${LICENSE}"
  153. !endif
  154. ; 3. Install mode (if it is set to `both`)
  155. !if "${INSTALLMODE}" == "both"
  156. !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive
  157. !insertmacro MULTIUSER_PAGE_INSTALLMODE
  158. !endif
  159. ; 4. Custom page to ask user if he wants to reinstall/uninstall
  160. ; only if a previous installation was detected
  161. Var ReinstallPageCheck
  162. Page custom PageReinstall PageLeaveReinstall
  163. Function PageReinstall
  164. ; Uninstall previous WiX installation if exists.
  165. ;
  166. ; A WiX installer stores the installation info in registry
  167. ; using a UUID and so we have to loop through all keys under
  168. ; `HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall`
  169. ; and check if `DisplayName` and `Publisher` keys match ${PRODUCTNAME} and ${MANUFACTURER}
  170. ;
  171. ; This has a potential issue that there maybe another installation that matches
  172. ; our ${PRODUCTNAME} and ${MANUFACTURER} but wasn't installed by our WiX installer,
  173. ; however, this should be fine since the user will have to confirm the uninstallation
  174. ; and they can chose to abort it if doesn't make sense.
  175. StrCpy $0 0
  176. wix_loop:
  177. EnumRegKey $1 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" $0
  178. StrCmp $1 "" wix_loop_done ; Exit loop if there is no more keys to loop on
  179. IntOp $0 $0 + 1
  180. ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$1" "DisplayName"
  181. ReadRegStr $R1 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$1" "Publisher"
  182. StrCmp "$R0$R1" "${PRODUCTNAME}${MANUFACTURER}" 0 wix_loop
  183. ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$1" "UninstallString"
  184. ${StrCase} $R1 $R0 "L"
  185. ${StrLoc} $R0 $R1 "msiexec" ">"
  186. StrCmp $R0 0 0 wix_loop_done
  187. StrCpy $WixMode 1
  188. StrCpy $R6 "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$1"
  189. Goto compare_version
  190. wix_loop_done:
  191. ; Check if there is an existing installation, if not, abort the reinstall page
  192. ReadRegStr $R0 SHCTX "${UNINSTKEY}" ""
  193. ReadRegStr $R1 SHCTX "${UNINSTKEY}" "UninstallString"
  194. ${IfThen} "$R0$R1" == "" ${|} Abort ${|}
  195. ; Compare this installar version with the existing installation
  196. ; and modify the messages presented to the user accordingly
  197. compare_version:
  198. StrCpy $R4 "$(older)"
  199. ${If} $WixMode = 1
  200. ReadRegStr $R0 HKLM "$R6" "DisplayVersion"
  201. ${Else}
  202. ReadRegStr $R0 SHCTX "${UNINSTKEY}" "DisplayVersion"
  203. ${EndIf}
  204. ${IfThen} $R0 == "" ${|} StrCpy $R4 "$(unknown)" ${|}
  205. nsis_tauri_utils::SemverCompare "${VERSION}" $R0
  206. Pop $R0
  207. ; Reinstalling the same version
  208. ${If} $R0 = 0
  209. StrCpy $R1 "$(alreadyInstalledLong)"
  210. StrCpy $R2 "$(addOrReinstall)"
  211. StrCpy $R3 "$(uninstallApp)"
  212. !insertmacro MUI_HEADER_TEXT "$(alreadyInstalled)" "$(chooseMaintenanceOption)"
  213. ; Upgrading
  214. ${ElseIf} $R0 = 1
  215. StrCpy $R1 "$(olderOrUnknownVersionInstalled)"
  216. StrCpy $R2 "$(uninstallBeforeInstalling)"
  217. StrCpy $R3 "$(dontUninstall)"
  218. !insertmacro MUI_HEADER_TEXT "$(alreadyInstalled)" "$(choowHowToInstall)"
  219. ; Downgrading
  220. ${ElseIf} $R0 = -1
  221. StrCpy $R1 "$(newerVersionInstalled)"
  222. StrCpy $R2 "$(uninstallBeforeInstalling)"
  223. !if "${ALLOWDOWNGRADES}" == "true"
  224. StrCpy $R3 "$(dontUninstall)"
  225. !else
  226. StrCpy $R3 "$(dontUninstallDowngrade)"
  227. !endif
  228. !insertmacro MUI_HEADER_TEXT "$(alreadyInstalled)" "$(choowHowToInstall)"
  229. ${Else}
  230. Abort
  231. ${EndIf}
  232. ; Skip showing the page if passive
  233. ;
  234. ; Note that we don't call this earlier at the begining
  235. ; of this function because we need to populate some variables
  236. ; related to current installed version if detected and whether
  237. ; we are downgrading or not.
  238. ${If} $PassiveMode = 1
  239. Call PageLeaveReinstall
  240. ${Else}
  241. nsDialogs::Create 1018
  242. Pop $R4
  243. ${IfThen} $(^RTL) = 1 ${|} nsDialogs::SetRTL $(^RTL) ${|}
  244. ${NSD_CreateLabel} 0 0 100% 24u $R1
  245. Pop $R1
  246. ${NSD_CreateRadioButton} 30u 50u -30u 8u $R2
  247. Pop $R2
  248. ${NSD_OnClick} $R2 PageReinstallUpdateSelection
  249. ${NSD_CreateRadioButton} 30u 70u -30u 8u $R3
  250. Pop $R3
  251. ; Disable this radio button if downgrading and downgrades are disabled
  252. !if "${ALLOWDOWNGRADES}" == "false"
  253. ${IfThen} $R0 = -1 ${|} EnableWindow $R3 0 ${|}
  254. !endif
  255. ${NSD_OnClick} $R3 PageReinstallUpdateSelection
  256. ; Check the first radio button if this the first time
  257. ; we enter this page or if the second button wasn't
  258. ; selected the last time we were on this page
  259. ${If} $ReinstallPageCheck <> 2
  260. SendMessage $R2 ${BM_SETCHECK} ${BST_CHECKED} 0
  261. ${Else}
  262. SendMessage $R3 ${BM_SETCHECK} ${BST_CHECKED} 0
  263. ${EndIf}
  264. ${NSD_SetFocus} $R2
  265. nsDialogs::Show
  266. ${EndIf}
  267. FunctionEnd
  268. Function PageReinstallUpdateSelection
  269. ${NSD_GetState} $R2 $R1
  270. ${If} $R1 == ${BST_CHECKED}
  271. StrCpy $ReinstallPageCheck 1
  272. ${Else}
  273. StrCpy $ReinstallPageCheck 2
  274. ${EndIf}
  275. FunctionEnd
  276. Function PageLeaveReinstall
  277. ${NSD_GetState} $R2 $R1
  278. ; If migrating from Wix, always uninstall
  279. ${If} $WixMode = 1
  280. Goto reinst_uninstall
  281. ${EndIf}
  282. ; In update mode, always proceeds without uninstalling
  283. ${If} $UpdateMode = 1
  284. Goto reinst_done
  285. ${EndIf}
  286. ; $R0 holds whether same(0)/upgrading(1)/downgrading(-1) version
  287. ; $R1 holds the radio buttons state:
  288. ; 1 => first choice was selected
  289. ; 0 => second choice was selected
  290. ${If} $R0 = 0 ; Same version, proceed
  291. ${If} $R1 = 1 ; User chose to add/reinstall
  292. Goto reinst_done
  293. ${Else} ; User chose to uninstall
  294. Goto reinst_uninstall
  295. ${EndIf}
  296. ${ElseIf} $R0 = 1 ; Upgrading
  297. ${If} $R1 = 1 ; User chose to uninstall
  298. Goto reinst_uninstall
  299. ${Else}
  300. Goto reinst_done ; User chose NOT to uninstall
  301. ${EndIf}
  302. ${ElseIf} $R0 = -1 ; Downgrading
  303. ${If} $R1 = 1 ; User chose to uninstall
  304. Goto reinst_uninstall
  305. ${Else}
  306. Goto reinst_done ; User chose NOT to uninstall
  307. ${EndIf}
  308. ${EndIf}
  309. reinst_uninstall:
  310. HideWindow
  311. ClearErrors
  312. ${If} $WixMode = 1
  313. ReadRegStr $R1 HKLM "$R6" "UninstallString"
  314. ExecWait '$R1' $0
  315. ${Else}
  316. ReadRegStr $4 SHCTX "${MANUPRODUCTKEY}" ""
  317. ReadRegStr $R1 SHCTX "${UNINSTKEY}" "UninstallString"
  318. ${IfThen} $UpdateMode = 1 ${|} StrCpy $R1 "$R1 /UPDATE" ${|} ; append /UPDATE
  319. ${IfThen} $PassiveMode = 1 ${|} StrCpy $R1 "$R1 /P" ${|} ; append /P
  320. StrCpy $R1 "$R1 _?=$4" ; append uninstall directory
  321. ExecWait '$R1' $0
  322. ${EndIf}
  323. BringToFront
  324. ${IfThen} ${Errors} ${|} StrCpy $0 2 ${|} ; ExecWait failed, set fake exit code
  325. ${If} $0 <> 0
  326. ${OrIf} ${FileExists} "$INSTDIR\${MAINBINARYNAME}.exe"
  327. ; User cancelled wix uninstaller? return to select un/reinstall page
  328. ${If} $WixMode = 1
  329. ${AndIf} $0 = 1602
  330. Abort
  331. ${EndIf}
  332. ; User cancelled NSIS uninstaller? return to select un/reinstall page
  333. ${If} $0 = 1
  334. Abort
  335. ${EndIf}
  336. ; Other erros? show generic error message and return to select un/reinstall page
  337. MessageBox MB_ICONEXCLAMATION "$(unableToUninstall)"
  338. Abort
  339. ${EndIf}
  340. reinst_done:
  341. FunctionEnd
  342. ; 5. Choose install directory page
  343. !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive
  344. !insertmacro MUI_PAGE_DIRECTORY
  345. ; 6. Start menu shortcut page
  346. Var AppStartMenuFolder
  347. !if "${STARTMENUFOLDER}" != ""
  348. !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive
  349. !define MUI_STARTMENUPAGE_DEFAULTFOLDER "${STARTMENUFOLDER}"
  350. !else
  351. !define MUI_PAGE_CUSTOMFUNCTION_PRE Skip
  352. !endif
  353. !insertmacro MUI_PAGE_STARTMENU Application $AppStartMenuFolder
  354. ; 7. Installation page
  355. !insertmacro MUI_PAGE_INSTFILES
  356. ; 8. Finish page
  357. ;
  358. ; Don't auto jump to finish page after installation page,
  359. ; because the installation page has useful info that can be used debug any issues with the installer.
  360. !define MUI_FINISHPAGE_NOAUTOCLOSE
  361. ; Use show readme button in the finish page as a button create a desktop shortcut
  362. !define MUI_FINISHPAGE_SHOWREADME
  363. !define MUI_FINISHPAGE_SHOWREADME_TEXT "$(createDesktop)"
  364. !define MUI_FINISHPAGE_SHOWREADME_FUNCTION CreateOrUpdateDesktopShortcut
  365. ; Show run app after installation.
  366. !define MUI_FINISHPAGE_RUN
  367. !define MUI_FINISHPAGE_RUN_FUNCTION RunMainBinary
  368. !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive
  369. !insertmacro MUI_PAGE_FINISH
  370. Function RunMainBinary
  371. nsis_tauri_utils::RunAsUser "$INSTDIR\${MAINBINARYNAME}.exe" ""
  372. FunctionEnd
  373. ; Uninstaller Pages
  374. ; 1. Confirm uninstall page
  375. Var DeleteAppDataCheckbox
  376. Var DeleteAppDataCheckboxState
  377. !define /ifndef WS_EX_LAYOUTRTL 0x00400000
  378. !define MUI_PAGE_CUSTOMFUNCTION_SHOW un.ConfirmShow
  379. Function un.ConfirmShow ; Add add a `Delete app data` check box
  380. ; $1 inner dialog HWND
  381. ; $2 window DPI
  382. ; $3 style
  383. ; $4 x
  384. ; $5 y
  385. ; $6 width
  386. ; $7 height
  387. FindWindow $1 "#32770" "" $HWNDPARENT ; Find inner dialog
  388. System::Call "user32::GetDpiForWindow(p r1) i .r2"
  389. ${If} $(^RTL) = 1
  390. StrCpy $3 "${__NSD_CheckBox_EXSTYLE} | ${WS_EX_LAYOUTRTL}"
  391. IntOp $4 50 * $2
  392. ${Else}
  393. StrCpy $3 "${__NSD_CheckBox_EXSTYLE}"
  394. IntOp $4 0 * $2
  395. ${EndIf}
  396. IntOp $5 100 * $2
  397. IntOp $6 400 * $2
  398. IntOp $7 25 * $2
  399. IntOp $4 $4 / 96
  400. IntOp $5 $5 / 96
  401. IntOp $6 $6 / 96
  402. IntOp $7 $7 / 96
  403. System::Call 'user32::CreateWindowEx(i r3, w "${__NSD_CheckBox_CLASS}", w "$(deleteAppData)", i ${__NSD_CheckBox_STYLE}, i r4, i r5, i r6, i r7, p r1, i0, i0, i0) i .s'
  404. Pop $DeleteAppDataCheckbox
  405. SendMessage $HWNDPARENT ${WM_GETFONT} 0 0 $1
  406. SendMessage $DeleteAppDataCheckbox ${WM_SETFONT} $1 1
  407. FunctionEnd
  408. !define MUI_PAGE_CUSTOMFUNCTION_LEAVE un.ConfirmLeave
  409. Function un.ConfirmLeave
  410. SendMessage $DeleteAppDataCheckbox ${BM_GETCHECK} 0 0 $DeleteAppDataCheckboxState
  411. FunctionEnd
  412. !define MUI_PAGE_CUSTOMFUNCTION_PRE un.SkipIfPassive
  413. !insertmacro MUI_UNPAGE_CONFIRM
  414. ; 2. Uninstalling Page
  415. !insertmacro MUI_UNPAGE_INSTFILES
  416. ;Languages
  417. {{#each languages}}
  418. !insertmacro MUI_LANGUAGE "{{this}}"
  419. {{/each}}
  420. !insertmacro MUI_RESERVEFILE_LANGDLL
  421. {{#each language_files}}
  422. !include "{{this}}"
  423. {{/each}}
  424. Function .onInit
  425. ${GetOptions} $CMDLINE "/P" $PassiveMode
  426. ${IfNot} ${Errors}
  427. StrCpy $PassiveMode 1
  428. ${EndIf}
  429. ${GetOptions} $CMDLINE "/NS" $NoShortcutMode
  430. ${IfNot} ${Errors}
  431. StrCpy $NoShortcutMode 1
  432. ${EndIf}
  433. ${GetOptions} $CMDLINE "/UPDATE" $UpdateMode
  434. ${IfNot} ${Errors}
  435. StrCpy $UpdateMode 1
  436. ${EndIf}
  437. !if "${DISPLAYLANGUAGESELECTOR}" == "true"
  438. !insertmacro MUI_LANGDLL_DISPLAY
  439. !endif
  440. !insertmacro SetContext
  441. ${If} $INSTDIR == "${PLACEHOLDER_INSTALL_DIR}"
  442. ; Prefer D drive as default install location when available.
  443. ${If} ${FileExists} "D:\*.*"
  444. StrCpy $INSTDIR "D:\${INSTALLDIRNAME}"
  445. ${Else}
  446. ; Fall back to install mode defaults.
  447. !if "${INSTALLMODE}" == "perMachine"
  448. ${If} ${RunningX64}
  449. !if "${ARCH}" == "x64"
  450. StrCpy $INSTDIR "$PROGRAMFILES64\${INSTALLDIRNAME}"
  451. !else if "${ARCH}" == "arm64"
  452. StrCpy $INSTDIR "$PROGRAMFILES64\${INSTALLDIRNAME}"
  453. !else
  454. StrCpy $INSTDIR "$PROGRAMFILES\${INSTALLDIRNAME}"
  455. !endif
  456. ${Else}
  457. StrCpy $INSTDIR "$PROGRAMFILES\${INSTALLDIRNAME}"
  458. ${EndIf}
  459. !else if "${INSTALLMODE}" == "currentUser"
  460. StrCpy $INSTDIR "$LOCALAPPDATA\${INSTALLDIRNAME}"
  461. !endif
  462. ${EndIf}
  463. Call RestorePreviousInstallLocation
  464. ${EndIf}
  465. !if "${INSTALLMODE}" == "both"
  466. !insertmacro MULTIUSER_INIT
  467. !endif
  468. FunctionEnd
  469. Section EarlyChecks
  470. ; Abort silent installer if downgrades is disabled
  471. !if "${ALLOWDOWNGRADES}" == "false"
  472. ${If} ${Silent}
  473. ; If downgrading
  474. ${If} $R0 = -1
  475. System::Call 'kernel32::AttachConsole(i -1)i.r0'
  476. ${If} $0 <> 0
  477. System::Call 'kernel32::GetStdHandle(i -11)i.r0'
  478. System::call 'kernel32::SetConsoleTextAttribute(i r0, i 0x0004)' ; set red color
  479. FileWrite $0 "$(silentDowngrades)"
  480. ${EndIf}
  481. Abort
  482. ${EndIf}
  483. ${EndIf}
  484. !endif
  485. SectionEnd
  486. Section WebView2
  487. ; Check if Webview2 is already installed and skip this section
  488. ${If} ${RunningX64}
  489. ReadRegStr $4 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\${WEBVIEW2APPGUID}" "pv"
  490. ${Else}
  491. ReadRegStr $4 HKLM "SOFTWARE\Microsoft\EdgeUpdate\Clients\${WEBVIEW2APPGUID}" "pv"
  492. ${EndIf}
  493. ${If} $4 == ""
  494. ReadRegStr $4 HKCU "SOFTWARE\Microsoft\EdgeUpdate\Clients\${WEBVIEW2APPGUID}" "pv"
  495. ${EndIf}
  496. ${If} $4 == ""
  497. ; Webview2 installation
  498. ;
  499. ; Skip if updating
  500. ${If} $UpdateMode <> 1
  501. !if "${INSTALLWEBVIEW2MODE}" == "downloadBootstrapper"
  502. Delete "$TEMP\MicrosoftEdgeWebview2Setup.exe"
  503. DetailPrint "$(webview2Downloading)"
  504. NSISdl::download "https://go.microsoft.com/fwlink/p/?LinkId=2124703" "$TEMP\MicrosoftEdgeWebview2Setup.exe"
  505. Pop $0
  506. ${If} $0 == "success"
  507. DetailPrint "$(webview2DownloadSuccess)"
  508. ${Else}
  509. DetailPrint "$(webview2DownloadError)"
  510. Abort "$(webview2AbortError)"
  511. ${EndIf}
  512. StrCpy $6 "$TEMP\MicrosoftEdgeWebview2Setup.exe"
  513. Goto install_webview2
  514. !endif
  515. !if "${INSTALLWEBVIEW2MODE}" == "embedBootstrapper"
  516. Delete "$TEMP\MicrosoftEdgeWebview2Setup.exe"
  517. File "/oname=$TEMP\MicrosoftEdgeWebview2Setup.exe" "${WEBVIEW2BOOTSTRAPPERPATH}"
  518. DetailPrint "$(installingWebview2)"
  519. StrCpy $6 "$TEMP\MicrosoftEdgeWebview2Setup.exe"
  520. Goto install_webview2
  521. !endif
  522. !if "${INSTALLWEBVIEW2MODE}" == "offlineInstaller"
  523. Delete "$TEMP\MicrosoftEdgeWebView2RuntimeInstaller.exe"
  524. File "/oname=$TEMP\MicrosoftEdgeWebView2RuntimeInstaller.exe" "${WEBVIEW2INSTALLERPATH}"
  525. DetailPrint "$(installingWebview2)"
  526. StrCpy $6 "$TEMP\MicrosoftEdgeWebView2RuntimeInstaller.exe"
  527. Goto install_webview2
  528. !endif
  529. Goto webview2_done
  530. install_webview2:
  531. DetailPrint "$(installingWebview2)"
  532. ; $6 holds the path to the webview2 installer
  533. ExecWait "$6 ${WEBVIEW2INSTALLERARGS} /install" $1
  534. ${If} $1 = 0
  535. DetailPrint "$(webview2InstallSuccess)"
  536. ${Else}
  537. DetailPrint "$(webview2InstallError)"
  538. Abort "$(webview2AbortError)"
  539. ${EndIf}
  540. webview2_done:
  541. ${EndIf}
  542. ${Else}
  543. !if "${MINIMUMWEBVIEW2VERSION}" != ""
  544. ${VersionCompare} "${MINIMUMWEBVIEW2VERSION}" "$4" $R0
  545. ${If} $R0 = 1
  546. update_webview:
  547. DetailPrint "$(installingWebview2)"
  548. ${If} ${RunningX64}
  549. ReadRegStr $R1 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate" "path"
  550. ${Else}
  551. ReadRegStr $R1 HKLM "SOFTWARE\Microsoft\EdgeUpdate" "path"
  552. ${EndIf}
  553. ${If} $R1 == ""
  554. ReadRegStr $R1 HKCU "SOFTWARE\Microsoft\EdgeUpdate" "path"
  555. ${EndIf}
  556. ${If} $R1 != ""
  557. ; Chromium updater docs: https://source.chromium.org/chromium/chromium/src/+/main:docs/updater/user_manual.md
  558. ; Modified from "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Microsoft EdgeWebView\ModifyPath"
  559. ExecWait `"$R1" /install appguid=${WEBVIEW2APPGUID}&needsadmin=true` $1
  560. ${If} $1 = 0
  561. DetailPrint "$(webview2InstallSuccess)"
  562. ${Else}
  563. MessageBox MB_ICONEXCLAMATION|MB_ABORTRETRYIGNORE "$(webview2InstallError)" IDIGNORE ignore IDRETRY update_webview
  564. Quit
  565. ignore:
  566. ${EndIf}
  567. ${EndIf}
  568. ${EndIf}
  569. !endif
  570. ${EndIf}
  571. SectionEnd
  572. Function WaitForMainBinaryRelease
  573. StrCpy $0 0
  574. wait_main_binary_release:
  575. Delete "$INSTDIR\${MAINBINARYNAME}.exe"
  576. IfFileExists "$INSTDIR\${MAINBINARYNAME}.exe" 0 wait_main_binary_released
  577. IntOp $0 $0 + 1
  578. ${If} $0 >= 30
  579. Abort "当前程序文件仍被占用,请完全退出 QMaiWrite 后重试。"
  580. ${EndIf}
  581. Sleep 500
  582. Goto wait_main_binary_release
  583. wait_main_binary_released:
  584. FunctionEnd
  585. Section Install
  586. SetOutPath $INSTDIR
  587. !ifmacrodef NSIS_HOOK_PREINSTALL
  588. !insertmacro NSIS_HOOK_PREINSTALL
  589. !endif
  590. !insertmacro CheckIfAppIsRunning "${MAINBINARYNAME}.exe" "${PRODUCTNAME}"
  591. Call WaitForMainBinaryRelease
  592. ; Copy main executable
  593. File "${MAINBINARYSRCPATH}"
  594. ; Copy resources
  595. {{#each resources_dirs}}
  596. CreateDirectory "$INSTDIR\\{{this}}"
  597. {{/each}}
  598. {{#each resources}}
  599. File /a "/oname={{this.[1]}}" "{{no-escape @key}}"
  600. {{/each}}
  601. ; Copy external binaries
  602. {{#each binaries}}
  603. File /a "/oname={{this}}" "{{no-escape @key}}"
  604. {{/each}}
  605. ; Create file associations
  606. {{#each file_associations as |association| ~}}
  607. {{#each association.ext as |ext| ~}}
  608. !insertmacro APP_ASSOCIATE "{{ext}}" "{{or association.name ext}}" "{{association-description association.description ext}}" "$INSTDIR\${MAINBINARYNAME}.exe,0" "Open with ${PRODUCTNAME}" "$INSTDIR\${MAINBINARYNAME}.exe $\"%1$\""
  609. {{/each}}
  610. {{/each}}
  611. ; Register deep links
  612. {{#each deep_link_protocols as |protocol| ~}}
  613. WriteRegStr SHCTX "Software\Classes\\{{protocol}}" "URL Protocol" ""
  614. WriteRegStr SHCTX "Software\Classes\\{{protocol}}" "" "URL:${BUNDLEID} protocol"
  615. WriteRegStr SHCTX "Software\Classes\\{{protocol}}\DefaultIcon" "" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\",0"
  616. WriteRegStr SHCTX "Software\Classes\\{{protocol}}\shell\open\command" "" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\" $\"%1$\""
  617. {{/each}}
  618. ; Create uninstaller
  619. WriteUninstaller "$INSTDIR\uninstall.exe"
  620. ; Save $INSTDIR in registry for future installations
  621. WriteRegStr SHCTX "${MANUPRODUCTKEY}" "" $INSTDIR
  622. !if "${INSTALLMODE}" == "both"
  623. ; Save install mode to be selected by default for the next installation such as updating
  624. ; or when uninstalling
  625. WriteRegStr SHCTX "${UNINSTKEY}" $MultiUser.InstallMode 1
  626. !endif
  627. ; Remove old main binary if it doesn't match new main binary name
  628. ReadRegStr $OldMainBinaryName SHCTX "${UNINSTKEY}" "MainBinaryName"
  629. ${If} $OldMainBinaryName != ""
  630. ${AndIf} $OldMainBinaryName != "${MAINBINARYNAME}.exe"
  631. Delete "$INSTDIR\$OldMainBinaryName"
  632. ${EndIf}
  633. ; Save current MAINBINARYNAME for future updates
  634. WriteRegStr SHCTX "${UNINSTKEY}" "MainBinaryName" "${MAINBINARYNAME}.exe"
  635. ; Registry information for add/remove programs
  636. WriteRegStr SHCTX "${UNINSTKEY}" "DisplayName" "${PRODUCTNAME}"
  637. WriteRegStr SHCTX "${UNINSTKEY}" "DisplayIcon" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\""
  638. WriteRegStr SHCTX "${UNINSTKEY}" "DisplayVersion" "${VERSION}"
  639. WriteRegStr SHCTX "${UNINSTKEY}" "Publisher" "${MANUFACTURER}"
  640. WriteRegStr SHCTX "${UNINSTKEY}" "InstallLocation" "$\"$INSTDIR$\""
  641. WriteRegStr SHCTX "${UNINSTKEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\""
  642. WriteRegDWORD SHCTX "${UNINSTKEY}" "NoModify" "1"
  643. WriteRegDWORD SHCTX "${UNINSTKEY}" "NoRepair" "1"
  644. ${GetSize} "$INSTDIR" "/M=uninstall.exe /S=0K /G=0" $0 $1 $2
  645. IntOp $0 $0 + ${ESTIMATEDSIZE}
  646. IntFmt $0 "0x%08X" $0
  647. WriteRegDWORD SHCTX "${UNINSTKEY}" "EstimatedSize" "$0"
  648. !if "${HOMEPAGE}" != ""
  649. WriteRegStr SHCTX "${UNINSTKEY}" "URLInfoAbout" "${HOMEPAGE}"
  650. WriteRegStr SHCTX "${UNINSTKEY}" "URLUpdateInfo" "${HOMEPAGE}"
  651. WriteRegStr SHCTX "${UNINSTKEY}" "HelpLink" "${HOMEPAGE}"
  652. !endif
  653. ; Create start menu shortcut
  654. !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
  655. Call CreateOrUpdateStartMenuShortcut
  656. !insertmacro MUI_STARTMENU_WRITE_END
  657. ; Create desktop shortcut for silent and passive installers
  658. ; because finish page will be skipped
  659. ${If} $PassiveMode = 1
  660. ${OrIf} ${Silent}
  661. Call CreateOrUpdateDesktopShortcut
  662. ${EndIf}
  663. !ifmacrodef NSIS_HOOK_POSTINSTALL
  664. !insertmacro NSIS_HOOK_POSTINSTALL
  665. !endif
  666. ; Auto close this page for passive mode
  667. ${If} $PassiveMode = 1
  668. SetAutoClose true
  669. ${EndIf}
  670. SectionEnd
  671. Function .onInstSuccess
  672. ; Check for `/R` flag only in silent and passive installers because
  673. ; GUI installer has a toggle for the user to (re)start the app
  674. ${If} $PassiveMode = 1
  675. ${OrIf} ${Silent}
  676. ${GetOptions} $CMDLINE "/R" $R0
  677. ${IfNot} ${Errors}
  678. ${GetOptions} $CMDLINE "/ARGS" $R0
  679. nsis_tauri_utils::RunAsUser "$INSTDIR\${MAINBINARYNAME}.exe" "$R0"
  680. ${EndIf}
  681. ${EndIf}
  682. FunctionEnd
  683. Function un.onInit
  684. !insertmacro SetContext
  685. !if "${INSTALLMODE}" == "both"
  686. !insertmacro MULTIUSER_UNINIT
  687. !endif
  688. !insertmacro MUI_UNGETLANGUAGE
  689. ${GetOptions} $CMDLINE "/P" $PassiveMode
  690. ${IfNot} ${Errors}
  691. StrCpy $PassiveMode 1
  692. ${EndIf}
  693. ${GetOptions} $CMDLINE "/UPDATE" $UpdateMode
  694. ${IfNot} ${Errors}
  695. StrCpy $UpdateMode 1
  696. ${EndIf}
  697. FunctionEnd
  698. Section Uninstall
  699. !ifmacrodef NSIS_HOOK_PREUNINSTALL
  700. !insertmacro NSIS_HOOK_PREUNINSTALL
  701. !endif
  702. !insertmacro CheckIfAppIsRunning "${MAINBINARYNAME}.exe" "${PRODUCTNAME}"
  703. ; Delete the app directory and its content from disk
  704. ; Copy main executable
  705. Delete "$INSTDIR\${MAINBINARYNAME}.exe"
  706. ; Delete resources
  707. {{#each resources}}
  708. Delete "$INSTDIR\\{{this.[1]}}"
  709. {{/each}}
  710. ; Delete external binaries
  711. {{#each binaries}}
  712. Delete "$INSTDIR\\{{this}}"
  713. {{/each}}
  714. ; Delete app associations
  715. {{#each file_associations as |association| ~}}
  716. {{#each association.ext as |ext| ~}}
  717. !insertmacro APP_UNASSOCIATE "{{ext}}" "{{or association.name ext}}"
  718. {{/each}}
  719. {{/each}}
  720. ; Delete deep links
  721. {{#each deep_link_protocols as |protocol| ~}}
  722. ReadRegStr $R7 SHCTX "Software\Classes\\{{protocol}}\shell\open\command" ""
  723. ${If} $R7 == "$\"$INSTDIR\${MAINBINARYNAME}.exe$\" $\"%1$\""
  724. DeleteRegKey SHCTX "Software\Classes\\{{protocol}}"
  725. ${EndIf}
  726. {{/each}}
  727. ; Delete uninstaller
  728. Delete "$INSTDIR\uninstall.exe"
  729. {{#each resources_ancestors}}
  730. RMDir /REBOOTOK "$INSTDIR\\{{this}}"
  731. {{/each}}
  732. RMDir "$INSTDIR"
  733. ; Remove shortcuts if not updating
  734. ${If} $UpdateMode <> 1
  735. !insertmacro DeleteAppUserModelId
  736. ; Remove start menu shortcut
  737. !insertmacro MUI_STARTMENU_GETFOLDER Application $AppStartMenuFolder
  738. !insertmacro IsShortcutTarget "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
  739. Pop $0
  740. ${If} $0 = 1
  741. !insertmacro UnpinShortcut "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk"
  742. Delete "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk"
  743. RMDir "$SMPROGRAMS\$AppStartMenuFolder"
  744. ${EndIf}
  745. !insertmacro IsShortcutTarget "$SMPROGRAMS\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
  746. Pop $0
  747. ${If} $0 = 1
  748. !insertmacro UnpinShortcut "$SMPROGRAMS\${PRODUCTNAME}.lnk"
  749. Delete "$SMPROGRAMS\${PRODUCTNAME}.lnk"
  750. ${EndIf}
  751. ; Remove desktop shortcuts
  752. !insertmacro IsShortcutTarget "$DESKTOP\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
  753. Pop $0
  754. ${If} $0 = 1
  755. !insertmacro UnpinShortcut "$DESKTOP\${PRODUCTNAME}.lnk"
  756. Delete "$DESKTOP\${PRODUCTNAME}.lnk"
  757. ${EndIf}
  758. ${EndIf}
  759. ; Remove registry information for add/remove programs
  760. !if "${INSTALLMODE}" == "both"
  761. DeleteRegKey SHCTX "${UNINSTKEY}"
  762. !else if "${INSTALLMODE}" == "perMachine"
  763. DeleteRegKey HKLM "${UNINSTKEY}"
  764. !else
  765. DeleteRegKey HKCU "${UNINSTKEY}"
  766. !endif
  767. ; Removes the Autostart entry for ${PRODUCTNAME} from the HKCU Run key if it exists.
  768. ; This ensures the program does not launch automatically after uninstallation if it exists.
  769. ; If it doesn't exist, it does nothing.
  770. ; We do this when not updating (to preserve the registry value on updates)
  771. ${If} $UpdateMode <> 1
  772. DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "${PRODUCTNAME}"
  773. ${EndIf}
  774. ; Delete app data if the checkbox is selected
  775. ; and if not updating
  776. ${If} $DeleteAppDataCheckboxState = 1
  777. ${AndIf} $UpdateMode <> 1
  778. ; Clear the install location $INSTDIR from registry
  779. DeleteRegKey SHCTX "${MANUPRODUCTKEY}"
  780. DeleteRegKey /ifempty SHCTX "${MANUKEY}"
  781. ; Clear the install language from registry
  782. DeleteRegValue HKCU "${MANUPRODUCTKEY}" "Installer Language"
  783. DeleteRegKey /ifempty HKCU "${MANUPRODUCTKEY}"
  784. DeleteRegKey /ifempty HKCU "${MANUKEY}"
  785. SetShellVarContext current
  786. RmDir /r "$APPDATA\${BUNDLEID}"
  787. RmDir /r "$LOCALAPPDATA\${BUNDLEID}"
  788. ${EndIf}
  789. !ifmacrodef NSIS_HOOK_POSTUNINSTALL
  790. !insertmacro NSIS_HOOK_POSTUNINSTALL
  791. !endif
  792. ; Auto close if passive mode or updating
  793. ${If} $PassiveMode = 1
  794. ${OrIf} $UpdateMode = 1
  795. SetAutoClose true
  796. ${EndIf}
  797. SectionEnd
  798. Function RestorePreviousInstallLocation
  799. ReadRegStr $4 SHCTX "${MANUPRODUCTKEY}" ""
  800. StrCmp $4 "" +2 0
  801. StrCpy $INSTDIR $4
  802. FunctionEnd
  803. Function Skip
  804. Abort
  805. FunctionEnd
  806. Function SkipIfPassive
  807. ${IfThen} $PassiveMode = 1 ${|} Abort ${|}
  808. FunctionEnd
  809. Function un.SkipIfPassive
  810. ${IfThen} $PassiveMode = 1 ${|} Abort ${|}
  811. FunctionEnd
  812. Function CreateOrUpdateStartMenuShortcut
  813. ; We used to use product name as MAINBINARYNAME
  814. ; migrate old shortcuts to target the new MAINBINARYNAME
  815. StrCpy $R0 0
  816. !insertmacro IsShortcutTarget "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk" "$INSTDIR\$OldMainBinaryName"
  817. Pop $0
  818. ${If} $0 = 1
  819. !insertmacro SetShortcutTarget "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
  820. StrCpy $R0 1
  821. ${EndIf}
  822. !insertmacro IsShortcutTarget "$SMPROGRAMS\${PRODUCTNAME}.lnk" "$INSTDIR\$OldMainBinaryName"
  823. Pop $0
  824. ${If} $0 = 1
  825. !insertmacro SetShortcutTarget "$SMPROGRAMS\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
  826. StrCpy $R0 1
  827. ${EndIf}
  828. ${If} $R0 = 1
  829. Return
  830. ${EndIf}
  831. ; Skip creating shortcut if in update mode or no shortcut mode
  832. ; but always create if migrating from wix
  833. ${If} $WixMode = 0
  834. ${If} $UpdateMode = 1
  835. ${OrIf} $NoShortcutMode = 1
  836. Return
  837. ${EndIf}
  838. ${EndIf}
  839. !if "${STARTMENUFOLDER}" != ""
  840. CreateDirectory "$SMPROGRAMS\$AppStartMenuFolder"
  841. CreateShortcut "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
  842. !insertmacro SetLnkAppUserModelId "$SMPROGRAMS\$AppStartMenuFolder\${PRODUCTNAME}.lnk"
  843. !else
  844. CreateShortcut "$SMPROGRAMS\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
  845. !insertmacro SetLnkAppUserModelId "$SMPROGRAMS\${PRODUCTNAME}.lnk"
  846. !endif
  847. FunctionEnd
  848. Function CreateOrUpdateDesktopShortcut
  849. ; We used to use product name as MAINBINARYNAME
  850. ; migrate old shortcuts to target the new MAINBINARYNAME
  851. !insertmacro IsShortcutTarget "$DESKTOP\${PRODUCTNAME}.lnk" "$INSTDIR\$OldMainBinaryName"
  852. Pop $0
  853. ${If} $0 = 1
  854. !insertmacro SetShortcutTarget "$DESKTOP\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
  855. Return
  856. ${EndIf}
  857. ; Skip creating shortcut if in update mode or no shortcut mode
  858. ; but always create if migrating from wix
  859. ${If} $WixMode = 0
  860. ${If} $UpdateMode = 1
  861. ${OrIf} $NoShortcutMode = 1
  862. Return
  863. ${EndIf}
  864. ${EndIf}
  865. CreateShortcut "$DESKTOP\${PRODUCTNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
  866. !insertmacro SetLnkAppUserModelId "$DESKTOP\${PRODUCTNAME}.lnk"
  867. FunctionEnd