_tauri-installer-template.nsi 32 KB

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