| 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 detectedVar ReinstallPageCheckPage custom PageReinstall PageLeaveReinstallFunction 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::ShowFunctionEndFunction PageReinstallUpdateSelection  ${NSD_GetState} $R2 $R1  ${If} $R1 == ${BST_CHECKED}    StrCpy $ReinstallPageCheck 1  ${Else}    StrCpy $ReinstallPageCheck 2  ${EndIf}FunctionEndFunction 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 SkipIfPassiveVar 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_FINISHFunction RunMainBinary  nsis_tauri_utils::RunAsUser "$INSTDIR\${MAINBINARYNAME}.exe" ""FunctionEnd; Uninstaller Pages; 1. Confirm uninstall pageVar DeleteAppDataCheckboxVar DeleteAppDataCheckboxState!define /ifndef WS_EX_LAYOUTRTL         0x00400000!define MUI_PAGE_CUSTOMFUNCTION_SHOW un.ConfirmShowFunction 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 1FunctionEnd!define MUI_PAGE_CUSTOMFUNCTION_LEAVE un.ConfirmLeaveFunction un.ConfirmLeave    SendMessage $DeleteAppDataCheckbox ${BM_GETCHECK} 0 0 $DeleteAppDataCheckboxStateFunctionEnd!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}!macroendVar PassiveModeFunction .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  !endifFunctionEnd!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}!macroendSection 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:  !endifSectionEndSection 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:!macroendSection 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 ${|}SectionEndFunction .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:FunctionEndFunction un.onInit  !insertmacro SetContext  !if "${INSTALLMODE}" == "both"    !insertmacro MULTIUSER_UNINIT  !endif  !insertmacro MUI_UNGETLANGUAGEFunctionEnd!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}!macroendSection 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 trueSectionEndFunction RestorePreviousInstallLocation  ReadRegStr $4 SHCTX "${MANUPRODUCTKEY}" ""  StrCmp $4 "" +2 0    StrCpy $INSTDIR $4FunctionEndFunction 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}!macroendFunction CreateDesktopShortcut  CreateShortcut "$DESKTOP\${MAINBINARYNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"  !insertmacro SetLnkAppUserModelId "$DESKTOP\${MAINBINARYNAME}.lnk"FunctionEndFunction CreateStartMenuShortcut  CreateDirectory "$SMPROGRAMS\$AppStartMenuFolder"  CreateShortcut "$SMPROGRAMS\$AppStartMenuFolder\${MAINBINARYNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe"  !insertmacro SetLnkAppUserModelId "$SMPROGRAMS\$AppStartMenuFolder\${MAINBINARYNAME}.lnk"FunctionEnd
 |