123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918 |
- ; This file is copied from https://github.com/tauri-apps/tauri/blob/tauri-v1.5/tooling/bundler/src/bundle/windows/templates/installer.nsi
- ; and edit to fit the needs of the project. the latest tauri 2.x has a different base nsi script.
- Unicode true
- ; Set the compression algorithm. Default is LZMA.
- !if "{{compression}}" == ""
- SetCompressor /SOLID lzma
- !else
- SetCompressor /SOLID "{{compression}}"
- !endif
- !include MUI2.nsh
- !include FileFunc.nsh
- !include x64.nsh
- !include WordFunc.nsh
- !include "StrFunc.nsh"
- !include "Win\COM.nsh"
- !include "Win\Propkey.nsh"
- !addplugindir "$%AppData%\Local\NSIS\"
- ${StrCase}
- ${StrLoc}
- !define MANUFACTURER "{{manufacturer}}"
- !define PRODUCTNAME "{{product_name}}"
- !define VERSION "{{version}}"
- !define VERSIONWITHBUILD "{{version_with_build}}"
- !define SHORTDESCRIPTION "{{short_description}}"
- !define INSTALLMODE "{{install_mode}}"
- !define LICENSE "{{license}}"
- !define INSTALLERICON "{{installer_icon}}"
- !define SIDEBARIMAGE "{{sidebar_image}}"
- !define HEADERIMAGE "{{header_image}}"
- !define MAINBINARYNAME "{{main_binary_name}}"
- !define MAINBINARYSRCPATH "{{main_binary_path}}"
- !define BUNDLEID "{{bundle_id}}"
- !define COPYRIGHT "{{copyright}}"
- !define OUTFILE "{{out_file}}"
- !define ARCH "{{arch}}"
- !define PLUGINSPATH "{{additional_plugins_path}}"
- !define ALLOWDOWNGRADES "{{allow_downgrades}}"
- !define DISPLAYLANGUAGESELECTOR "{{display_language_selector}}"
- !define INSTALLWEBVIEW2MODE "{{install_webview2_mode}}"
- !define WEBVIEW2INSTALLERARGS "{{webview2_installer_args}}"
- !define WEBVIEW2BOOTSTRAPPERPATH "{{webview2_bootstrapper_path}}"
- !define WEBVIEW2INSTALLERPATH "{{webview2_installer_path}}"
- !define UNINSTKEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCTNAME}"
- !define MANUPRODUCTKEY "Software\${MANUFACTURER}\${PRODUCTNAME}"
- !define UNINSTALLERSIGNCOMMAND "{{uninstaller_sign_cmd}}"
- !define ESTIMATEDSIZE "{{estimated_size}}"
- Name "${PRODUCTNAME}"
- BrandingText "${COPYRIGHT}"
- OutFile "${OUTFILE}"
- VIProductVersion "${VERSIONWITHBUILD}"
- VIAddVersionKey "ProductName" "${PRODUCTNAME}"
- VIAddVersionKey "FileDescription" "${SHORTDESCRIPTION}"
- VIAddVersionKey "LegalCopyright" "${COPYRIGHT}"
- VIAddVersionKey "FileVersion" "${VERSION}"
- VIAddVersionKey "ProductVersion" "${VERSION}"
- ; Plugins path, currently exists for linux only
- !if "${PLUGINSPATH}" != ""
- !addplugindir "${PLUGINSPATH}"
- !endif
- !if "${UNINSTALLERSIGNCOMMAND}" != ""
- !uninstfinalize '${UNINSTALLERSIGNCOMMAND}'
- !endif
- ; Handle install mode, `perUser`, `perMachine` or `both`
- !if "${INSTALLMODE}" == "perMachine"
- RequestExecutionLevel highest
- !endif
- !if "${INSTALLMODE}" == "currentUser"
- RequestExecutionLevel user
- !endif
- !if "${INSTALLMODE}" == "both"
- !define MULTIUSER_MUI
- !define MULTIUSER_INSTALLMODE_INSTDIR "${PRODUCTNAME}"
- !define MULTIUSER_INSTALLMODE_COMMANDLINE
- !if "${ARCH}" == "x64"
- !define MULTIUSER_USE_PROGRAMFILES64
- !else if "${ARCH}" == "arm64"
- !define MULTIUSER_USE_PROGRAMFILES64
- !endif
- !define MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY "${UNINSTKEY}"
- !define MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME "CurrentUser"
- !define MULTIUSER_INSTALLMODEPAGE_SHOWUSERNAME
- !define MULTIUSER_INSTALLMODE_FUNCTION RestorePreviousInstallLocation
- !define MULTIUSER_EXECUTIONLEVEL Highest
- !include MultiUser.nsh
- !endif
- ; installer icon
- !if "${INSTALLERICON}" != ""
- !define MUI_ICON "${INSTALLERICON}"
- !endif
- ; installer sidebar image
- !if "${SIDEBARIMAGE}" != ""
- !define MUI_WELCOMEFINISHPAGE_BITMAP "${SIDEBARIMAGE}"
- !endif
- ; installer header image
- !if "${HEADERIMAGE}" != ""
- !define MUI_HEADERIMAGE
- !define MUI_HEADERIMAGE_BITMAP "${HEADERIMAGE}"
- !endif
- ; Define registry key to store installer language
- !define MUI_LANGDLL_REGISTRY_ROOT "HKCU"
- !define MUI_LANGDLL_REGISTRY_KEY "${MANUPRODUCTKEY}"
- !define MUI_LANGDLL_REGISTRY_VALUENAME "Installer Language"
- ; Installer pages, must be ordered as they appear
- ; 1. Welcome Page
- !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive
- !insertmacro MUI_PAGE_WELCOME
- ; 2. License Page (if defined)
- !if "${LICENSE}" != ""
- !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive
- !insertmacro MUI_PAGE_LICENSE "${LICENSE}"
- !endif
- ; 3. Install mode (if it is set to `both`)
- !if "${INSTALLMODE}" == "both"
- !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive
- !insertmacro MULTIUSER_PAGE_INSTALLMODE
- !endif
- ; 4. Custom page to ask user if he wants to reinstall/uninstall
- ; only if a previous installtion was detected
- Var ReinstallPageCheck
- Page custom PageReinstall PageLeaveReinstall
- Function PageReinstall
- ; Uninstall previous WiX installation if exists.
- ;
- ; A WiX installer stores the isntallation info in registry
- ; using a UUID and so we have to loop through all keys under
- ; `HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall`
- ; and check if `DisplayName` and `Publisher` keys match ${PRODUCTNAME} and ${MANUFACTURER}
- ;
- ; This has a potentional issue that there maybe another installation that matches
- ; our ${PRODUCTNAME} and ${MANUFACTURER} but wasn't installed by our WiX installer,
- ; however, this should be fine since the user will have to confirm the uninstallation
- ; and they can chose to abort it if doesn't make sense.
- StrCpy $0 0
- wix_loop:
- EnumRegKey $1 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" $0
- StrCmp $1 "" wix_done ; Exit loop if there is no more keys to loop on
- IntOp $0 $0 + 1
- ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$1" "DisplayName"
- ReadRegStr $R1 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$1" "Publisher"
- StrCmp "$R0$R1" "${PRODUCTNAME}${MANUFACTURER}" 0 wix_loop
- ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$1" "UninstallString"
- ${StrCase} $R1 $R0 "L"
- ${StrLoc} $R0 $R1 "msiexec" ">"
- StrCmp $R0 0 0 wix_done
- StrCpy $R7 "wix"
- StrCpy $R6 "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$1"
- Goto compare_version
- wix_done:
- ; Check if there is an existing installation, if not, abort the reinstall page
- ReadRegStr $R0 SHCTX "${UNINSTKEY}" ""
- ReadRegStr $R1 SHCTX "${UNINSTKEY}" "UninstallString"
- ${IfThen} "$R0$R1" == "" ${|} Abort ${|}
- ; Compare this installar version with the existing installation
- ; and modify the messages presented to the user accordingly
- compare_version:
- StrCpy $R4 "$(older)"
- ${If} $R7 == "wix"
- ReadRegStr $R0 HKLM "$R6" "DisplayVersion"
- ${Else}
- ReadRegStr $R0 SHCTX "${UNINSTKEY}" "DisplayVersion"
- ${EndIf}
- ${IfThen} $R0 == "" ${|} StrCpy $R4 "$(unknown)" ${|}
- nsis_tauri_utils::SemverCompare "${VERSION}" $R0
- Pop $R0
- ; Reinstalling the same version
- ${If} $R0 == 0
- StrCpy $R1 "$(alreadyInstalledLong)"
- StrCpy $R2 "$(addOrReinstall)"
- StrCpy $R3 "$(uninstallApp)"
- !insertmacro MUI_HEADER_TEXT "$(alreadyInstalled)" "$(chooseMaintenanceOption)"
- StrCpy $R5 "2"
- ; Upgrading
- ${ElseIf} $R0 == 1
- StrCpy $R1 "$(olderOrUnknownVersionInstalled)"
- StrCpy $R2 "$(uninstallBeforeInstalling)"
- StrCpy $R3 "$(dontUninstall)"
- !insertmacro MUI_HEADER_TEXT "$(alreadyInstalled)" "$(choowHowToInstall)"
- StrCpy $R5 "1"
- ; Downgrading
- ${ElseIf} $R0 == -1
- StrCpy $R1 "$(newerVersionInstalled)"
- StrCpy $R2 "$(uninstallBeforeInstalling)"
- !if "${ALLOWDOWNGRADES}" == "true"
- StrCpy $R3 "$(dontUninstall)"
- !else
- StrCpy $R3 "$(dontUninstallDowngrade)"
- !endif
- !insertmacro MUI_HEADER_TEXT "$(alreadyInstalled)" "$(choowHowToInstall)"
- StrCpy $R5 "1"
- ${Else}
- Abort
- ${EndIf}
- Call SkipIfPassive
- nsDialogs::Create 1018
- Pop $R4
- ${IfThen} $(^RTL) == 1 ${|} nsDialogs::SetRTL $(^RTL) ${|}
- ${NSD_CreateLabel} 0 0 100% 24u $R1
- Pop $R1
- ${NSD_CreateRadioButton} 30u 50u -30u 8u $R2
- Pop $R2
- ${NSD_OnClick} $R2 PageReinstallUpdateSelection
- ${NSD_CreateRadioButton} 30u 70u -30u 8u $R3
- Pop $R3
- ; disable this radio button if downgrading and downgrades are disabled
- !if "${ALLOWDOWNGRADES}" == "false"
- ${IfThen} $R0 == -1 ${|} EnableWindow $R3 0 ${|}
- !endif
- ${NSD_OnClick} $R3 PageReinstallUpdateSelection
- ; Check the first radio button if this the first time
- ; we enter this page or if the second button wasn't
- ; selected the last time we were on this page
- ${If} $ReinstallPageCheck != 2
- SendMessage $R2 ${BM_SETCHECK} ${BST_CHECKED} 0
- ${Else}
- SendMessage $R3 ${BM_SETCHECK} ${BST_CHECKED} 0
- ${EndIf}
- ${NSD_SetFocus} $R2
- nsDialogs::Show
- FunctionEnd
- Function PageReinstallUpdateSelection
- ${NSD_GetState} $R2 $R1
- ${If} $R1 == ${BST_CHECKED}
- StrCpy $ReinstallPageCheck 1
- ${Else}
- StrCpy $ReinstallPageCheck 2
- ${EndIf}
- FunctionEnd
- Function PageLeaveReinstall
- ${NSD_GetState} $R2 $R1
- ; $R5 holds whether we are reinstalling the same version or not
- ; $R5 == "1" -> different versions
- ; $R5 == "2" -> same version
- ;
- ; $R1 holds the radio buttons state. its meaning is dependant on the context
- StrCmp $R5 "1" 0 +2 ; Existing install is not the same version?
- StrCmp $R1 "1" reinst_uninstall reinst_done ; $R1 == "1", then user chose to uninstall existing version, otherwise skip uninstalling
- StrCmp $R1 "1" reinst_done ; Same version? skip uninstalling
- reinst_uninstall:
- HideWindow
- ClearErrors
- ${If} $R7 == "wix"
- ReadRegStr $R1 HKLM "$R6" "UninstallString"
- ExecWait '$R1' $0
- ${Else}
- ReadRegStr $4 SHCTX "${MANUPRODUCTKEY}" ""
- ReadRegStr $R1 SHCTX "${UNINSTKEY}" "UninstallString"
- ExecWait '$R1 /P _?=$4' $0
- ${EndIf}
- BringToFront
- ${IfThen} ${Errors} ${|} StrCpy $0 2 ${|} ; ExecWait failed, set fake exit code
- ${If} $0 <> 0
- ${OrIf} ${FileExists} "$INSTDIR\${MAINBINARYNAME}.exe"
- ${If} $0 = 1 ; User aborted uninstaller?
- StrCmp $R5 "2" 0 +2 ; Is the existing install the same version?
- Quit ; ...yes, already installed, we are done
- Abort
- ${EndIf}
- MessageBox MB_ICONEXCLAMATION "$(unableToUninstall)"
- Abort
- ${Else}
- StrCpy $0 $R1 1
- ${IfThen} $0 == '"' ${|} StrCpy $R1 $R1 -1 1 ${|} ; Strip quotes from UninstallString
- Delete $R1
- RMDir $INSTDIR
- ${EndIf}
- reinst_done:
- FunctionEnd
- ; 5. Choose install directoy page
- !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive
- !insertmacro MUI_PAGE_DIRECTORY
- ; 6. Start menu shortcut page
- !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive
- Var AppStartMenuFolder
- !insertmacro MUI_PAGE_STARTMENU Application $AppStartMenuFolder
- ; 7. Installation page
- !insertmacro MUI_PAGE_INSTFILES
- ; 8. Finish page
- ;
- ; Don't auto jump to finish page after installation page,
- ; because the installation page has useful info that can be used debug any issues with the installer.
- !define MUI_FINISHPAGE_NOAUTOCLOSE
- ; Use show readme button in the finish page as a button create a desktop shortcut
- !define MUI_FINISHPAGE_SHOWREADME
- !define MUI_FINISHPAGE_SHOWREADME_TEXT "$(createDesktop)"
- !define MUI_FINISHPAGE_SHOWREADME_FUNCTION CreateDesktopShortcut
- ; Show run app after installation.
- !define MUI_FINISHPAGE_RUN
- !define MUI_FINISHPAGE_RUN_FUNCTION RunMainBinary
- !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive
- !insertmacro MUI_PAGE_FINISH
- Function RunMainBinary
- nsis_tauri_utils::RunAsUser "$INSTDIR\${MAINBINARYNAME}.exe" ""
- FunctionEnd
- ; Uninstaller Pages
- ; 1. Confirm uninstall page
- Var DeleteAppDataCheckbox
- Var DeleteAppDataCheckboxState
- !define /ifndef WS_EX_LAYOUTRTL 0x00400000
- !define MUI_PAGE_CUSTOMFUNCTION_SHOW un.ConfirmShow
- Function un.ConfirmShow
- FindWindow $1 "#32770" "" $HWNDPARENT ; Find inner dialog
- ${If} $(^RTL) == 1
- 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'
- ${Else}
- 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'
- ${EndIf}
- Pop $DeleteAppDataCheckbox
- SendMessage $HWNDPARENT ${WM_GETFONT} 0 0 $1
- SendMessage $DeleteAppDataCheckbox ${WM_SETFONT} $1 1
- FunctionEnd
- !define MUI_PAGE_CUSTOMFUNCTION_LEAVE un.ConfirmLeave
- Function un.ConfirmLeave
- SendMessage $DeleteAppDataCheckbox ${BM_GETCHECK} 0 0 $DeleteAppDataCheckboxState
- FunctionEnd
- !insertmacro MUI_UNPAGE_CONFIRM
- ; 2. Uninstalling Page
- !insertmacro MUI_UNPAGE_INSTFILES
- ;Languages
- {{#each languages}}
- !insertmacro MUI_LANGUAGE "{{this}}"
- {{/each}}
- !insertmacro MUI_RESERVEFILE_LANGDLL
- {{#each language_files}}
- !include "{{this}}"
- {{/each}}
- !macro SetContext
- !if "${INSTALLMODE}" == "currentUser"
- SetShellVarContext current
- !else if "${INSTALLMODE}" == "perMachine"
- SetShellVarContext all
- !endif
- ${If} ${RunningX64}
- !if "${ARCH}" == "x64"
- SetRegView 64
- !else if "${ARCH}" == "arm64"
- SetRegView 64
- !else
- SetRegView 32
- !endif
- ${EndIf}
- !macroend
- Var PassiveMode
- Function .onInit
- ${GetOptions} $CMDLINE "/P" $PassiveMode
- IfErrors +2 0
- StrCpy $PassiveMode 1
- !if "${DISPLAYLANGUAGESELECTOR}" == "true"
- !insertmacro MUI_LANGDLL_DISPLAY
- !endif
- !insertmacro SetContext
- ${If} $INSTDIR == ""
- ; Set default install location
- !if "${INSTALLMODE}" == "perMachine"
- ${If} ${RunningX64}
- !if "${ARCH}" == "x64"
- StrCpy $INSTDIR "$PROGRAMFILES64\${PRODUCTNAME}"
- !else if "${ARCH}" == "arm64"
- StrCpy $INSTDIR "$PROGRAMFILES64\${PRODUCTNAME}"
- !else
- StrCpy $INSTDIR "$PROGRAMFILES\${PRODUCTNAME}"
- !endif
- ${Else}
- StrCpy $INSTDIR "$PROGRAMFILES\${PRODUCTNAME}"
- ${EndIf}
- !else if "${INSTALLMODE}" == "currentUser"
- StrCpy $INSTDIR "$LOCALAPPDATA\${PRODUCTNAME}"
- !endif
- Call RestorePreviousInstallLocation
- ${EndIf}
- !if "${INSTALLMODE}" == "both"
- !insertmacro MULTIUSER_INIT
- !endif
- FunctionEnd
- !macro CheckAllVergeProcesses
- ; Check if clash-verge-service.exe is running
- !if "${INSTALLMODE}" == "currentUser"
- nsis_tauri_utils::FindProcessCurrentUser "clash-verge-service.exe"
- !else
- nsis_tauri_utils::FindProcess "clash-verge-service.exe"
- !endif
- Pop $R0
- ${If} $R0 = 0
- DetailPrint "Kill clash-verge-service.exe..."
- !if "${INSTALLMODE}" == "currentUser"
- nsis_tauri_utils::KillProcessCurrentUser "clash-verge-service.exe"
- !else
- nsis_tauri_utils::KillProcess "clash-verge-service.exe"
- !endif
- ${EndIf}
- ; Check if verge-mihomo-alpha.exe is running
- !if "${INSTALLMODE}" == "currentUser"
- nsis_tauri_utils::FindProcessCurrentUser "verge-mihomo-alpha.exe"
- !else
- nsis_tauri_utils::FindProcess "verge-mihomo-alpha.exe"
- !endif
- Pop $R0
- ${If} $R0 = 0
- DetailPrint "Kill verge-mihomo-alpha.exe..."
- !if "${INSTALLMODE}" == "currentUser"
- nsis_tauri_utils::KillProcessCurrentUser "verge-mihomo-alpha.exe"
- !else
- nsis_tauri_utils::KillProcess "verge-mihomo-alpha.exe"
- !endif
- ${EndIf}
- ; Check if verge-mihomo.exe is running
- !if "${INSTALLMODE}" == "currentUser"
- nsis_tauri_utils::FindProcessCurrentUser "verge-mihomo.exe"
- !else
- nsis_tauri_utils::FindProcess "verge-mihomo.exe"
- !endif
- Pop $R0
- ${If} $R0 = 0
- DetailPrint "Kill verge-mihomo.exe..."
- !if "${INSTALLMODE}" == "currentUser"
- nsis_tauri_utils::KillProcessCurrentUser "verge-mihomo.exe"
- !else
- nsis_tauri_utils::KillProcess "verge-mihomo.exe"
- !endif
- ${EndIf}
- ; Check if clash-meta-alpha.exe is running
- !if "${INSTALLMODE}" == "currentUser"
- nsis_tauri_utils::FindProcessCurrentUser "clash-meta-alpha.exe"
- !else
- nsis_tauri_utils::FindProcess "clash-meta-alpha.exe"
- !endif
- Pop $R0
- ${If} $R0 = 0
- DetailPrint "Kill clash-meta-alpha.exe..."
- !if "${INSTALLMODE}" == "currentUser"
- nsis_tauri_utils::KillProcessCurrentUser "clash-meta-alpha.exe"
- !else
- nsis_tauri_utils::KillProcess "clash-meta-alpha.exe"
- !endif
- ${EndIf}
- ; Check if clash-meta.exe is running
- !if "${INSTALLMODE}" == "currentUser"
- nsis_tauri_utils::FindProcessCurrentUser "clash-meta.exe"
- !else
- nsis_tauri_utils::FindProcess "clash-meta.exe"
- !endif
- Pop $R0
- ${If} $R0 = 0
- DetailPrint "Kill clash-meta.exe..."
- !if "${INSTALLMODE}" == "currentUser"
- nsis_tauri_utils::KillProcessCurrentUser "clash-meta.exe"
- !else
- nsis_tauri_utils::KillProcess "clash-meta.exe"
- !endif
- ${EndIf}
- !macroend
- !macro StartVergeService
- ; Check if the service exists
- SimpleSC::ExistsService "clash_verge_service"
- Pop $0 ; 0:service exists;other: service not exists
- ; Service exists
- ${If} $0 == 0
- Push $0
- ; Check if the service is running
- SimpleSC::ServiceIsRunning "clash_verge_service"
- Pop $0 ; returns an errorcode (<>0) otherwise success (0)
- Pop $1 ; returns 1 (service is running) - returns 0 (service is not running)
- ${If} $0 == 0
- Push $0
- ${If} $1 == 0
- DetailPrint "Restart Clash Verge Service..."
- SimpleSC::StartService "clash_verge_service" "" 30
- ${EndIf}
- ${ElseIf} $0 != 0
- Push $0
- SimpleSC::GetErrorMessage
- Pop $0
- MessageBox MB_OK|MB_ICONSTOP "Check Service Status Error ($0)"
- ${EndIf}
- ${EndIf}
- !macroend
- !macro RemoveVergeService
- ; Check if the service exists
- SimpleSC::ExistsService "clash_verge_service"
- Pop $0 ; 0:service exists;other: service not exists
- ; Service exists
- ${If} $0 == 0
- Push $0
- ; Check if the service is running
- SimpleSC::ServiceIsRunning "clash_verge_service"
- Pop $0 ; returns an errorcode (<>0) otherwise success (0)
- Pop $1 ; returns 1 (service is running) - returns 0 (service is not running)
- ${If} $0 == 0
- Push $0
- ${If} $1 == 1
- DetailPrint "Stop Clash Verge Service..."
- SimpleSC::StopService "clash_verge_service" 1 30
- Pop $0 ; returns an errorcode (<>0) otherwise success (0)
- ${If} $0 == 0
- DetailPrint "Removing Clash Verge Service..."
- SimpleSC::RemoveService "clash_verge_service"
- ${ElseIf} $0 != 0
- Push $0
- SimpleSC::GetErrorMessage
- Pop $0
- MessageBox MB_OK|MB_ICONSTOP "Clash Verge Service Stop Error ($0)"
- ${EndIf}
- ${ElseIf} $1 == 0
- DetailPrint "Removing Clash Verge Service..."
- SimpleSC::RemoveService "clash_verge_service"
- ${EndIf}
- ${ElseIf} $0 != 0
- Push $0
- SimpleSC::GetErrorMessage
- Pop $0
- MessageBox MB_OK|MB_ICONSTOP "Check Service Status Error ($0)"
- ${EndIf}
- ${EndIf}
- !macroend
- Section EarlyChecks
- ; Abort silent installer if downgrades is disabled
- !if "${ALLOWDOWNGRADES}" == "false"
- IfSilent 0 silent_downgrades_done
- ; If downgrading
- ${If} $R0 == -1
- System::Call 'kernel32::AttachConsole(i -1)i.r0'
- ${If} $0 != 0
- System::Call 'kernel32::GetStdHandle(i -11)i.r0'
- System::call 'kernel32::SetConsoleTextAttribute(i r0, i 0x0004)' ; set red color
- FileWrite $0 "$(silentDowngrades)"
- ${EndIf}
- Abort
- ${EndIf}
- silent_downgrades_done:
- !endif
- SectionEnd
- Section WebView2
- ; Check if Webview2 is already installed and skip this section
- ${If} ${RunningX64}
- ReadRegStr $4 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv"
- ${Else}
- ReadRegStr $4 HKLM "SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv"
- ${EndIf}
- ReadRegStr $5 HKCU "SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv"
- StrCmp $4 "" 0 webview2_done
- StrCmp $5 "" 0 webview2_done
- ; Webview2 install modes
- !if "${INSTALLWEBVIEW2MODE}" == "downloadBootstrapper"
- Delete "$TEMP\MicrosoftEdgeWebview2Setup.exe"
- DetailPrint "$(webview2Downloading)"
- NSISdl::download "https://go.microsoft.com/fwlink/p/?LinkId=2124703" "$TEMP\MicrosoftEdgeWebview2Setup.exe"
- Pop $0
- ${If} $0 == 0
- DetailPrint "$(webview2DownloadSuccess)"
- ${Else}
- DetailPrint "$(webview2DownloadError)"
- Abort "$(webview2AbortError)"
- ${EndIf}
- StrCpy $6 "$TEMP\MicrosoftEdgeWebview2Setup.exe"
- Goto install_webview2
- !endif
- !if "${INSTALLWEBVIEW2MODE}" == "embedBootstrapper"
- Delete "$TEMP\MicrosoftEdgeWebview2Setup.exe"
- File "/oname=$TEMP\MicrosoftEdgeWebview2Setup.exe" "${WEBVIEW2BOOTSTRAPPERPATH}"
- DetailPrint "$(installingWebview2)"
- StrCpy $6 "$TEMP\MicrosoftEdgeWebview2Setup.exe"
- Goto install_webview2
- !endif
- !if "${INSTALLWEBVIEW2MODE}" == "offlineInstaller"
- Delete "$TEMP\MicrosoftEdgeWebView2RuntimeInstaller.exe"
- File "/oname=$TEMP\MicrosoftEdgeWebView2RuntimeInstaller.exe" "${WEBVIEW2INSTALLERPATH}"
- DetailPrint "$(installingWebview2)"
- StrCpy $6 "$TEMP\MicrosoftEdgeWebView2RuntimeInstaller.exe"
- Goto install_webview2
- !endif
- Goto webview2_done
- install_webview2:
- DetailPrint "$(installingWebview2)"
- ; $6 holds the path to the webview2 installer
- ExecWait "$6 ${WEBVIEW2INSTALLERARGS} /install" $1
- ${If} $1 == 0
- DetailPrint "$(webview2InstallSuccess)"
- ${Else}
- DetailPrint "$(webview2InstallError)"
- Abort "$(webview2AbortError)"
- ${EndIf}
- webview2_done:
- SectionEnd
- !macro CheckIfAppIsRunning
- !if "${INSTALLMODE}" == "currentUser"
- nsis_tauri_utils::FindProcessCurrentUser "${MAINBINARYNAME}.exe"
- !else
- nsis_tauri_utils::FindProcess "${MAINBINARYNAME}.exe"
- !endif
- Pop $R0
- ${If} $R0 = 0
- IfSilent kill 0
- ${IfThen} $PassiveMode != 1 ${|} MessageBox MB_OKCANCEL "$(appRunningOkKill)" IDOK kill IDCANCEL cancel ${|}
- kill:
- !if "${INSTALLMODE}" == "currentUser"
- nsis_tauri_utils::KillProcessCurrentUser "${MAINBINARYNAME}.exe"
- !else
- nsis_tauri_utils::KillProcess "${MAINBINARYNAME}.exe"
- !endif
- Pop $R0
- Sleep 500
- ${If} $R0 = 0
- Goto app_check_done
- ${Else}
- IfSilent silent ui
- silent:
- System::Call 'kernel32::AttachConsole(i -1)i.r0'
- ${If} $0 != 0
- System::Call 'kernel32::GetStdHandle(i -11)i.r0'
- System::call 'kernel32::SetConsoleTextAttribute(i r0, i 0x0004)' ; set red color
- FileWrite $0 "$(appRunning)$\n"
- ${EndIf}
- Abort
- ui:
- Abort "$(failedToKillApp)"
- ${EndIf}
- cancel:
- Abort "$(appRunning)"
- ${EndIf}
- app_check_done:
- !macroend
- Section Install
- SetOutPath $INSTDIR
- !insertmacro CheckIfAppIsRunning
- !insertmacro CheckAllVergeProcesses
- ; Copy main executable
- File "${MAINBINARYSRCPATH}"
- ; Copy resources
- {{#each resources_dirs}}
- CreateDirectory "$INSTDIR\\{{this}}"
- {{/each}}
- {{#each resources}}
- File /a "/oname={{this.[1]}}" "{{@key}}"
- {{/each}}
- ; Copy external binaries
- {{#each binaries}}
- File /a "/oname={{this}}" "{{@key}}"
- {{/each}}
- !insertmacro StartVergeService
- ; Create uninstaller
- WriteUninstaller "$INSTDIR\uninstall.exe"
- ; Save $INSTDIR in registry for future installations
- WriteRegStr SHCTX "${MANUPRODUCTKEY}" "" $INSTDIR
- !if "${INSTALLMODE}" == "both"
- ; Save install mode to be selected by default for the next installation such as updating
- ; or when uninstalling
- WriteRegStr SHCTX "${UNINSTKEY}" $MultiUser.InstallMode 1
- !endif
- ; Registry information for add/remove programs
- WriteRegStr SHCTX "${UNINSTKEY}" "DisplayName" "${PRODUCTNAME}"
- WriteRegStr SHCTX "${UNINSTKEY}" "DisplayIcon" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\""
- WriteRegStr SHCTX "${UNINSTKEY}" "DisplayVersion" "${VERSION}"
- WriteRegStr SHCTX "${UNINSTKEY}" "Publisher" "${MANUFACTURER}"
- WriteRegStr SHCTX "${UNINSTKEY}" "InstallLocation" "$\"$INSTDIR$\""
- WriteRegStr SHCTX "${UNINSTKEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\""
- WriteRegDWORD SHCTX "${UNINSTKEY}" "NoModify" "1"
- WriteRegDWORD SHCTX "${UNINSTKEY}" "NoRepair" "1"
- WriteRegDWORD SHCTX "${UNINSTKEY}" "EstimatedSize" "${ESTIMATEDSIZE}"
- ; Create start menu shortcut (GUI)
- !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
- Call CreateStartMenuShortcut
- !insertmacro MUI_STARTMENU_WRITE_END
- ; Create shortcuts for silent and passive installers, which
- ; can be disabled by passing `/NS` flag
- ; GUI installer has buttons for users to control creating them
- IfSilent check_ns_flag 0
- ${IfThen} $PassiveMode == 1 ${|} Goto check_ns_flag ${|}
- Goto shortcuts_done
- check_ns_flag:
- ${GetOptions} $CMDLINE "/NS" $R0
- IfErrors 0 shortcuts_done
- Call CreateDesktopShortcut
- Call CreateStartMenuShortcut
- shortcuts_done:
- ; Auto close this page for passive mode
- ${IfThen} $PassiveMode == 1 ${|} SetAutoClose true ${|}
- SectionEnd
- Function .onInstSuccess
- ; Check for `/R` flag only in silent and passive installers because
- ; GUI installer has a toggle for the user to (re)start the app
- IfSilent check_r_flag 0
- ${IfThen} $PassiveMode == 1 ${|} Goto check_r_flag ${|}
- Goto run_done
- check_r_flag:
- ${GetOptions} $CMDLINE "/R" $R0
- IfErrors run_done 0
- ${GetOptions} $CMDLINE "/ARGS" $R0
- nsis_tauri_utils::RunAsUser "$INSTDIR\${MAINBINARYNAME}.exe" "$R0"
- run_done:
- FunctionEnd
- Function un.onInit
- !insertmacro SetContext
- !if "${INSTALLMODE}" == "both"
- !insertmacro MULTIUSER_UNINIT
- !endif
- !insertmacro MUI_UNGETLANGUAGE
- FunctionEnd
- !macro DeleteAppUserModelId
- !insertmacro ComHlpr_CreateInProcInstance ${CLSID_DestinationList} ${IID_ICustomDestinationList} r1 ""
- ${If} $1 P<> 0
- ${ICustomDestinationList::DeleteList} $1 '("${BUNDLEID}")'
- ${IUnknown::Release} $1 ""
- ${EndIf}
- !insertmacro ComHlpr_CreateInProcInstance ${CLSID_ApplicationDestinations} ${IID_IApplicationDestinations} r1 ""
- ${If} $1 P<> 0
- ${IApplicationDestinations::SetAppID} $1 '("${BUNDLEID}")i.r0'
- ${If} $0 >= 0
- ${IApplicationDestinations::RemoveAllDestinations} $1 ''
- ${EndIf}
- ${IUnknown::Release} $1 ""
- ${EndIf}
- !macroend
- ; From https://stackoverflow.com/a/42816728/16993372
- !macro UnpinShortcut shortcut
- !insertmacro ComHlpr_CreateInProcInstance ${CLSID_StartMenuPin} ${IID_IStartMenuPinnedList} r0 ""
- ${If} $0 P<> 0
- System::Call 'SHELL32::SHCreateItemFromParsingName(ws, p0, g "${IID_IShellItem}", *p0r1)' "${shortcut}"
- ${If} $1 P<> 0
- ${IStartMenuPinnedList::RemoveFromList} $0 '(r1)'
- ${IUnknown::Release} $1 ""
- ${EndIf}
- ${IUnknown::Release} $0 ""
- ${EndIf}
- !macroend
- Section Uninstall
- !insertmacro CheckIfAppIsRunning
- !insertmacro CheckAllVergeProcesses
- !insertmacro RemoveVergeService
- ; Delete the app directory and its content from disk
- ; Copy main executable
- Delete "$INSTDIR\${MAINBINARYNAME}.exe"
- ; Delete resources
- {{#each resources}}
- Delete "$INSTDIR\\{{this.[1]}}"
- {{/each}}
- Delete "$INSTDIR\resources"
- ; Delete external binaries
- {{#each binaries}}
- Delete "$INSTDIR\\{{this}}"
- {{/each}}
- ; Delete uninstaller
- Delete "$INSTDIR\uninstall.exe"
- {{#each resources_ancestors}}
- RMDir /REBOOTOK "$INSTDIR\\{{this}}"
- {{/each}}
- RMDir "$INSTDIR"
- !insertmacro DeleteAppUserModelId
- !insertmacro UnpinShortcut "$SMPROGRAMS\$AppStartMenuFolder\${MAINBINARYNAME}.lnk"
- !insertmacro UnpinShortcut "$DESKTOP\${MAINBINARYNAME}.lnk"
- ; Remove start menu shortcut
- !insertmacro MUI_STARTMENU_GETFOLDER Application $AppStartMenuFolder
- Delete "$SMPROGRAMS\$AppStartMenuFolder\${MAINBINARYNAME}.lnk"
- RMDir "$SMPROGRAMS\$AppStartMenuFolder"
- ; Remove desktop shortcuts
- Delete "$DESKTOP\${MAINBINARYNAME}.lnk"
- ; Remove registry information for add/remove programs
- !if "${INSTALLMODE}" == "both"
- DeleteRegKey SHCTX "${UNINSTKEY}"
- !else if "${INSTALLMODE}" == "perMachine"
- DeleteRegKey HKLM "${UNINSTKEY}"
- !else
- DeleteRegKey HKCU "${UNINSTKEY}"
- !endif
- DeleteRegValue HKCU "${MANUPRODUCTKEY}" "Installer Language"
- ; Delete app data
- ${If} $DeleteAppDataCheckboxState == 1
- SetShellVarContext current
- RmDir /r "$APPDATA\${BUNDLEID}"
- RmDir /r "$LOCALAPPDATA\${BUNDLEID}"
- ${EndIf}
- ${GetOptions} $CMDLINE "/P" $R0
- IfErrors +2 0
- SetAutoClose true
- SectionEnd
- Function RestorePreviousInstallLocation
- ReadRegStr $4 SHCTX "${MANUPRODUCTKEY}" ""
- StrCmp $4 "" +2 0
- StrCpy $INSTDIR $4
- FunctionEnd
- Function SkipIfPassive
- ${IfThen} $PassiveMode == 1 ${|} Abort ${|}
- FunctionEnd
- !macro SetLnkAppUserModelId shortcut
- !insertmacro ComHlpr_CreateInProcInstance ${CLSID_ShellLink} ${IID_IShellLink} r0 ""
- ${If} $0 P<> 0
- ${IUnknown::QueryInterface} $0 '("${IID_IPersistFile}",.r1)'
- ${If} $1 P<> 0
- ${IPersistFile::Load} $1 '("${shortcut}", ${STGM_READWRITE})'
- ${IUnknown::QueryInterface} $0 '("${IID_IPropertyStore}",.r2)'
- ${If} $2 P<> 0
- System::Call 'Oleaut32::SysAllocString(w "${BUNDLEID}") i.r3'
- System::Call '*${SYSSTRUCT_PROPERTYKEY}(${PKEY_AppUserModel_ID})p.r4'
- System::Call '*${SYSSTRUCT_PROPVARIANT}(${VT_BSTR},,&i4 $3)p.r5'
- ${IPropertyStore::SetValue} $2 '($4,$5)'
- System::Call 'Oleaut32::SysFreeString($3)'
- System::Free $4
- System::Free $5
- ${IPropertyStore::Commit} $2 ""
- ${IUnknown::Release} $2 ""
- ${IPersistFile::Save} $1 '("${shortcut}",1)'
- ${EndIf}
- ${IUnknown::Release} $1 ""
- ${EndIf}
- ${IUnknown::Release} $0 ""
- ${EndIf}
- !macroend
- Function CreateDesktopShortcut
- CreateShortcut "$DESKTOP\${MAINBINARYNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
- !insertmacro SetLnkAppUserModelId "$DESKTOP\${MAINBINARYNAME}.lnk"
- FunctionEnd
- Function CreateStartMenuShortcut
- CreateDirectory "$SMPROGRAMS\$AppStartMenuFolder"
- CreateShortcut "$SMPROGRAMS\$AppStartMenuFolder\${MAINBINARYNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"
- !insertmacro SetLnkAppUserModelId "$SMPROGRAMS\$AppStartMenuFolder\${MAINBINARYNAME}.lnk"
- FunctionEnd
|