installer.nsi 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  1. ; This file is copied from https://github.com/tauri-apps/tauri/blob/tauri-v1.5/tooling/bundler/src/bundle/windows/templates/installer.nsi
  2. ; and edit to fit the needs of the project. the latest tauri 2.x has a different base nsi script.
  3. Unicode true
  4. ; Set the compression algorithm. Default is LZMA.
  5. !if "{{compression}}" == ""
  6. SetCompressor /SOLID lzma
  7. !else
  8. SetCompressor /SOLID "{{compression}}"
  9. !endif
  10. !include MUI2.nsh
  11. !include FileFunc.nsh
  12. !include x64.nsh
  13. !include WordFunc.nsh
  14. !include "LogicLib.nsh"
  15. !include "StrFunc.nsh"
  16. !addplugindir "$%AppData%\Local\NSIS\"
  17. ${StrCase}
  18. ${StrLoc}
  19. !define MANUFACTURER "{{manufacturer}}"
  20. !define PRODUCTNAME "{{product_name}}"
  21. !define VERSION "{{version}}"
  22. !define VERSIONWITHBUILD "{{version_with_build}}"
  23. !define SHORTDESCRIPTION "{{short_description}}"
  24. !define INSTALLMODE "{{install_mode}}"
  25. !define LICENSE "{{license}}"
  26. !define INSTALLERICON "{{installer_icon}}"
  27. !define SIDEBARIMAGE "{{sidebar_image}}"
  28. !define HEADERIMAGE "{{header_image}}"
  29. !define MAINBINARYNAME "{{main_binary_name}}"
  30. !define MAINBINARYSRCPATH "{{main_binary_path}}"
  31. !define BUNDLEID "{{bundle_id}}"
  32. !define COPYRIGHT "{{copyright}}"
  33. !define OUTFILE "{{out_file}}"
  34. !define ARCH "{{arch}}"
  35. !define PLUGINSPATH "{{additional_plugins_path}}"
  36. !define ALLOWDOWNGRADES "{{allow_downgrades}}"
  37. !define DISPLAYLANGUAGESELECTOR "{{display_language_selector}}"
  38. !define INSTALLWEBVIEW2MODE "{{install_webview2_mode}}"
  39. !define WEBVIEW2INSTALLERARGS "{{webview2_installer_args}}"
  40. !define WEBVIEW2BOOTSTRAPPERPATH "{{webview2_bootstrapper_path}}"
  41. !define WEBVIEW2INSTALLERPATH "{{webview2_installer_path}}"
  42. !define UNINSTKEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCTNAME}"
  43. !define MANUPRODUCTKEY "Software\${MANUFACTURER}\${PRODUCTNAME}"
  44. !define UNINSTALLERSIGNCOMMAND "{{uninstaller_sign_cmd}}"
  45. !define ESTIMATEDSIZE "{{estimated_size}}"
  46. Name "${PRODUCTNAME}"
  47. BrandingText "${COPYRIGHT}"
  48. OutFile "${OUTFILE}"
  49. VIProductVersion "${VERSIONWITHBUILD}"
  50. VIAddVersionKey "ProductName" "${PRODUCTNAME}"
  51. VIAddVersionKey "FileDescription" "${SHORTDESCRIPTION}"
  52. VIAddVersionKey "LegalCopyright" "${COPYRIGHT}"
  53. VIAddVersionKey "FileVersion" "${VERSION}"
  54. VIAddVersionKey "ProductVersion" "${VERSION}"
  55. ; Plugins path, currently exists for linux only
  56. !if "${PLUGINSPATH}" != ""
  57. !addplugindir "${PLUGINSPATH}"
  58. !endif
  59. !if "${UNINSTALLERSIGNCOMMAND}" != ""
  60. !uninstfinalize '${UNINSTALLERSIGNCOMMAND}'
  61. !endif
  62. ; Handle install mode, `perUser`, `perMachine` or `both`
  63. !if "${INSTALLMODE}" == "perMachine"
  64. RequestExecutionLevel highest
  65. !endif
  66. !if "${INSTALLMODE}" == "currentUser"
  67. RequestExecutionLevel user
  68. !endif
  69. !if "${INSTALLMODE}" == "both"
  70. !define MULTIUSER_MUI
  71. !define MULTIUSER_INSTALLMODE_INSTDIR "${PRODUCTNAME}"
  72. !define MULTIUSER_INSTALLMODE_COMMANDLINE
  73. !if "${ARCH}" == "x64"
  74. !define MULTIUSER_USE_PROGRAMFILES64
  75. !else if "${ARCH}" == "arm64"
  76. !define MULTIUSER_USE_PROGRAMFILES64
  77. !endif
  78. !define MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY "${UNINSTKEY}"
  79. !define MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME "CurrentUser"
  80. !define MULTIUSER_INSTALLMODEPAGE_SHOWUSERNAME
  81. !define MULTIUSER_INSTALLMODE_FUNCTION RestorePreviousInstallLocation
  82. !define MULTIUSER_EXECUTIONLEVEL Highest
  83. !include MultiUser.nsh
  84. !endif
  85. ; installer icon
  86. !if "${INSTALLERICON}" != ""
  87. !define MUI_ICON "${INSTALLERICON}"
  88. !endif
  89. ; installer sidebar image
  90. !if "${SIDEBARIMAGE}" != ""
  91. !define MUI_WELCOMEFINISHPAGE_BITMAP "${SIDEBARIMAGE}"
  92. !endif
  93. ; installer header image
  94. !if "${HEADERIMAGE}" != ""
  95. !define MUI_HEADERIMAGE
  96. !define MUI_HEADERIMAGE_BITMAP "${HEADERIMAGE}"
  97. !endif
  98. ; Define registry key to store installer language
  99. !define MUI_LANGDLL_REGISTRY_ROOT "HKCU"
  100. !define MUI_LANGDLL_REGISTRY_KEY "${MANUPRODUCTKEY}"
  101. !define MUI_LANGDLL_REGISTRY_VALUENAME "Installer Language"
  102. ; Installer pages, must be ordered as they appear
  103. ; 1. Welcome Page
  104. !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive
  105. !insertmacro MUI_PAGE_WELCOME
  106. ; 2. License Page (if defined)
  107. !if "${LICENSE}" != ""
  108. !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive
  109. !insertmacro MUI_PAGE_LICENSE "${LICENSE}"
  110. !endif
  111. ; 3. Install mode (if it is set to `both`)
  112. !if "${INSTALLMODE}" == "both"
  113. !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive
  114. !insertmacro MULTIUSER_PAGE_INSTALLMODE
  115. !endif
  116. ; 4. Custom page to ask user if he wants to reinstall/uninstall
  117. ; only if a previous installtion was detected
  118. Var ReinstallPageCheck
  119. Page custom PageReinstall PageLeaveReinstall
  120. Function PageReinstall
  121. ; Uninstall previous WiX installation if exists.
  122. ;
  123. ; A WiX installer stores the isntallation info in registry
  124. ; using a UUID and so we have to loop through all keys under
  125. ; `HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall`
  126. ; and check if `DisplayName` and `Publisher` keys match ${PRODUCTNAME} and ${MANUFACTURER}
  127. ;
  128. ; This has a potentional issue that there maybe another installation that matches
  129. ; our ${PRODUCTNAME} and ${MANUFACTURER} but wasn't installed by our WiX installer,
  130. ; however, this should be fine since the user will have to confirm the uninstallation
  131. ; and they can chose to abort it if doesn't make sense.
  132. StrCpy $0 0
  133. wix_loop:
  134. EnumRegKey $1 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" $0
  135. StrCmp $1 "" wix_done ; Exit loop if there is no more keys to loop on
  136. IntOp $0 $0 + 1
  137. ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$1" "DisplayName"
  138. ReadRegStr $R1 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$1" "Publisher"
  139. StrCmp "$R0$R1" "${PRODUCTNAME}${MANUFACTURER}" 0 wix_loop
  140. ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$1" "UninstallString"
  141. ${StrCase} $R1 $R0 "L"
  142. ${StrLoc} $R0 $R1 "msiexec" ">"
  143. StrCmp $R0 0 0 wix_done
  144. StrCpy $R7 "wix"
  145. StrCpy $R6 "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$1"
  146. Goto compare_version
  147. wix_done:
  148. ; Check if there is an existing installation, if not, abort the reinstall page
  149. ReadRegStr $R0 SHCTX "${UNINSTKEY}" ""
  150. ReadRegStr $R1 SHCTX "${UNINSTKEY}" "UninstallString"
  151. ${IfThen} "$R0$R1" == "" ${|} Abort ${|}
  152. ; Compare this installar version with the existing installation
  153. ; and modify the messages presented to the user accordingly
  154. compare_version:
  155. StrCpy $R4 "$(older)"
  156. ${If} $R7 == "wix"
  157. ReadRegStr $R0 HKLM "$R6" "DisplayVersion"
  158. ${Else}
  159. ReadRegStr $R0 SHCTX "${UNINSTKEY}" "DisplayVersion"
  160. ${EndIf}
  161. ${IfThen} $R0 == "" ${|} StrCpy $R4 "$(unknown)" ${|}
  162. nsis_tauri_utils::SemverCompare "${VERSION}" $R0
  163. Pop $R0
  164. ; Reinstalling the same version
  165. ${If} $R0 == 0
  166. StrCpy $R1 "$(alreadyInstalledLong)"
  167. StrCpy $R2 "$(addOrReinstall)"
  168. StrCpy $R3 "$(uninstallApp)"
  169. !insertmacro MUI_HEADER_TEXT "$(alreadyInstalled)" "$(chooseMaintenanceOption)"
  170. StrCpy $R5 "2"
  171. ; Upgrading
  172. ${ElseIf} $R0 == 1
  173. StrCpy $R1 "$(olderOrUnknownVersionInstalled)"
  174. StrCpy $R2 "$(uninstallBeforeInstalling)"
  175. StrCpy $R3 "$(dontUninstall)"
  176. !insertmacro MUI_HEADER_TEXT "$(alreadyInstalled)" "$(choowHowToInstall)"
  177. StrCpy $R5 "1"
  178. ; Downgrading
  179. ${ElseIf} $R0 == -1
  180. StrCpy $R1 "$(newerVersionInstalled)"
  181. StrCpy $R2 "$(uninstallBeforeInstalling)"
  182. !if "${ALLOWDOWNGRADES}" == "true"
  183. StrCpy $R3 "$(dontUninstall)"
  184. !else
  185. StrCpy $R3 "$(dontUninstallDowngrade)"
  186. !endif
  187. !insertmacro MUI_HEADER_TEXT "$(alreadyInstalled)" "$(choowHowToInstall)"
  188. StrCpy $R5 "1"
  189. ${Else}
  190. Abort
  191. ${EndIf}
  192. Call SkipIfPassive
  193. nsDialogs::Create 1018
  194. Pop $R4
  195. ${IfThen} $(^RTL) == 1 ${|} nsDialogs::SetRTL $(^RTL) ${|}
  196. ${NSD_CreateLabel} 0 0 100% 24u $R1
  197. Pop $R1
  198. ${NSD_CreateRadioButton} 30u 50u -30u 8u $R2
  199. Pop $R2
  200. ${NSD_OnClick} $R2 PageReinstallUpdateSelection
  201. ${NSD_CreateRadioButton} 30u 70u -30u 8u $R3
  202. Pop $R3
  203. ; disable this radio button if downgrading and downgrades are disabled
  204. !if "${ALLOWDOWNGRADES}" == "false"
  205. ${IfThen} $R0 == -1 ${|} EnableWindow $R3 0 ${|}
  206. !endif
  207. ${NSD_OnClick} $R3 PageReinstallUpdateSelection
  208. ; Check the first radio button if this the first time
  209. ; we enter this page or if the second button wasn't
  210. ; selected the last time we were on this page
  211. ${If} $ReinstallPageCheck != 2
  212. SendMessage $R2 ${BM_SETCHECK} ${BST_CHECKED} 0
  213. ${Else}
  214. SendMessage $R3 ${BM_SETCHECK} ${BST_CHECKED} 0
  215. ${EndIf}
  216. ${NSD_SetFocus} $R2
  217. nsDialogs::Show
  218. FunctionEnd
  219. Function PageReinstallUpdateSelection
  220. ${NSD_GetState} $R2 $R1
  221. ${If} $R1 == ${BST_CHECKED}
  222. StrCpy $ReinstallPageCheck 1
  223. ${Else}
  224. StrCpy $ReinstallPageCheck 2
  225. ${EndIf}
  226. FunctionEnd
  227. Function PageLeaveReinstall
  228. ${NSD_GetState} $R2 $R1
  229. ; $R5 holds whether we are reinstalling the same version or not
  230. ; $R5 == "1" -> different versions
  231. ; $R5 == "2" -> same version
  232. ;
  233. ; $R1 holds the radio buttons state. its meaning is dependant on the context
  234. StrCmp $R5 "1" 0 +2 ; Existing install is not the same version?
  235. StrCmp $R1 "1" reinst_uninstall reinst_done ; $R1 == "1", then user chose to uninstall existing version, otherwise skip uninstalling
  236. StrCmp $R1 "1" reinst_done ; Same version? skip uninstalling
  237. reinst_uninstall:
  238. HideWindow
  239. ClearErrors
  240. ${If} $R7 == "wix"
  241. ReadRegStr $R1 HKLM "$R6" "UninstallString"
  242. ExecWait '$R1' $0
  243. ${Else}
  244. ReadRegStr $4 SHCTX "${MANUPRODUCTKEY}" ""
  245. ReadRegStr $R1 SHCTX "${UNINSTKEY}" "UninstallString"
  246. ExecWait '$R1 /P _?=$4' $0
  247. ${EndIf}
  248. BringToFront
  249. ${IfThen} ${Errors} ${|} StrCpy $0 2 ${|} ; ExecWait failed, set fake exit code
  250. ${If} $0 <> 0
  251. ${OrIf} ${FileExists} "$INSTDIR\${MAINBINARYNAME}.exe"
  252. ${If} $0 = 1 ; User aborted uninstaller?
  253. StrCmp $R5 "2" 0 +2 ; Is the existing install the same version?
  254. Quit ; ...yes, already installed, we are done
  255. Abort
  256. ${EndIf}
  257. MessageBox MB_ICONEXCLAMATION "$(unableToUninstall)"
  258. Abort
  259. ${Else}
  260. StrCpy $0 $R1 1
  261. ${IfThen} $0 == '"' ${|} StrCpy $R1 $R1 -1 1 ${|} ; Strip quotes from UninstallString
  262. Delete $R1
  263. RMDir $INSTDIR
  264. ${EndIf}
  265. reinst_done:
  266. FunctionEnd
  267. ; 5. Choose install directoy page
  268. !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive
  269. !insertmacro MUI_PAGE_DIRECTORY
  270. ; 6. Start menu shortcut page
  271. !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive
  272. Var AppStartMenuFolder
  273. !insertmacro MUI_PAGE_STARTMENU Application $AppStartMenuFolder
  274. ; 7. Installation page
  275. !insertmacro MUI_PAGE_INSTFILES
  276. ; 8. Finish page
  277. ;
  278. ; Don't auto jump to finish page after installation page,
  279. ; because the installation page has useful info that can be used debug any issues with the installer.
  280. !define MUI_FINISHPAGE_NOAUTOCLOSE
  281. ; Use show readme button in the finish page as a button create a desktop shortcut
  282. !define MUI_FINISHPAGE_SHOWREADME
  283. !define MUI_FINISHPAGE_SHOWREADME_TEXT "$(createDesktop)"
  284. !define MUI_FINISHPAGE_SHOWREADME_FUNCTION CreateDesktopShortcut
  285. ; Show run app after installation.
  286. !define MUI_FINISHPAGE_RUN "$INSTDIR\${MAINBINARYNAME}.exe"
  287. !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive
  288. !insertmacro MUI_PAGE_FINISH
  289. ; Uninstaller Pages
  290. ; 1. Confirm uninstall page
  291. Var DeleteAppDataCheckbox
  292. Var DeleteAppDataCheckboxState
  293. !define /ifndef WS_EX_LAYOUTRTL 0x00400000
  294. !define MUI_PAGE_CUSTOMFUNCTION_SHOW un.ConfirmShow
  295. Function un.ConfirmShow
  296. FindWindow $1 "#32770" "" $HWNDPARENT ; Find inner dialog
  297. ${If} $(^RTL) == 1
  298. System::Call 'USER32::CreateWindowEx(i${__NSD_CheckBox_EXSTYLE}|${WS_EX_LAYOUTRTL},t"${__NSD_CheckBox_CLASS}",t "$(deleteAppData)",i${__NSD_CheckBox_STYLE},i 50,i 100,i 400, i 25,i$1,i0,i0,i0)i.s'
  299. ${Else}
  300. System::Call 'USER32::CreateWindowEx(i${__NSD_CheckBox_EXSTYLE},t"${__NSD_CheckBox_CLASS}",t "$(deleteAppData)",i${__NSD_CheckBox_STYLE},i 0,i 100,i 400, i 25,i$1,i0,i0,i0)i.s'
  301. ${EndIf}
  302. Pop $DeleteAppDataCheckbox
  303. SendMessage $HWNDPARENT ${WM_GETFONT} 0 0 $1
  304. SendMessage $DeleteAppDataCheckbox ${WM_SETFONT} $1 1
  305. FunctionEnd
  306. !define MUI_PAGE_CUSTOMFUNCTION_LEAVE un.ConfirmLeave
  307. Function un.ConfirmLeave
  308. SendMessage $DeleteAppDataCheckbox ${BM_GETCHECK} 0 0 $DeleteAppDataCheckboxState
  309. FunctionEnd
  310. !insertmacro MUI_UNPAGE_CONFIRM
  311. ; 2. Uninstalling Page
  312. !insertmacro MUI_UNPAGE_INSTFILES
  313. ;Languages
  314. {{#each languages}}
  315. !insertmacro MUI_LANGUAGE "{{this}}"
  316. {{/each}}
  317. !insertmacro MUI_RESERVEFILE_LANGDLL
  318. {{#each language_files}}
  319. !include "{{this}}"
  320. {{/each}}
  321. !macro SetContext
  322. !if "${INSTALLMODE}" == "currentUser"
  323. SetShellVarContext current
  324. !else if "${INSTALLMODE}" == "perMachine"
  325. SetShellVarContext all
  326. !endif
  327. ${If} ${RunningX64}
  328. !if "${ARCH}" == "x64"
  329. SetRegView 64
  330. !else if "${ARCH}" == "arm64"
  331. SetRegView 64
  332. !else
  333. SetRegView 32
  334. !endif
  335. ${EndIf}
  336. !macroend
  337. Var PassiveMode
  338. Function .onInit
  339. ${GetOptions} $CMDLINE "/P" $PassiveMode
  340. IfErrors +2 0
  341. StrCpy $PassiveMode 1
  342. !if "${DISPLAYLANGUAGESELECTOR}" == "true"
  343. !insertmacro MUI_LANGDLL_DISPLAY
  344. !endif
  345. !insertmacro SetContext
  346. ${If} $INSTDIR == ""
  347. ; Set default install location
  348. !if "${INSTALLMODE}" == "perMachine"
  349. ${If} ${RunningX64}
  350. !if "${ARCH}" == "x64"
  351. StrCpy $INSTDIR "$PROGRAMFILES64\${PRODUCTNAME}"
  352. !else if "${ARCH}" == "arm64"
  353. StrCpy $INSTDIR "$PROGRAMFILES64\${PRODUCTNAME}"
  354. !else
  355. StrCpy $INSTDIR "$PROGRAMFILES\${PRODUCTNAME}"
  356. !endif
  357. ${Else}
  358. StrCpy $INSTDIR "$PROGRAMFILES\${PRODUCTNAME}"
  359. ${EndIf}
  360. !else if "${INSTALLMODE}" == "currentUser"
  361. StrCpy $INSTDIR "$LOCALAPPDATA\${PRODUCTNAME}"
  362. !endif
  363. Call RestorePreviousInstallLocation
  364. ${EndIf}
  365. !if "${INSTALLMODE}" == "both"
  366. !insertmacro MULTIUSER_INIT
  367. !endif
  368. FunctionEnd
  369. !macro CheckAllVergeProcesses
  370. ; Check if Clash Verge.exe is running
  371. nsis_tauri_utils::FindProcess "Clash Verge.exe"
  372. ${If} $R0 != 0
  373. ; Kill the process
  374. DetailPrint "Kill Clash Verge.exe..."
  375. !if "${INSTALLMODE}" == "currentUser"
  376. nsis_tauri_utils::KillProcessCurrentUser "Clash Verge.exe"
  377. !else
  378. nsis_tauri_utils::KillProcess "Clash Verge.exe"
  379. !endif
  380. ${EndIf}
  381. ; Check if clash-verge-service.exe is running
  382. nsis_tauri_utils::FindProcess "clash-verge-service.exe"
  383. ${If} $R0 != 0
  384. ; Kill the process
  385. DetailPrint "Kill clash-verge-service.exe..."
  386. !if "${INSTALLMODE}" == "currentUser"
  387. nsis_tauri_utils::KillProcessCurrentUser "clash-verge-service.exe"
  388. !else
  389. nsis_tauri_utils::KillProcess "clash-verge-service.exe"
  390. !endif
  391. ${EndIf}
  392. ; Check if clash-meta-alpha.exe is running
  393. nsis_tauri_utils::FindProcess "clash-meta-alpha.exe"
  394. ${If} $R0 != 0
  395. ; Kill the process
  396. DetailPrint "Kill clash-meta-alpha.exe..."
  397. !if "${INSTALLMODE}" == "currentUser"
  398. nsis_tauri_utils::KillProcessCurrentUser "clash-meta-alpha.exe"
  399. !else
  400. nsis_tauri_utils::KillProcess "clash-meta-alpha.exe"
  401. !endif
  402. ${EndIf}
  403. ; Check if clash-meta.exe is running
  404. nsis_tauri_utils::FindProcess "clash-meta.exe"
  405. ${If} $R0 != 0
  406. ; Kill the process
  407. DetailPrint "Kill clash-meta.exe..."
  408. !if "${INSTALLMODE}" == "currentUser"
  409. nsis_tauri_utils::KillProcessCurrentUser "clash-meta.exe"
  410. !else
  411. nsis_tauri_utils::KillProcess "clash-meta.exe"
  412. !endif
  413. ${EndIf}
  414. !macroend
  415. !macro StartVergeService
  416. ; Check if the service exists
  417. SimpleSC::ExistsService "clash_verge_service"
  418. Pop $0 ; 0:service exists;other: service not exists
  419. ; Service exists
  420. ${If} $0 == 0
  421. Push $0
  422. ; Check if the service is running
  423. SimpleSC::ServiceIsRunning "clash_verge_service"
  424. Pop $0 ; returns an errorcode (<>0) otherwise success (0)
  425. Pop $1 ; returns 1 (service is running) - returns 0 (service is not running)
  426. ${If} $0 == 0
  427. Push $0
  428. ${If} $1 == 0
  429. DetailPrint "Restart Clash Verge Service..."
  430. SimpleSC::StartService "clash_verge_service" "" 30
  431. ${EndIf}
  432. ${ElseIf} $0 != 0
  433. Push $0
  434. SimpleSC::GetErrorMessage
  435. Pop $0
  436. MessageBox MB_OK|MB_ICONSTOP "Check Service Status Error ($0)"
  437. ${EndIf}
  438. ${EndIf}
  439. !macroend
  440. !macro RemoveVergeService
  441. ; Check if the service exists
  442. SimpleSC::ExistsService "clash_verge_service"
  443. Pop $0 ; 0:service exists;other: service not exists
  444. ; Service exists
  445. ${If} $0 == 0
  446. Push $0
  447. ; Check if the service is running
  448. SimpleSC::ServiceIsRunning "clash_verge_service"
  449. Pop $0 ; returns an errorcode (<>0) otherwise success (0)
  450. Pop $1 ; returns 1 (service is running) - returns 0 (service is not running)
  451. ${If} $0 == 0
  452. Push $0
  453. ${If} $1 == 1
  454. DetailPrint "Stop Clash Verge Service..."
  455. SimpleSC::StopService "clash_verge_service" 1 30
  456. Pop $0 ; returns an errorcode (<>0) otherwise success (0)
  457. ${If} $0 == 0
  458. DetailPrint "Removing Clash Verge Service..."
  459. SimpleSC::RemoveService "clash_verge_service"
  460. ${ElseIf} $0 != 0
  461. Push $0
  462. SimpleSC::GetErrorMessage
  463. Pop $0
  464. MessageBox MB_OK|MB_ICONSTOP "Clash Verge Service Stop Error ($0)"
  465. ${EndIf}
  466. ${ElseIf} $1 == 0
  467. DetailPrint "Removing Clash Verge Service..."
  468. SimpleSC::RemoveService "clash_verge_service"
  469. ${EndIf}
  470. ${ElseIf} $0 != 0
  471. Push $0
  472. SimpleSC::GetErrorMessage
  473. Pop $0
  474. MessageBox MB_OK|MB_ICONSTOP "Check Service Status Error ($0)"
  475. ${EndIf}
  476. ${EndIf}
  477. !macroend
  478. Section EarlyChecks
  479. ; Abort silent installer if downgrades is disabled
  480. !if "${ALLOWDOWNGRADES}" == "false"
  481. IfSilent 0 silent_downgrades_done
  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. silent_downgrades_done:
  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\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv"
  499. ${Else}
  500. ReadRegStr $4 HKLM "SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv"
  501. ${EndIf}
  502. ReadRegStr $5 HKCU "SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv"
  503. StrCmp $4 "" 0 webview2_done
  504. StrCmp $5 "" 0 webview2_done
  505. ; Webview2 install modes
  506. !if "${INSTALLWEBVIEW2MODE}" == "downloadBootstrapper"
  507. Delete "$TEMP\MicrosoftEdgeWebview2Setup.exe"
  508. DetailPrint "$(webview2Downloading)"
  509. nsis_tauri_utils::download "https://go.microsoft.com/fwlink/p/?LinkId=2124703" "$TEMP\MicrosoftEdgeWebview2Setup.exe"
  510. Pop $0
  511. ${If} $0 == 0
  512. DetailPrint "$(webview2DownloadSuccess)"
  513. ${Else}
  514. DetailPrint "$(webview2DownloadError)"
  515. Abort "$(webview2AbortError)"
  516. ${EndIf}
  517. StrCpy $6 "$TEMP\MicrosoftEdgeWebview2Setup.exe"
  518. Goto install_webview2
  519. !endif
  520. !if "${INSTALLWEBVIEW2MODE}" == "embedBootstrapper"
  521. Delete "$TEMP\MicrosoftEdgeWebview2Setup.exe"
  522. File "/oname=$TEMP\MicrosoftEdgeWebview2Setup.exe" "${WEBVIEW2BOOTSTRAPPERPATH}"
  523. DetailPrint "$(installingWebview2)"
  524. StrCpy $6 "$TEMP\MicrosoftEdgeWebview2Setup.exe"
  525. Goto install_webview2
  526. !endif
  527. !if "${INSTALLWEBVIEW2MODE}" == "offlineInstaller"
  528. Delete "$TEMP\MicrosoftEdgeWebView2RuntimeInstaller.exe"
  529. File "/oname=$TEMP\MicrosoftEdgeWebView2RuntimeInstaller.exe" "${WEBVIEW2INSTALLERPATH}"
  530. DetailPrint "$(installingWebview2)"
  531. StrCpy $6 "$TEMP\MicrosoftEdgeWebView2RuntimeInstaller.exe"
  532. Goto install_webview2
  533. !endif
  534. Goto webview2_done
  535. install_webview2:
  536. DetailPrint "$(installingWebview2)"
  537. ; $6 holds the path to the webview2 installer
  538. ExecWait "$6 ${WEBVIEW2INSTALLERARGS} /install" $1
  539. ${If} $1 == 0
  540. DetailPrint "$(webview2InstallSuccess)"
  541. ${Else}
  542. DetailPrint "$(webview2InstallError)"
  543. Abort "$(webview2AbortError)"
  544. ${EndIf}
  545. webview2_done:
  546. SectionEnd
  547. !macro CheckIfAppIsRunning
  548. !if "${INSTALLMODE}" == "currentUser"
  549. nsis_tauri_utils::FindProcessCurrentUser "${MAINBINARYNAME}.exe"
  550. !else
  551. nsis_tauri_utils::FindProcess "${MAINBINARYNAME}.exe"
  552. !endif
  553. Pop $R0
  554. ${If} $R0 = 0
  555. IfSilent kill 0
  556. ${IfThen} $PassiveMode != 1 ${|} MessageBox MB_OKCANCEL "$(appRunningOkKill)" IDOK kill IDCANCEL cancel ${|}
  557. kill:
  558. !if "${INSTALLMODE}" == "currentUser"
  559. nsis_tauri_utils::KillProcessCurrentUser "${MAINBINARYNAME}.exe"
  560. !else
  561. nsis_tauri_utils::KillProcess "${MAINBINARYNAME}.exe"
  562. !endif
  563. Pop $R0
  564. Sleep 500
  565. ${If} $R0 = 0
  566. Goto app_check_done
  567. ${Else}
  568. IfSilent silent ui
  569. silent:
  570. System::Call 'kernel32::AttachConsole(i -1)i.r0'
  571. ${If} $0 != 0
  572. System::Call 'kernel32::GetStdHandle(i -11)i.r0'
  573. System::call 'kernel32::SetConsoleTextAttribute(i r0, i 0x0004)' ; set red color
  574. FileWrite $0 "$(appRunning)$\n"
  575. ${EndIf}
  576. Abort
  577. ui:
  578. Abort "$(failedToKillApp)"
  579. ${EndIf}
  580. cancel:
  581. Abort "$(appRunning)"
  582. ${EndIf}
  583. app_check_done:
  584. !macroend
  585. Section Install
  586. SetOutPath $INSTDIR
  587. !insertmacro CheckIfAppIsRunning
  588. !insertmacro CheckAllVergeProcesses
  589. ; Copy main executable
  590. File "${MAINBINARYSRCPATH}"
  591. ; Copy resources
  592. {{#each resources_dirs}}
  593. CreateDirectory "$INSTDIR\\{{this}}"
  594. {{/each}}
  595. {{#each resources}}
  596. File /a "/oname={{this.[1]}}" "{{@key}}"
  597. {{/each}}
  598. ; Copy external binaries
  599. {{#each binaries}}
  600. File /a "/oname={{this}}" "{{@key}}"
  601. {{/each}}
  602. !insertmacro StartVergeService
  603. ; Create uninstaller
  604. WriteUninstaller "$INSTDIR\uninstall.exe"
  605. ; Save $INSTDIR in registry for future installations
  606. WriteRegStr SHCTX "${MANUPRODUCTKEY}" "" $INSTDIR
  607. !if "${INSTALLMODE}" == "both"
  608. ; Save install mode to be selected by default for the next installation such as updating
  609. ; or when uninstalling
  610. WriteRegStr SHCTX "${UNINSTKEY}" $MultiUser.InstallMode 1
  611. !endif
  612. ; Registry information for add/remove programs
  613. WriteRegStr SHCTX "${UNINSTKEY}" "DisplayName" "${PRODUCTNAME}"
  614. WriteRegStr SHCTX "${UNINSTKEY}" "DisplayIcon" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\""
  615. WriteRegStr SHCTX "${UNINSTKEY}" "DisplayVersion" "${VERSION}"
  616. WriteRegStr SHCTX "${UNINSTKEY}" "Publisher" "${MANUFACTURER}"
  617. WriteRegStr SHCTX "${UNINSTKEY}" "InstallLocation" "$\"$INSTDIR$\""
  618. WriteRegStr SHCTX "${UNINSTKEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\""
  619. WriteRegDWORD SHCTX "${UNINSTKEY}" "NoModify" "1"
  620. WriteRegDWORD SHCTX "${UNINSTKEY}" "NoRepair" "1"
  621. WriteRegDWORD SHCTX "${UNINSTKEY}" "EstimatedSize" "${ESTIMATEDSIZE}"
  622. ; Create start menu shortcut (GUI)
  623. !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
  624. Call CreateStartMenuShortcut
  625. !insertmacro MUI_STARTMENU_WRITE_END
  626. ; Create shortcuts for silent and passive installers, which
  627. ; can be disabled by passing `/NS` flag
  628. ; GUI installer has buttons for users to control creating them
  629. IfSilent check_ns_flag 0
  630. ${IfThen} $PassiveMode == 1 ${|} Goto check_ns_flag ${|}
  631. Goto shortcuts_done
  632. check_ns_flag:
  633. ${GetOptions} $CMDLINE "/NS" $R0
  634. IfErrors 0 shortcuts_done
  635. Call CreateDesktopShortcut
  636. Call CreateStartMenuShortcut
  637. shortcuts_done:
  638. ; Auto close this page for passive mode
  639. ${IfThen} $PassiveMode == 1 ${|} SetAutoClose true ${|}
  640. SectionEnd
  641. Function .onInstSuccess
  642. ; Check for `/R` flag only in silent and passive installers because
  643. ; GUI installer has a toggle for the user to (re)start the app
  644. IfSilent check_r_flag 0
  645. ${IfThen} $PassiveMode == 1 ${|} Goto check_r_flag ${|}
  646. Goto run_done
  647. check_r_flag:
  648. ${GetOptions} $CMDLINE "/R" $R0
  649. IfErrors run_done 0
  650. Exec '"$INSTDIR\${MAINBINARYNAME}.exe"'
  651. run_done:
  652. FunctionEnd
  653. Function un.onInit
  654. !insertmacro SetContext
  655. !if "${INSTALLMODE}" == "both"
  656. !insertmacro MULTIUSER_UNINIT
  657. !endif
  658. !insertmacro MUI_UNGETLANGUAGE
  659. FunctionEnd
  660. Section Uninstall
  661. !insertmacro CheckIfAppIsRunning
  662. !insertmacro CheckAllVergeProcesses
  663. !insertmacro RemoveVergeService
  664. ; Delete the app directory and its content from disk
  665. ; Copy main executable
  666. Delete "$INSTDIR\${MAINBINARYNAME}.exe"
  667. ; Delete resources
  668. {{#each resources}}
  669. Delete "$INSTDIR\\{{this.[1]}}"
  670. {{/each}}
  671. ; Delete external binaries
  672. {{#each binaries}}
  673. Delete "$INSTDIR\\{{this}}"
  674. {{/each}}
  675. ; Delete uninstaller
  676. Delete "$INSTDIR\uninstall.exe"
  677. ${If} $DeleteAppDataCheckboxState == 1
  678. RMDir /R /REBOOTOK "$INSTDIR"
  679. ${Else}
  680. {{#each resources_ancestors}}
  681. RMDir /REBOOTOK "$INSTDIR\\{{this}}"
  682. {{/each}}
  683. RMDir "$INSTDIR"
  684. ${EndIf}
  685. ; Remove start menu shortcut
  686. !insertmacro MUI_STARTMENU_GETFOLDER Application $AppStartMenuFolder
  687. Delete "$SMPROGRAMS\$AppStartMenuFolder\${MAINBINARYNAME}.lnk"
  688. RMDir "$SMPROGRAMS\$AppStartMenuFolder"
  689. ; Remove desktop shortcuts
  690. Delete "$DESKTOP\${MAINBINARYNAME}.lnk"
  691. ; Remove registry information for add/remove programs
  692. !if "${INSTALLMODE}" == "both"
  693. DeleteRegKey SHCTX "${UNINSTKEY}"
  694. !else if "${INSTALLMODE}" == "perMachine"
  695. DeleteRegKey HKLM "${UNINSTKEY}"
  696. !else
  697. DeleteRegKey HKCU "${UNINSTKEY}"
  698. !endif
  699. DeleteRegValue HKCU "${MANUPRODUCTKEY}" "Installer Language"
  700. ; Delete app data
  701. ${If} $DeleteAppDataCheckboxState == 1
  702. SetShellVarContext current
  703. RmDir /r "$APPDATA\${BUNDLEID}"
  704. RmDir /r "$LOCALAPPDATA\${BUNDLEID}"
  705. ${EndIf}
  706. ${GetOptions} $CMDLINE "/P" $R0
  707. IfErrors +2 0
  708. SetAutoClose true
  709. SectionEnd
  710. Function RestorePreviousInstallLocation
  711. ReadRegStr $4 SHCTX "${MANUPRODUCTKEY}" ""
  712. StrCmp $4 "" +2 0
  713. StrCpy $INSTDIR $4
  714. FunctionEnd
  715. Function SkipIfPassive
  716. ${IfThen} $PassiveMode == 1 ${|} Abort ${|}
  717. FunctionEnd
  718. Function CreateDesktopShortcut
  719. CreateShortcut "$DESKTOP\${MAINBINARYNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
  720. ApplicationID::Set "$DESKTOP\${MAINBINARYNAME}.lnk" "${BUNDLEID}"
  721. FunctionEnd
  722. Function CreateStartMenuShortcut
  723. CreateDirectory "$SMPROGRAMS\$AppStartMenuFolder"
  724. CreateShortcut "$SMPROGRAMS\$AppStartMenuFolder\${MAINBINARYNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
  725. ApplicationID::Set "$SMPROGRAMS\$AppStartMenuFolder\${MAINBINARYNAME}.lnk" "${BUNDLEID}"
  726. FunctionEnd