This commit is contained in:
2022-09-30 05:39:11 +00:00
parent 41ee9463ae
commit 4687fa49bc
11418 changed files with 1312504 additions and 0 deletions

View File

@ -0,0 +1,142 @@
!include UAC.nsh
!ifndef INSTALL_MODE_PER_ALL_USERS
!include multiUserUi.nsh
!endif
!ifndef BUILD_UNINSTALLER
!ifmacrodef customWelcomePage
!insertmacro customWelcomePage
!endif
!ifmacrodef licensePage
!insertmacro skipPageIfUpdated
!insertmacro licensePage
!endif
!ifndef INSTALL_MODE_PER_ALL_USERS
!insertmacro PAGE_INSTALL_MODE
!endif
!ifdef allowToChangeInstallationDirectory
!include StrContains.nsh
!insertmacro skipPageIfUpdated
!insertmacro MUI_PAGE_DIRECTORY
# pageDirectory leave doesn't work (it seems because $INSTDIR is set after custom leave function)
# so, we use instfiles pre
!define MUI_PAGE_CUSTOMFUNCTION_PRE instFilesPre
# sanitize the MUI_PAGE_DIRECTORY result to make sure it has a application name sub-folder
Function instFilesPre
${If} ${FileExists} "$INSTDIR\*"
${StrContains} $0 "${APP_FILENAME}" $INSTDIR
${If} $0 == ""
StrCpy $INSTDIR "$INSTDIR\${APP_FILENAME}"
${endIf}
${endIf}
FunctionEnd
!endif
# after change installation directory and before install start, you can show custom page here.
!ifmacrodef customPageAfterChangeDir
!insertmacro customPageAfterChangeDir
!endif
!insertmacro MUI_PAGE_INSTFILES
!ifmacrodef customFinishPage
!insertmacro customFinishPage
!else
!ifndef HIDE_RUN_AFTER_FINISH
Function StartApp
${if} ${isUpdated}
StrCpy $1 "--updated"
${else}
StrCpy $1 ""
${endif}
${StdUtils.ExecShellAsUser} $0 "$launchLink" "open" "$1"
FunctionEnd
!define MUI_FINISHPAGE_RUN
!define MUI_FINISHPAGE_RUN_FUNCTION "StartApp"
!endif
!insertmacro MUI_PAGE_FINISH
!endif
!else
!insertmacro MUI_UNPAGE_WELCOME
!ifndef INSTALL_MODE_PER_ALL_USERS
!insertmacro PAGE_INSTALL_MODE
!endif
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_FINISH
!endif
!macro initMultiUser
!ifdef INSTALL_MODE_PER_ALL_USERS
!insertmacro setInstallModePerAllUsers
!else
${If} ${UAC_IsInnerInstance}
${AndIfNot} ${UAC_IsAdmin}
# special return value for outer instance so it knows we did not have admin rights
SetErrorLevel 0x666666
Quit
${endIf}
!ifndef MULTIUSER_INIT_TEXT_ADMINREQUIRED
!define MULTIUSER_INIT_TEXT_ADMINREQUIRED "$(^Caption) requires administrator privileges."
!endif
!ifndef MULTIUSER_INIT_TEXT_POWERREQUIRED
!define MULTIUSER_INIT_TEXT_POWERREQUIRED "$(^Caption) requires at least Power User privileges."
!endif
!ifndef MULTIUSER_INIT_TEXT_ALLUSERSNOTPOSSIBLE
!define MULTIUSER_INIT_TEXT_ALLUSERSNOTPOSSIBLE "Your user account does not have sufficient privileges to install $(^Name) for all users of this computer."
!endif
# checks registry for previous installation path (both for upgrading, reinstall, or uninstall)
StrCpy $hasPerMachineInstallation "0"
StrCpy $hasPerUserInstallation "0"
# set installation mode to setting from a previous installation
ReadRegStr $perMachineInstallationFolder HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation
${if} $perMachineInstallationFolder != ""
StrCpy $hasPerMachineInstallation "1"
${endif}
ReadRegStr $perUserInstallationFolder HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation
${if} $perUserInstallationFolder != ""
StrCpy $hasPerUserInstallation "1"
${endif}
${GetParameters} $R0
${GetOptions} $R0 "/allusers" $R1
${IfNot} ${Errors}
StrCpy $hasPerMachineInstallation "1"
StrCpy $hasPerUserInstallation "0"
${EndIf}
${GetOptions} $R0 "/currentuser" $R1
${IfNot} ${Errors}
StrCpy $hasPerMachineInstallation "0"
StrCpy $hasPerUserInstallation "1"
${EndIf}
${if} $hasPerUserInstallation == "1"
${andif} $hasPerMachineInstallation == "0"
!insertmacro setInstallModePerUser
${elseif} $hasPerUserInstallation == "0"
${andif} $hasPerMachineInstallation == "1"
!insertmacro setInstallModePerAllUsers
${else}
# if there is no installation, or there is both per-user and per-machine
!ifdef INSTALL_MODE_PER_ALL_USERS
!insertmacro setInstallModePerAllUsers
!else
!insertmacro setInstallModePerUser
!endif
${endif}
!endif
!macroend

View File

@ -0,0 +1,351 @@
# assisted installer messages, see messages.yml for one-click installer messages
chooseInstallationOptions:
en: Choose Installation Options
de: Installationsoption wählen
ru: Выберите опции установки
sk: Vyberte možnosti inštalácie
cs: Vyberte možnosti instalace
fr: Choisis les options d'installation
hu_HU: Telepítési opciók kiválasztása
pt_BR: Escolha uma opção de instalação
zh_CN: 安装选项
zh_TW: 安裝選項
tr_TR: Yükleme Ayarlarını Seçin
sv_SE: Välj alternativ för installation
pl_PL: Wybierz opcje instalacji
no: Velg alternativer for installering
nl_NL: Kies installatie-opties
it_IT: Scegli opzioni di installazione
fi: Valitse asennusvaihtoehdot
es: Elegir opciones de instalación
da: Vælg Installeringsmuligheder
ja: インストールオプションの選択
chooseUninstallationOptions:
en: Choose Uninstallation Options
de: Deinstallationsoption wählen
ru: Выберите опции удаления
sk: Vyberte možnosti odinštalovania
cs: Vyberte možnosti odinstalace
fr: Choisis les options de désinstallation
hu_HU: Eltávolítási opciók kiválasztása
pt_BR: Escolha uma opção de desinstalação
zh_CN: 卸载选项
zh_TW: 卸載選項
tr_TR: Kaldırma Ayarlarını Seçin
sv_SE: Välj alternativ för avinstallation
pl_PL: Wybierz opcje dezinstalacji
no: Velg alternativer for avinstallering
nl_NL: Kies verwijderings-opties
it_IT: Scegli opzioni di disinstallazione
fi: Valitse asennuksen poistovaihtoehdot
es: Elegir opciones de desinstalación
da: Vælg Afinstalleringsmuligheder
ja: アンインストールオプションの選択
whichInstallationShouldBeRemoved:
en: Which installation should be removed?
de: Welche Installation soll entfernt werden?
ru: Какую из установленных программ следует удалить?
sk: Ktorá inštalácia by mala byt odstránená?
cs: Která instalace by měla má být odstraněná?
fr: Quelle installation doit être supprimée ?
hu_HU: Melyik telepítést távolítsuk el?
pt_BR: Qual instalação deve ser removida?
zh_CN: 需要移除哪个安装?
zh_TW: 需要移除哪個安裝?
tr_TR: Hangi Yükleme Kaldırılsın?
sv_SE: Vilken installation ska tas bort?
pl_PL: Którą instalację chcesz usunąć?
no: Hvilken installasjon skal fjernes?
nl_NL: Welke installatie moet worden verwijderd?
it_IT: Quale installazione intendi rimuovere?
fi: Mikä asennus pitäisi poistaa?
es: ¿Qué tipo de instalación debe eliminarse?
da: Hvilken installering skal fjernes?
ja: どれをアンインストールしますか?
whoShouldThisApplicationBeInstalledFor:
en: Who should this application be installed for?
de: Für wen soll diese Anwendung installiert werden?
ru: Для кого следует установить это приложение?
sk: Pre koho sa ma táto aplikacia inštalovať?
cs: Pro koho se má tato aplikace instalovat?
fr: Pour qui cette application doit-elle être installée ?
hu_HU: Kinek legyen ez az alkalmazás telepítve?
pt_BR: Para quem esta aplicação deve ser instalada?
zh_CN: 为哪位用户安装该应用?
zh_TW: 為哪位用戶安裝該應用?
tr_TR: Bu Uygulama Kimler için Kurulsun?
sv_SE: Vem ska den här applikationen installeras för?
pl_PL: Dla kogo zainstalować tę aplikację?
no: Hvem skal dette programmet installeres for?
nl_NL: Voor wie moet deze applicatie worden geïnstalleerd?
it_IT: Per chi dovrebbe essere installata questa applicazione?
fi: Kenen käyttöön tämä sovellus pitäisi asentaa?
es: ¿Para quién se instalará esta aplicación?
da: Hvem skal denne applikation installeres til?
ja: どのユーザーにインストールしますか?
selectUserMode:
en: Please select whether you wish to make this software available to all users or just yourself
de: Bitte wählen Sie, ob Sie die Anwendung nur für sich oder für alle Benutzer installieren möchten.
ru: Выбери, хочешь ли ты сделать эту программу доступной для всех пользователей или только для себя
sk: Prosím vyberte či sa ma tento softvér inštalovať len pre Vás alebo pre všetkých uživateľov
cs: Prosím vyberte, zda se má tento software instalovat jen proVás nebo pro všechny uživatele
fr: "Choisis pour qui ce logiciel doit être accessible : pour tous les utilisateurs ou juste pour toi ?"
hu_HU: Válaszd ki, hogy a szoftver elérhető legyen-e minden felhasználó számára, vagy csak neked
pt_BR: Por favor, selecione se este software deve estar disponível apenas para você ou para todos usuários
zh_CN: 请选择为当前用户还是所有用户安装该软件
zh_TW: 請選擇為當前用戶還是所有用戶安裝該軟件
tr_TR: Lütfen bu yazılımı tüm kullanıcılar için mi yoksa sadece kendiniz mi kullanmak istediğinizi seçin
sv_SE: Välj om du vill göra den här mjukvaran tillgänglig för alla användare eller bara för dig
pl_PL: Wybierz, czy to oprogramowanie ma być dostępne dla wszystkich użytkowników, czy tylko dla Ciebie
no: Velg om du vil gjøre denne programvaren tilgjengelig for alle brukerne eller bare deg selv
nl_NL: Selecteer of je deze software beschikbaar wilt maken voor alle gebruikers of alleen voor jezelf.
it_IT: Seleziona se desideri rendere questo software accessibile a tutti gli utenti o solo a te
fi: Valitse, haluatko tämän ohjelmiston kaikkien käyttäjien vai pelkästään itsesi käyttöön
es: Elige si deseas que este software esté disponible para todos los usuarios o solo para ti.
da: Vælg, om du vil gøre denne software tilgængelig for andre brugere, eller kun for dig selv
ja: このソフトウェアをすべてのユーザーが使用できるようにするか、現在のユーザーのみ使用するかを選択してください
whichInstallationRemove:
en: This software is installed both per-machine (all users) and per-user.\nWhich installation you wish to remove?
de: Die Anwendung wurde für alle Benutzer und pro Benutzer installiert.\nWelche Installation möchten Sie entfernen?
ru: Эта программа установлена для всего компьютера (для всех пользователей) и для отдельного пользователя.\nКакую из установленных программ ты хочешь удалить?
sk: Tento softvér je nainštalovaný pre Vás a súčasne pre všetkých uživateľov.\nKtorú inštaláciu si želáte odstraniť?
cs: Tento software je nainstalovaný pro Vás a současně pro všechny uživatele.\nKterou instalace si přejete odstranit?
fr: Ce logiciel est installé à la fois par machine (tous les utilisateurs) et par utilisateur.\nQuelle installation veux-tu supprimer ?
hu_HU: Ez a szoftver számítógépenként (minden felhasználó) és felhasználónként is telepítve van.\nMelyik telepítést szeretnéd eltávolítani?
pt_BR: Este software é instalado por máquina (todos os usuários) e por usuário. Qual instalação você deseja remover?
zh_CN: 该软件已为所有用户和当前用户安装.\n您希望移除哪个安装?
zh_TW: 該軟件已為所有用戶和當前用戶安裝.\n您希望移除哪個安裝?
tr_TR: Bu yazılım hem makine başına (tüm kullanıcılar) hem de kullanıcı başına yüklenir.\nKaldırmak istediğiniz kurulum?
sv_SE: Den här mjukvaran är installerad både ”per dator” (alla användare) och ”per användare”.\nVilken installation vill du ta bort?
pl_PL: To oprogramowanie zostało zainstalowane zarówno dla urządzenia (wszyscy użytkownicy), jak i dla użytkownika.\nKtórą instalację chcesz usunąć?
no: Denne programvaren er installert både per-maskin (alle brukere) og per-bruker. Hvilken installasjon vil du fjerne?
nl_NL: Deze software is zowel per apparaat (alle gebruikers) als per gebruiker geïnstalleerd. Welke installatie wil je verwijderen?
it_IT: Questo software è stato installato sia per computer (tutti gli utenti) sia per utente.\nQuale installazione desideri rimuovere?
fi: Tämä ohjelmisto on asennettu sekä konekohtaisesti (kaikki käyttäjät) että käyttäjäkohtaisesti.\nMinkä asennuksen haluat poistaa?
es: Este software se ha instalado para la máquina (todos los usuarios) y para el usuario.\n¿Qué instalación quieres eliminar?
da: Denne software er installeret både pr. maskine (alle brugere) og pr. bruger./nHvilken installering ønsker du at fjerne?
ja: このソフトウェアは、マシンごと(すべてのユーザー)とユーザーごとにインストールされています。\ nどちらを削除しますか
freshInstallForAll:
en: Fresh install for all users. (will prompt for admin credentials)
de: Neuinstallation für alle Benutzer durchführen. (Administratorrechte benötigt)
ru: Новая установка для всех пользователей. (потребуются права администратора)
sk: Nová inštalácia pre všetkých uživateľov. (will prompt for admin credentials)
cs: Nová instalace pro všechny uživatele. (bude vyžadovat přihlášení administrátora)
fr: Nouvelle installation pour tous les utilisateurs. (demandera les identifiants administrateur)
hu_HU: Új telepítés minden felhasználó számára. (Az adminisztrátor hitelesítő adataira lesz szükség.)
pt_BR: Instalação limpa para todos os usuários. (irá solicitar credenciais de administrador)
zh_CN: 为所有用户进行全新安装. (需要管理员资格)
zh_TW: 為所有用戶進行全新安裝. (需要管理員資格)
tr_TR: Tüm kullanıcılar için yeni yükleme. (yönetici kimlik bilgilerini soracaktır)
sv_SE: Ny installation för alla användare. (kommer att begära adminbehörighet)
pl_PL: Nowa instalacja dla wszystkich użytkowników (potrzebne będą dane administratora).
no: Ny installasjon for alle brukere. (vil be om administratorlegitimasjon)
nl_NL: Nieuwe installatie voor alle gebruikers. (zal om beheerder-gegevens vragen)
it_IT: Re-installa per tutti gli utenti. (Richiede le credenziali di amministratore)
fi: Uusi asennus kaikille käyttäjille (pyytää ylläpitäjän käyttäjätunnuksia)
es: Instalación nueva para todos los usuarios (se pedirán los credenciales del administrador)
da: Ny installering til alle brugere. (Vil medføre administrations-legitimationsoplysninger)
ja: すべてのユーザーに新規インストール(管理者権限が必要)
freshInstallForCurrent:
en: Fresh install for current user only.
de: Neuinstallation nur für den aktuellen Benutzer durchführen.
ru: Новая установка только для текущего пользователя.
cs: Nová instalace pro aktuálního uživatele.
fr: Nouvelle installation uniquement pour l'utilisateur actuel.
hu_HU: Új telepítés csak a jelenlegi felhasználó számára.
pt_BR: Instalação limpa somente para o usuário atual.
zh_CN: 仅为当前用户进行全新安装.
zh_TW: 僅為當前用戶進行全新安裝.
tr_TR: Sadece mevcut kullanıcı için yeni yükleme.
sv_SE: Ny installation endast för den aktuella användaren.
pl_PL: Nowa instalacja wyłącznie dla obecnego użytkownika.
no: Ny installasjon kun for nåværende bruker.
nl_NL: Nieuwe installatie alleen voor huidige gebruiker.
it_IT: Re-installa solo per l'utente attuale.
fi: Uusi asennus vain nykyiselle käyttäjälle.
es: Instalación nueva solo para el usuario actual.
da: Ny installering kun til nuværende bruger.
ja: 現在のユーザーのみ新規インストール
onlyForMe:
en: Only for &me
de: Nur für &mich
ru: Только для &меня
sk: Iba pre mňa
cs: Pouze pro &mě
fr: Juste pour moi
hu_HU: Csak az én számomra
pt_BR: Apenas para &mim
zh_CN: 仅为我安装
zh_TW: 僅為我安裝
tr_TR: Sadece benim için
sv_SE: Endast för &mig
pl_PL: Tylko dla &mnie
no: Kun for &meg
nl_NL: Alleen voor &mij
it_IT: Solo per &me
fi: Vain minulle
es: Solo para mí.
da: Kun til mig
ja: 現在のユーザーのみにインストールする
forAll:
en: Anyone who uses this computer (&all users)
de: Für alle Benutzer dieses Computers (&alle Benutzer)
ru: Для &всех пользователей данного компьютера
sk: Pre každého kto použiva tento počitač (všetci uživatelia)
cs: Pro každého, kdo používá tento počítač (všichni uživatelé)
fr: Pour tous ceux qui utilisent cet ordinateur (tous les utilisateurs)
hu_HU: Bárki számára, aki ezt a számítógépet használja (minden felhasználó)
pt_BR: Para todos que usam esta máquina (&todos os usuários)
zh_CN: 为使用这台电脑的任何人安装 (所有用户)
zh_TW: 為使用這台電腦的任何人安裝 (所有用戶)
tr_TR: Bu bilgisayarı kullanan herkes (ve tüm kullanıcılar)
sv_SE: Alla som använder den här datorn (alla användare)
pl_PL: Każdy korzystający z tego komputera (wszyscy użytkownicy)
no: Alle som bruker denne datamaskinen (alle brukere)
nl_NL: Iedereen die deze computer gebruikt (alle gebruikers)
it_IT: Per chiunque usi questo computer (tutti gli utenti)
fi: Kaikille, jotka käyttävät tätä tietokonetta (kaikki käyttäjät)
es: Cualquiera que utilice este ordenador (todos los usuarios)
da: Enhver, der bruger denne computer (alle brugere)
ja: このコンピューターを使用しているすべてのユーザー用にインストールする
loginWithAdminAccount:
en: You need to login with an account that is a member of the admin group to continue...
de: Um die Installation fortzusetzen müssen Sie sich mit einem Administrator-Account anmelden...
ru: Чтобы продолжить, тебе нужно войти в учетную запись, которая входит в группу администраторов...
sk: Pre pokračovanie sa musíte zalogovať s účtom ktorý patrí do skupiny adminstrátorov...
cs: Pro pokračování se musíte přihlásit s účtem, který patří do skupiny administrátorů...
fr: Tu dois te connecter avec un compte ayant des droits d'administrateur pour continuer...
hu_HU: A folytatáshoz adminisztrátori jogokkal rendelkező fiókkal kell bejelentkezned...
pt_BR: Você precisa realizar o login com uma conta que é membro do grupo de administração para continuar...
zh_CN: 您需要用属于管理员群组的用户账户登录来继续...
zh_TW: 您需要用屬於管理員群組的用戶賬戶登錄來繼續...
tr_TR: Devam etmek için yönetici grubunun üyesi olan bir hesapla giriş yapmanız gerekiyor..
sv_SE: Du måste logga in med ett konto som är medlem i admingruppen för att fortsätta...
pl_PL: Musisz się zalogować za pomocą konta będącego członkiem grupy administratora, by kontynuować...
no: Du må logge inn med en konto som er medlem av administrasjonsgruppen for å fortsette...
nl_NL: Je dient in te loggen met een account dat lid is van de beheerdersgroep om verder te gaan...
it_IT: Devi accedere con un account incluso nel gruppo amministratore per continuare...
fi: Jatkaaksesi sinun on kirjauduttava käyttäjätilillä, joka on ylläpitäjäryhmän jäsen...
es: Para continuar, tienes que iniciar sesión con una cuenta que pertenezca al grupo de administradores...
da: Du skal logge ind med en konto, der er medlem af administrationsgruppen for at kunne fortsætte...
ja: 続行するには、管理者権限アカウントでログインする必要があります...
perUserInstallExists:
en: There is already a per-user installation.
de: Es existiert bereits eine Installtion für den ausgewählten Benutzer.
ru: Уже есть установленная программа для отдельного пользователя.
cs: Již existuje instalace pro uživatele.
fr: Il y a déjà une installation par utilisateur.
hu_HU: Már van egy felhasználónkénti telepítés.
pt_BR: Já existe uma instalação por usuário.
zh_CN: 已经存在一个安装到当前用户的安装.
zh_TW: 已經存在一個安裝到當前用戶的安裝.
tr_TR: Her kullanıcı için zaten bir kurulum var.
sv_SE: Det finns redan en ”per användare”-installation.
pl_PL: Instalacja dla użytkownika już istnieje.
no: Det er allerede en per-bruker-installasjon.
nl_NL: Er is al een installatie 'per gebruiker'.
it_IT: È già presente un'installazione per utente.
fi: Tämä on jo käyttäjäkohtainen asennus.
es: Ya hay una instalación por usuario.
da: Der er allerede en pr. bruger installation.
ja: すでに現在のユーザーにインストールされています。
perUserInstall:
en: There is a per-user installation.
de: Benutzerinstallation bereits vorhanden.
ru: Есть установленная программа для отдельного пользователя.
cs: Instalace pro uživatele.
fr: Il y a une installation par utilisateur.
hu_HU: Van felhasználónkénti telepítés.
pt_BR: Existe uma instalação por usuário.
zh_CN: 存在一个安装到当前用户的安装.
zh_TW: 存在一個安裝到當前用戶的安裝.
tr_TR: Kullanıcı başına bir kurulum var.
sv_SE: Det finns en ”per användare”-installation.
pl_PL: Instalacja dla użytkownika istnieje.
no: Det er en per-bruker-installasjon.
nl_NL: Er is een installatie 'per gebruiker'.
it_IT: È presente un'installazione per utente.
fi: Käyttäjäkohtainen asennus on olemassa.
es: Hay una instalación por usuario.
da: Der er en pr. bruger installation.
ja: ユーザーごとのインストールがあります。
perMachineInstallExists:
en: There is already a per-machine installation.
de: Es existiert bereits eine Installation für diesen Computer.
ru: Уже есть установленная программа для всего компьютера.
cs: Již existuje instalace pro tento počítač.
fr: Il y a déjà une installation par machine.
hu_HU: Már van egy számítógépenkénti telepítés.
pt_BR: Já existe uma instalação por máquina.
zh_CN: 已经存在一个安装到所有用户的安装.
zh_TW: 已經存在一個安裝到所有用戶的安裝.
tr_TR: Zaten makine başına bir kurulum var.
sv_SE: Det finns redan en ”per dator”-installation.
pl_PL: Instalacja dla urządzenia już istnieje.
no: Det er allerede en per-maskin-installasjon.
nl_NL: Er is al een installatie 'per apparaat'.
it_IT: È già presente un'installazione per computer.
fi: Tämä on jo tietokonekohtainen asennus.
es: Ya hay una instalación por máquina.
da: Der er allerede en pr. maskine installation.
ja: 既にすべてのユーザー用にインストールされています。
perMachineInstall:
en: There is a per-machine installation.
de: Es existiert eine Installation für diesen Computer.
ru: Есть установленная программа для всего компьютера.
cs: Instalace pro tento počítač.
fr: Il y a une installation par machine.
hu_HU: Van számítógépenkénti telepítés.
pt_BR: Existe uma instalação por máquina.
zh_CN: 存在一个安装到所有用户的安装.
zh_TW: 存在一個安裝到所有用戶的安裝.
tr_TR: Makine başına bir yükleme var.
sv_SE: Det finns en ”per dator”-installation.
pl_PL: Instalacja dla urządzenia istnieje.
no: Det er en per-maskin-installasjon.
nl_NL: Er is een installatie 'per apparaat'.
it_IT: È presente un'installazione per computer.
fi: Tietokonekohtainen asennus on olemassa.
es: Hay una instalación por máquina.
da: Der er en pr. maskine installation.
ja: すべてのユーザー用のインストールがあります。
reinstallUpgrade:
en: Will reinstall/upgrade.
de: Die Anwendung wird aktualisiert.
ru: Приложение будет переустановлено/обновлено.
cs: Bude přeinstalováno/aktualizováno.
fr: Va réinstaller/mettre à jour.
hu_HU: Újratelepít/frissít.
pt_BR: Irá reinstalar/atualizar.
zh_CN: 即将重新安装/升级.
zh_TW: 即將重新安裝/升級.
tr_TR: Yeniden yükleme/yükseltme
sv_SE: Kommer att ominstallera/uppgradera.
pl_PL: Nastąpi ponowna instalacja/aktualizacja.
no: Vil installere på nytt / oppgradere.
nl_NL: Zal opnieuw installeren/upgraden.
it_IT: Re-installa/aggiorna il programma.
fi: Asennetaan uudelleen/päivitetään.
es: Se reinstalará/actualizará.
da: Reinstallerer/opgraderer.
ja: 再インストール/アップグレードします。
uninstall:
en: Will uninstall.
de: Die Anwendung wird deinstalliert.
ru: Приложение будет удалено.
cs: Odinstaluje se.
fr: Va désinstaller.
hu_HU: Eltávolít.
pt_BR: Irá desinstalar.
zh_CN: 即将卸载.
zh_TW: 即將卸載.
tr_TR: Kaldıralacak.
sv_SE: Kommer att avinstallera.
pl_PL: Nastąpi dezinstalacja.
no: Vil avinstallere.
nl_NL: Zal installatie verwijderen.
it_IT: Disinstalla il programma.
fi: Poistetaan asennus.
es: Se desinstalará.
da: Afinstallerer.
ja: アンインストールします。

View File

@ -0,0 +1,101 @@
!include x64.nsh
!include WinVer.nsh
BrandingText "${PRODUCT_NAME} ${VERSION}"
ShowInstDetails nevershow
SpaceTexts none
!ifdef BUILD_UNINSTALLER
ShowUninstDetails nevershow
!endif
FileBufSize 64
Name "${PRODUCT_NAME}"
!define APP_EXECUTABLE_FILENAME "${PRODUCT_FILENAME}.exe"
!define UNINSTALL_FILENAME "Uninstall ${PRODUCT_FILENAME}.exe"
!macro check64BitAndSetRegView
# https://github.com/electron-userland/electron-builder/issues/2420
${If} ${IsWin2000}
${OrIf} ${IsWinME}
${OrIf} ${IsWinXP}
${OrIf} ${IsWinVista}
MessageBox MB_OK "$(win7Required)"
Quit
${EndIf}
!ifdef APP_ARM64
${If} ${RunningX64}
SetRegView 64
${EndIf}
${If} ${IsNativeARM64}
SetRegView 64
${EndIf}
!else
!ifdef APP_64
${If} ${RunningX64}
SetRegView 64
${Else}
!ifndef APP_32
MessageBox MB_OK|MB_ICONEXCLAMATION "$(x64WinRequired)"
Quit
!endif
${EndIf}
!endif
!endif
!macroend
# avoid exit code 2
!macro quitSuccess
SetErrorLevel 0
Quit
!macroend
!macro setLinkVars
# old desktop shortcut (could exist or not since the user might has selected to delete it)
ReadRegStr $oldShortcutName SHELL_CONTEXT "${INSTALL_REGISTRY_KEY}" ShortcutName
${if} $oldShortcutName == ""
StrCpy $oldShortcutName "${PRODUCT_FILENAME}"
${endIf}
StrCpy $oldDesktopLink "$DESKTOP\$oldShortcutName.lnk"
# new desktop shortcut (will be created/renamed in case of a fresh installation or if the user haven't deleted the initial one)
StrCpy $newDesktopLink "$DESKTOP\${SHORTCUT_NAME}.lnk"
ReadRegStr $oldMenuDirectory SHELL_CONTEXT "${INSTALL_REGISTRY_KEY}" MenuDirectory
${if} $oldMenuDirectory == ""
StrCpy $oldStartMenuLink "$SMPROGRAMS\$oldShortcutName.lnk"
${else}
StrCpy $oldStartMenuLink "$SMPROGRAMS\$oldMenuDirectory\$oldShortcutName.lnk"
${endIf}
# new menu shortcut (will be created/renamed in case of a fresh installation or if the user haven't deleted the initial one)
!ifdef MENU_FILENAME
StrCpy $newStartMenuLink "$SMPROGRAMS\${MENU_FILENAME}\${SHORTCUT_NAME}.lnk"
!else
StrCpy $newStartMenuLink "$SMPROGRAMS\${SHORTCUT_NAME}.lnk"
!endif
!macroend
!macro skipPageIfUpdated
!define UniqueID ${__LINE__}
Function skipPageIfUpdated_${UniqueID}
${if} ${isUpdated}
Abort
${endif}
FunctionEnd
!define MUI_PAGE_CUSTOMFUNCTION_PRE skipPageIfUpdated_${UniqueID}
!undef UniqueID
!macroend
!macro StartApp
Var /GLOBAL startAppArgs
${if} ${isUpdated}
StrCpy $startAppArgs "--updated"
${else}
StrCpy $startAppArgs ""
${endif}
${StdUtils.ExecShellAsUser} $0 "$launchLink" "open" "$startAppArgs"
!macroend

View File

@ -0,0 +1 @@
Loading...

View File

@ -0,0 +1,132 @@
; fileassoc.nsh
; File association helper macros
; Written by Saivert
;
; Features automatic backup system and UPDATEFILEASSOC macro for
; shell change notification.
;
; |> How to use <|
; To associate a file with an application so you can double-click it in explorer, use
; the APP_ASSOCIATE macro like this:
;
; Example:
; !insertmacro APP_ASSOCIATE "txt" "myapp.textfile" "Description of txt files" \
; "$INSTDIR\myapp.exe,0" "Open with myapp" "$INSTDIR\myapp.exe $\"%1$\""
;
; Never insert the APP_ASSOCIATE macro multiple times, it is only ment
; to associate an application with a single file and using the
; the "open" verb as default. To add more verbs (actions) to a file
; use the APP_ASSOCIATE_ADDVERB macro.
;
; Example:
; !insertmacro APP_ASSOCIATE_ADDVERB "myapp.textfile" "edit" "Edit with myapp" \
; "$INSTDIR\myapp.exe /edit $\"%1$\""
;
; To have access to more options when registering the file association use the
; APP_ASSOCIATE_EX macro. Here you can specify the verb and what verb is to be the
; standard action (default verb).
;
; Note, that this script takes into account user versus global installs.
; To properly work you must initialize the SHELL_CONTEXT variable via SetShellVarContext.
;
; And finally: To remove the association from the registry use the APP_UNASSOCIATE
; macro. Here is another example just to wrap it up:
; !insertmacro APP_UNASSOCIATE "txt" "myapp.textfile"
;
; |> Note <|
; When defining your file class string always use the short form of your application title
; then a period (dot) and the type of file. This keeps the file class sort of unique.
; Examples:
; Winamp.Playlist
; NSIS.Script
; Photoshop.JPEGFile
;
; |> Tech info <|
; The registry key layout for a global file association is:
;
; HKEY_LOCAL_MACHINE\Software\Classes
; <".ext"> = <applicationID>
; <applicationID> = <"description">
; shell
; <verb> = <"menu-item text">
; command = <"command string">
;
;
; The registry key layout for a per-user file association is:
;
; HKEY_CURRENT_USER\Software\Classes
; <".ext"> = <applicationID>
; <applicationID> = <"description">
; shell
; <verb> = <"menu-item text">
; command = <"command string">
;
!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND
; Backup the previously associated file class
ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" ""
WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0"
WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}"
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}`
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}`
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell" "" "open"
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open" "" `${COMMANDTEXT}`
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open\command" "" `${COMMAND}`
!macroend
!macro APP_ASSOCIATE_EX EXT FILECLASS DESCRIPTION ICON VERB DEFAULTVERB SHELLNEW COMMANDTEXT COMMAND
; Backup the previously associated file class
ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" ""
WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0"
WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}"
StrCmp "${SHELLNEW}" "0" +2
WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}\ShellNew" "NullFile" ""
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}`
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}`
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell" "" `${DEFAULTVERB}`
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\${VERB}" "" `${COMMANDTEXT}`
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\${VERB}\command" "" `${COMMAND}`
!macroend
!macro APP_ASSOCIATE_ADDVERB FILECLASS VERB COMMANDTEXT COMMAND
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\${VERB}" "" `${COMMANDTEXT}`
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\${VERB}\command" "" `${COMMAND}`
!macroend
!macro APP_ASSOCIATE_REMOVEVERB FILECLASS VERB
DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}\shell\${VERB}`
!macroend
!macro APP_UNASSOCIATE EXT FILECLASS
; Backup the previously associated file class
ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" `${FILECLASS}_backup`
WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "$R0"
DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}`
!macroend
!macro APP_ASSOCIATE_GETFILECLASS OUTPUT EXT
ReadRegStr ${OUTPUT} SHELL_CONTEXT "Software\Classes\.${EXT}" ""
!macroend
; !defines for use with SHChangeNotify
!ifdef SHCNE_ASSOCCHANGED
!undef SHCNE_ASSOCCHANGED
!endif
!define SHCNE_ASSOCCHANGED 0x08000000
!ifdef SHCNF_FLUSH
!undef SHCNF_FLUSH
!endif
!define SHCNF_FLUSH 0x1000
!macro UPDATEFILEASSOC
; Using the system.dll plugin to call the SHChangeNotify Win32 API function so we
; can update the shell.
System::Call "shell32::SHChangeNotify(i,i,i,i) (${SHCNE_ASSOCCHANGED}, ${SHCNF_FLUSH}, 0, 0)"
!macroend

View File

@ -0,0 +1,496 @@
#################################################################################
# StdUtils plug-in for NSIS
# Copyright (C) 2004-2018 LoRd_MuldeR <MuldeR2@GMX.de>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#
# http://www.gnu.org/licenses/lgpl-2.1.txt
#################################################################################
# DEVELOPER NOTES:
# - Please see "https://github.com/lordmulder/stdutils/" for news and updates!
# - Please see "Docs\StdUtils\StdUtils.html" for detailed function descriptions!
# - Please see "Examples\StdUtils\StdUtilsTest.nsi" for usage examples!
#################################################################################
# FUNCTION DECLARTIONS
#################################################################################
!ifndef ___STDUTILS__NSH___
!define ___STDUTILS__NSH___
!define StdUtils.Time '!insertmacro _StdU_Time' #time(), as in C standard library
!define StdUtils.GetMinutes '!insertmacro _StdU_GetMinutes' #GetSystemTimeAsFileTime(), returns the number of minutes
!define StdUtils.GetHours '!insertmacro _StdU_GetHours' #GetSystemTimeAsFileTime(), returns the number of hours
!define StdUtils.GetDays '!insertmacro _StdU_GetDays' #GetSystemTimeAsFileTime(), returns the number of days
!define StdUtils.Rand '!insertmacro _StdU_Rand' #rand(), as in C standard library
!define StdUtils.RandMax '!insertmacro _StdU_RandMax' #rand(), as in C standard library, with maximum value
!define StdUtils.RandMinMax '!insertmacro _StdU_RandMinMax' #rand(), as in C standard library, with minimum/maximum value
!define StdUtils.RandList '!insertmacro _StdU_RandList' #rand(), as in C standard library, with list support
!define StdUtils.RandBytes '!insertmacro _StdU_RandBytes' #Generates random bytes, returned as Base64-encoded string
!define StdUtils.FormatStr '!insertmacro _StdU_FormatStr' #sprintf(), as in C standard library, one '%d' placeholder
!define StdUtils.FormatStr2 '!insertmacro _StdU_FormatStr2' #sprintf(), as in C standard library, two '%d' placeholders
!define StdUtils.FormatStr3 '!insertmacro _StdU_FormatStr3' #sprintf(), as in C standard library, three '%d' placeholders
!define StdUtils.ScanStr '!insertmacro _StdU_ScanStr' #sscanf(), as in C standard library, one '%d' placeholder
!define StdUtils.ScanStr2 '!insertmacro _StdU_ScanStr2' #sscanf(), as in C standard library, two '%d' placeholders
!define StdUtils.ScanStr3 '!insertmacro _StdU_ScanStr3' #sscanf(), as in C standard library, three '%d' placeholders
!define StdUtils.TrimStr '!insertmacro _StdU_TrimStr' #Remove whitspaces from string, left and right
!define StdUtils.TrimStrLeft '!insertmacro _StdU_TrimStrLeft' #Remove whitspaces from string, left side only
!define StdUtils.TrimStrRight '!insertmacro _StdU_TrimStrRight' #Remove whitspaces from string, right side only
!define StdUtils.RevStr '!insertmacro _StdU_RevStr' #Reverse a string, e.g. "reverse me" <-> "em esrever"
!define StdUtils.ValidFileName '!insertmacro _StdU_ValidFileName' #Test whether string is a valid file name - no paths allowed
!define StdUtils.ValidPathSpec '!insertmacro _StdU_ValidPathSpec' #Test whether string is a valid full(!) path specification
!define StdUtils.ValidDomainName '!insertmacro _StdU_ValidDomain' #Test whether string is a valid host name or domain name
!define StdUtils.StrToUtf8 '!insertmacro _StdU_StrToUtf8' #Convert string from Unicode (UTF-16) or ANSI to UTF-8 bytes
!define StdUtils.StrFromUtf8 '!insertmacro _StdU_StrFromUtf8' #Convert string from UTF-8 bytes to Unicode (UTF-16) or ANSI
!define StdUtils.SHFileMove '!insertmacro _StdU_SHFileMove' #SHFileOperation(), using the FO_MOVE operation
!define StdUtils.SHFileCopy '!insertmacro _StdU_SHFileCopy' #SHFileOperation(), using the FO_COPY operation
!define StdUtils.AppendToFile '!insertmacro _StdU_AppendToFile' #Append contents of an existing file to another file
!define StdUtils.ExecShellAsUser '!insertmacro _StdU_ExecShlUser' #ShellExecute() as NON-elevated user from elevated installer
!define StdUtils.InvokeShellVerb '!insertmacro _StdU_InvkeShlVrb' #Invokes a "shell verb", e.g. for pinning items to the taskbar
!define StdUtils.ExecShellWaitEx '!insertmacro _StdU_ExecShlWaitEx' #ShellExecuteEx(), returns the handle of the new process
!define StdUtils.WaitForProcEx '!insertmacro _StdU_WaitForProcEx' #WaitForSingleObject(), e.g. to wait for a running process
!define StdUtils.GetParameter '!insertmacro _StdU_GetParameter' #Get the value of a specific command-line option
!define StdUtils.TestParameter '!insertmacro _StdU_TestParameter' #Test whether a specific command-line option has been set
!define StdUtils.ParameterCnt '!insertmacro _StdU_ParameterCnt' #Get number of command-line tokens, similar to argc in main()
!define StdUtils.ParameterStr '!insertmacro _StdU_ParameterStr' #Get the n-th command-line token, similar to argv[i] in main()
!define StdUtils.GetAllParameters '!insertmacro _StdU_GetAllParams' #Get complete command-line, but without executable name
!define StdUtils.GetRealOSVersion '!insertmacro _StdU_GetRealOSVer' #Get the *real* Windows version number, even on Windows 8.1+
!define StdUtils.GetRealOSBuildNo '!insertmacro _StdU_GetRealOSBld' #Get the *real* Windows build number, even on Windows 8.1+
!define StdUtils.GetRealOSName '!insertmacro _StdU_GetRealOSStr' #Get the *real* Windows version, as a "friendly" name
!define StdUtils.GetOSEdition '!insertmacro _StdU_GetOSEdition' #Get the Windows edition, i.e. "workstation" or "server"
!define StdUtils.GetOSReleaseId '!insertmacro _StdU_GetOSRelIdNo' #Get the Windows release identifier (on Windows 10)
!define StdUtils.VerifyOSVersion '!insertmacro _StdU_VrfyRealOSVer' #Compare *real* operating system to an expected version number
!define StdUtils.VerifyOSBuildNo '!insertmacro _StdU_VrfyRealOSBld' #Compare *real* operating system to an expected build number
!define StdUtils.HashText '!insertmacro _StdU_HashText' #Compute hash from text string (CRC32, MD5, SHA1/2/3, BLAKE2)
!define StdUtils.HashFile '!insertmacro _StdU_HashFile' #Compute hash from file (CRC32, MD5, SHA1/2/3, BLAKE2)
!define StdUtils.NormalizePath '!insertmacro _StdU_NormalizePath' #Simplifies the path to produce a direct, well-formed path
!define StdUtils.GetParentPath '!insertmacro _StdU_GetParentPath' #Get parent path by removing the last component from the path
!define StdUtils.SplitPath '!insertmacro _StdU_SplitPath' #Split the components of the given path
!define StdUtils.GetDrivePart '!insertmacro _StdU_GetDrivePart' #Get drive component of path
!define StdUtils.GetDirectoryPart '!insertmacro _StdU_GetDirPart' #Get directory component of path
!define StdUtils.GetFileNamePart '!insertmacro _StdU_GetFNamePart' #Get file name component of path
!define StdUtils.GetExtensionPart '!insertmacro _StdU_GetExtnPart' #Get file extension component of path
!define StdUtils.TimerCreate '!insertmacro _StdU_TimerCreate' #Create a new event-timer that will be triggered periodically
!define StdUtils.TimerDestroy '!insertmacro _StdU_TimerDestroy' #Destroy a running timer created with TimerCreate()
!define StdUtils.ProtectStr '!insertmacro _StdU_PrtctStr' #Protect a given String using Windows' DPAPI
!define StdUtils.UnprotectStr '!insertmacro _StdU_UnprtctStr' #Unprotect a string that was protected via ProtectStr()
!define StdUtils.GetLibVersion '!insertmacro _StdU_GetLibVersion' #Get the current StdUtils library version (for debugging)
!define StdUtils.SetVerbose '!insertmacro _StdU_SetVerbose' #Enable or disable "verbose" mode (for debugging)
#################################################################################
# MACRO DEFINITIONS
#################################################################################
!macro _StdU_Time out
StdUtils::Time /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_GetMinutes out
StdUtils::GetMinutes /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_GetHours out
StdUtils::GetHours /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_GetDays out
StdUtils::GetDays /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_Rand out
StdUtils::Rand /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_RandMax out max
push ${max}
StdUtils::RandMax /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_RandMinMax out min max
push ${min}
push ${max}
StdUtils::RandMinMax /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_RandList count max
push ${max}
push ${count}
StdUtils::RandList /NOUNLOAD
!macroend
!macro _StdU_RandBytes out count
push ${count}
StdUtils::RandBytes /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_FormatStr out format val
push `${format}`
push ${val}
StdUtils::FormatStr /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_FormatStr2 out format val1 val2
push `${format}`
push ${val1}
push ${val2}
StdUtils::FormatStr2 /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_FormatStr3 out format val1 val2 val3
push `${format}`
push ${val1}
push ${val2}
push ${val3}
StdUtils::FormatStr3 /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_ScanStr out format input default
push `${format}`
push `${input}`
push ${default}
StdUtils::ScanStr /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_ScanStr2 out1 out2 format input default1 default2
push `${format}`
push `${input}`
push ${default1}
push ${default2}
StdUtils::ScanStr2 /NOUNLOAD
pop ${out1}
pop ${out2}
!macroend
!macro _StdU_ScanStr3 out1 out2 out3 format input default1 default2 default3
push `${format}`
push `${input}`
push ${default1}
push ${default2}
push ${default3}
StdUtils::ScanStr3 /NOUNLOAD
pop ${out1}
pop ${out2}
pop ${out3}
!macroend
!macro _StdU_TrimStr var
push ${var}
StdUtils::TrimStr /NOUNLOAD
pop ${var}
!macroend
!macro _StdU_TrimStrLeft var
push ${var}
StdUtils::TrimStrLeft /NOUNLOAD
pop ${var}
!macroend
!macro _StdU_TrimStrRight var
push ${var}
StdUtils::TrimStrRight /NOUNLOAD
pop ${var}
!macroend
!macro _StdU_RevStr var
push ${var}
StdUtils::RevStr /NOUNLOAD
pop ${var}
!macroend
!macro _StdU_ValidFileName out test
push `${test}`
StdUtils::ValidFileName /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_ValidPathSpec out test
push `${test}`
StdUtils::ValidPathSpec /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_ValidDomain out test
push `${test}`
StdUtils::ValidDomainName /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_StrToUtf8 out str
push `${str}`
StdUtils::StrToUtf8 /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_StrFromUtf8 out trnc str
push ${trnc}
push `${str}`
StdUtils::StrFromUtf8 /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_SHFileMove out from to hwnd
push `${from}`
push `${to}`
push ${hwnd}
StdUtils::SHFileMove /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_SHFileCopy out from to hwnd
push `${from}`
push `${to}`
push ${hwnd}
StdUtils::SHFileCopy /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_AppendToFile out from dest offset maxlen
push `${from}`
push `${dest}`
push ${offset}
push ${maxlen}
StdUtils::AppendToFile /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_ExecShlUser out file verb args
push `${file}`
push `${verb}`
push `${args}`
StdUtils::ExecShellAsUser /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_InvkeShlVrb out path file verb_id
push "${path}"
push "${file}"
push ${verb_id}
StdUtils::InvokeShellVerb /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_ExecShlWaitEx out_res out_val file verb args
push `${file}`
push `${verb}`
push `${args}`
StdUtils::ExecShellWaitEx /NOUNLOAD
pop ${out_res}
pop ${out_val}
!macroend
!macro _StdU_WaitForProcEx out handle
push `${handle}`
StdUtils::WaitForProcEx /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_GetParameter out name default
push `${name}`
push `${default}`
StdUtils::GetParameter /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_TestParameter out name
push `${name}`
StdUtils::TestParameter /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_ParameterCnt out
StdUtils::ParameterCnt /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_ParameterStr out index
push ${index}
StdUtils::ParameterStr /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_GetAllParams out truncate
push `${truncate}`
StdUtils::GetAllParameters /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_GetRealOSVer out_major out_minor out_spack
StdUtils::GetRealOsVersion /NOUNLOAD
pop ${out_major}
pop ${out_minor}
pop ${out_spack}
!macroend
!macro _StdU_GetRealOSBld out
StdUtils::GetRealOsBuildNo /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_GetRealOSStr out
StdUtils::GetRealOsName /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_VrfyRealOSVer out major minor spack
push `${major}`
push `${minor}`
push `${spack}`
StdUtils::VerifyRealOsVersion /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_VrfyRealOSBld out build
push `${build}`
StdUtils::VerifyRealOsBuildNo /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_GetOSEdition out
StdUtils::GetOsEdition /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_GetOSRelIdNo out
StdUtils::GetOsReleaseId /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_HashText out type text
push `${type}`
push `${text}`
StdUtils::HashText /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_HashFile out type file
push `${type}`
push `${file}`
StdUtils::HashFile /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_NormalizePath out path
push `${path}`
StdUtils::NormalizePath /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_GetParentPath out path
push `${path}`
StdUtils::GetParentPath /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_SplitPath out_drive out_dir out_fname out_ext path
push `${path}`
StdUtils::SplitPath /NOUNLOAD
pop ${out_drive}
pop ${out_dir}
pop ${out_fname}
pop ${out_ext}
!macroend
!macro _StdU_GetDrivePart out path
push `${path}`
StdUtils::GetDrivePart /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_GetDirPart out path
push `${path}`
StdUtils::GetDirectoryPart /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_GetFNamePart out path
push `${path}`
StdUtils::GetFileNamePart /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_GetExtnPart out path
push `${path}`
StdUtils::GetExtensionPart /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_TimerCreate out callback interval
GetFunctionAddress ${out} ${callback}
push ${out}
push ${interval}
StdUtils::TimerCreate /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_TimerDestroy out timer_id
push ${timer_id}
StdUtils::TimerDestroy /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_PrtctStr out dpsc salt text
push `${dpsc}`
push `${salt}`
push `${text}`
StdUtils::ProtectStr /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_UnprtctStr out trnc salt data
push `${trnc}`
push `${salt}`
push `${data}`
StdUtils::UnprotectStr /NOUNLOAD
pop ${out}
!macroend
!macro _StdU_GetLibVersion out_ver out_tst
StdUtils::GetLibVersion /NOUNLOAD
pop ${out_ver}
pop ${out_tst}
!macroend
!macro _StdU_SetVerbose enable
Push ${enable}
StdUtils::SetVerboseMode /NOUNLOAD
!macroend
#################################################################################
# MAGIC NUMBERS
#################################################################################
!define StdUtils.Const.ShellVerb.PinToTaskbar 0
!define StdUtils.Const.ShellVerb.UnpinFromTaskbar 1
!define StdUtils.Const.ShellVerb.PinToStart 2
!define StdUtils.Const.ShellVerb.UnpinFromStart 3
!endif # !___STDUTILS__NSH___

View File

@ -0,0 +1,48 @@
; StrContains
; This function does a case sensitive searches for an occurrence of a substring in a string.
; It returns the substring if it is found.
; Otherwise it returns null("").
; Written by kenglish_hi
; Adapted from StrReplace written by dandaman32
Var STR_HAYSTACK
Var STR_NEEDLE
Var STR_CONTAINS_VAR_1
Var STR_CONTAINS_VAR_2
Var STR_CONTAINS_VAR_3
Var STR_CONTAINS_VAR_4
Var STR_RETURN_VAR
Function StrContains
Exch $STR_NEEDLE
Exch 1
Exch $STR_HAYSTACK
; Uncomment to debug
;MessageBox MB_OK 'STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK '
StrCpy $STR_RETURN_VAR ""
StrCpy $STR_CONTAINS_VAR_1 -1
StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE
StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK
loop:
IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1
StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1
StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found
StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done
Goto loop
found:
StrCpy $STR_RETURN_VAR $STR_NEEDLE
Goto done
done:
Pop $STR_NEEDLE ;Prevent "invalid opcode" errors and keep the
Exch $STR_RETURN_VAR
FunctionEnd
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK
Push `${HAYSTACK}`
Push `${NEEDLE}`
Call StrContains
Pop `${OUT}`
!macroend
!define StrContains '!insertmacro "_StrContainsConstructor"'

View File

@ -0,0 +1,299 @@
/*** UAC Plug-in ***
Interactive User (MediumIL) Admin user (HighIL)
***[Setup.exe]************* ***[Setup.exe]**************
* * * *
* +++[.OnInit]+++++++++++ * * +++[.OnInit]++++++++++++ *
* + UAC_RunElevated >---+-+----> * + + *
* + NSIS.Quit + * * + + *
* +++++++++++++++++++++++ * * ++++++++++++++++++++++++ *
* * * *
* * * *
* +++[Section]+++++++++++ * * +++[Section]++++++++++++ *
* + + * /--+-+-<UAC_AsUser_ExecShell+ *
* +++++++++++++++++++++++ * | * ++++++++++++++++++++++++ *
* * | * *
* Win32.ShellExecute <---+--/ * *
* * * *
*************************** ****************************
*/
!ifndef UAC_HDR__INC
!verbose push
!verbose 3
!ifndef UAC_VERBOSE
!define UAC_VERBOSE 3
!endif
!verbose ${UAC_VERBOSE}
!define UAC_HDR__INC 0x00020400 ;MMmmbbrr
!include LogicLib.nsh
/* UAC_RunElevated
**
** Starts the elevation operation.
**
** Return values:
**
** $0: Win32 error code (0 on success, 1223 if user aborted elevation dialog, anything else should be treated as a fatal error)
** $1: If $0==0:
** 0 UAC is not supported by the OS
** 1 Started a elevated child process, the current process should act like a wrapper (Call Quit without any further processing)
** 2 The process is already running @ HighIL (Member of admin group)
** 3 You should call RunElevated again (This can happen if a user without admin priv. is used in the runas dialog)
** $2: If $0==0 && $1==1: ExitCode of the elevated fork process (The NSIS errlvl is also set)
** $3: If $0==0: 1 if the user is a member of the admin group or 0 otherwise
**/
!macro UAC_RunElevated
UAC::_ 0
!macroend
!macro UAC_PageElevation_RunElevated
UAC::_ 0
!macroend
/*!macro UAC_OnInitElevation_RunElevated
UAC::_ 0
!macroend
!macro UAC_OnInitElevation_OnGuiInit
!macroend*/
/* UAC_GetIntegrityLevel <NSISVar:Output | "s">
**
** Get integrity level of current process
**
**/
!macro UAC_GetIntegrityLevel outvar
UAC::_ 6
!if "${outvar}" != "s"
Pop ${outvar}
!endif
!macroend
/* UAC_IsAdmin
**
** Is the current process running with administrator privileges? Result in $0
**
** ${If} ${UAC_IsAdmin} ...
**
**/
!macro UAC_IsAdmin
UAC::_ 2
!macroend
!define UAC_IsAdmin `"" UAC_IsAdmin ""`
!macro _UAC_IsAdmin _a _b _t _f
!insertmacro _UAC_MakeLL_Cmp _!= 0 2s
!macroend
/* UAC_IsInnerInstance
**
** Does the current process have a NSIS/UAC parent process that is part of the elevation operation?
**
** ${If} ${UAC_IsInnerInstance} ...
**
**/
!macro UAC_IsInnerInstance
UAC::_ 3
!macroend
!define UAC_IsInnerInstance `"" UAC_IsInnerInstance ""`
!macro _UAC_IsInnerInstance _a _b _t _f
!insertmacro _UAC_MakeLL_Cmp _!= 0 3s
!macroend
/* UAC_PageElevation_OnInit, UAC_PageElevation_OnGuiInit,
**
** Helper macros for elevation on a custom elevation page, see the DualMode example for more information.
**
**/
!macro UAC_Notify_OnGuiInit
UAC::_ 4
!macroend
!macro UAC_PageElevation_OnGuiInit
!insertmacro UAC_Notify_OnGuiInit
!macroend
!macro UAC_PageElevation_OnInit
UAC::_ 5
${IfThen} ${Errors} ${|} Quit ${|}
!macroend
/* UAC_AsUser_Call <Function|Label> <NSISAddressName> <UAC_* flags>
**
** Calls a function or label in the user process instance.
** All the UAC_AsUser_* macros use this helper macro.
**
**/
!define UAC_SYNCREGISTERS 0x1
;define UAC_SYNCSTACK 0x2
!define UAC_SYNCOUTDIR 0x4
!define UAC_SYNCINSTDIR 0x8
;define UAC_CLEARERRFLAG 0x10
!macro UAC_AsUser_Call type name flags
push $0
Get${type}Address $0 ${name}
!verbose push
!verbose ${UAC_VERBOSE}
!insertmacro _UAC_ParseDefineFlagsToInt _UAC_AsUser_Call__flags ${flags}
!verbose pop
StrCpy $0 "1$0:${_UAC_AsUser_Call__flags}"
!undef _UAC_AsUser_Call__flags
Exch $0
UAC::_
!macroend
/*
** UAC_AsUser_GetSection <Flags|InstTypes|Size|Text> <SectionIndex> <NSISVar:Output>
*/
!macro UAC_AsUser_GetSection secprop secidx outvar
!insertmacro _UAC_AsUser_GenOp ${outvar} SectionGet${secprop} ${secidx} ""
!macroend
/*
** UAC_AsUser_GetGlobalVar <NSISVar:SourceAndOutput>
** UAC_AsUser_GetGlobal <NSISVar:Output> <NSISVar:Source>
*/
!macro UAC_AsUser_GetGlobalVar var
!insertmacro _UAC_AsUser_GenOp ${var} StrCpy "" ${var}
!macroend
!macro UAC_AsUser_GetGlobal outvar srcvar
!insertmacro _UAC_AsUser_GenOp ${outvar} StrCpy "" ${srcvar}
!macroend
/*
** UAC_AsUser_ExecShell <Verb> <ApplicationOrFile> <Parameters> <Working Directory> <SW_*>
**
** Call ExecShell in the user process instance.
**
*/
!macro UAC_AsUser_ExecShell verb command params workdir show
!insertmacro _UAC_IncL
goto _UAC_L_E_${__UAC_L}
_UAC_L_F_${__UAC_L}:
ExecShell "${verb}" "${command}" '${params}' ${show}
return
_UAC_L_E_${__UAC_L}:
!if "${workdir}" != ""
push $outdir
SetOutPath "${workdir}"
!endif
!insertmacro UAC_AsUser_Call Label _UAC_L_F_${__UAC_L} ${UAC_SYNCREGISTERS}|${UAC_SYNCOUTDIR}|${UAC_SYNCINSTDIR} #|${UAC_CLEARERRFLAG}
!if "${workdir}" != ""
pop $outdir
SetOutPath $outdir
!endif
!macroend
!macro _UAC_MakeLL_Cmp cmpop cmp pluginparams
!insertmacro _LOGICLIB_TEMP
UAC::_ ${pluginparams}
pop $_LOGICLIB_TEMP
!insertmacro ${cmpop} $_LOGICLIB_TEMP ${cmp} `${_t}` `${_f}`
!macroend
!macro _UAC_definemath def val1 op val2
!define /math _UAC_definemath "${val1}" ${op} ${val2}
!ifdef ${def}
!undef ${def}
!endif
!define ${def} "${_UAC_definemath}"
!undef _UAC_definemath
!macroend
!macro _UAC_ParseDefineFlags_orin parse outflags
!searchparse /noerrors ${${parse}} "" _UAC_ParseDefineFlags_orin_f1 "|" _UAC_ParseDefineFlags_orin_f2
!define _UAC_ParseDefineFlags_orin_this ${_UAC_ParseDefineFlags_orin_f1}
!undef ${parse}
!define ${parse} ${_UAC_ParseDefineFlags_orin_f2}
!define _UAC_ParseDefineFlags_orin_saveout ${${outflags}}
!undef ${outflags}
!define /math ${outflags} "${_UAC_ParseDefineFlags_orin_saveout}" | "${_UAC_ParseDefineFlags_orin_this}"
!undef _UAC_ParseDefineFlags_orin_saveout
!undef _UAC_ParseDefineFlags_orin_this
!ifdef _UAC_ParseDefineFlags_orin_f1
!undef _UAC_ParseDefineFlags_orin_f1
!endif
!ifdef _UAC_ParseDefineFlags_orin_f2
!undef _UAC_ParseDefineFlags_orin_f2
!endif
!macroend
!macro _UAC_ParseDefineFlags_Begin _outdef _in
!define _UAC_PDF${_outdef}_parse "${_in}"
!define _UAC_PDF${_outdef}_flags ""
!define _UAC_PDF${_outdef}_r 0
!insertmacro _UAC_ParseDefineFlags_orin _UAC_PDF${_outdef}_parse _UAC_PDF${_outdef}_flags ;0x1
!insertmacro _UAC_ParseDefineFlags_orin _UAC_PDF${_outdef}_parse _UAC_PDF${_outdef}_flags ;0x2
!insertmacro _UAC_ParseDefineFlags_orin _UAC_PDF${_outdef}_parse _UAC_PDF${_outdef}_flags ;0x4
!insertmacro _UAC_ParseDefineFlags_orin _UAC_PDF${_outdef}_parse _UAC_PDF${_outdef}_flags ;0x8
!insertmacro _UAC_ParseDefineFlags_orin _UAC_PDF${_outdef}_parse _UAC_PDF${_outdef}_flags ;0x10
!macroend
!macro _UAC_ParseDefineFlags_End _outdef
!define ${_outdef} ${_UAC_PDF${_outdef}_r}
!undef _UAC_PDF${_outdef}_r
!undef _UAC_PDF${_outdef}_flags
!undef _UAC_PDF${_outdef}_parse
!macroend
!macro _UAC_ParseDefineFlags_IncludeFlag _outdef flag
!if ${_UAC_PDF${_outdef}_flags} & ${flag}
!insertmacro _UAC_definemath _UAC_PDF${_outdef}_r ${_UAC_PDF${_outdef}_r} | ${flag}
!endif
!macroend
!macro _UAC_ParseDefineFlagsToInt _outdef _in
!insertmacro _UAC_ParseDefineFlags_Begin _UAC_ParseDefineFlagsToInt_tmp "${_in}"
!define ${_outdef} ${_UAC_PDF_UAC_ParseDefineFlagsToInt_tmp_flags}
!insertmacro _UAC_ParseDefineFlags_End _UAC_ParseDefineFlagsToInt_tmp
!undef _UAC_ParseDefineFlagsToInt_tmp
!macroend
!macro _UAC_IncL
!insertmacro _UAC_definemath __UAC_L "${__UAC_L}" + 1
!macroend
!macro _UAC_AsUser_GenOp outvar op opparam1 opparam2
!define _UAC_AUGOGR_ID _UAC_AUGOGR_OP${outvar}${op}${opparam1}${opparam2}
!ifndef ${_UAC_AUGOGR_ID} ;Has this exact action been done before?
!if ${outvar} == $0
!define ${_UAC_AUGOGR_ID} $1
!else
!define ${_UAC_AUGOGR_ID} $0
!endif
!if "${opparam1}" == ""
!define _UAC_AUGOGR_OPP1 ${${_UAC_AUGOGR_ID}}
!define _UAC_AUGOGR_OPP2 ${opparam2}
!else
!define _UAC_AUGOGR_OPP1 ${opparam1}
!define _UAC_AUGOGR_OPP2 ${${_UAC_AUGOGR_ID}}
!endif
goto ${_UAC_AUGOGR_ID}_C
${_UAC_AUGOGR_ID}_F:
${op} ${_UAC_AUGOGR_OPP1} ${_UAC_AUGOGR_OPP2}
return
${_UAC_AUGOGR_ID}_C:
!undef _UAC_AUGOGR_OPP1
!undef _UAC_AUGOGR_OPP2
!endif
push ${${_UAC_AUGOGR_ID}}
!insertmacro UAC_AsUser_Call Label ${_UAC_AUGOGR_ID}_F ${UAC_SYNCREGISTERS}
StrCpy ${outvar} ${${_UAC_AUGOGR_ID}}
pop ${${_UAC_AUGOGR_ID}}
!undef _UAC_AUGOGR_ID
!macroend
!verbose pop
!endif /* UAC_HDR__INC */

View File

@ -0,0 +1,77 @@
!include "nsProcess.nsh"
!ifmacrondef customCheckAppRunning
!include "getProcessInfo.nsh"
Var pid
!endif
# http://nsis.sourceforge.net/Allow_only_one_installer_instance
!macro ALLOW_ONLY_ONE_INSTALLER_INSTANCE
BringToFront
!define /ifndef SYSTYPE_PTR p ; NSIS v3.0+
System::Call 'kernel32::CreateMutex(${SYSTYPE_PTR}0, i1, t"${APP_GUID}")?e'
Pop $0
IntCmpU $0 183 0 launch launch ; ERROR_ALREADY_EXISTS
StrLen $0 "$(^SetupCaption)"
IntOp $0 $0 + 1 ; GetWindowText count includes \0
StrCpy $1 "" ; Start FindWindow with NULL
loop:
FindWindow $1 "#32770" "" "" $1
StrCmp 0 $1 notfound
System::Call 'user32::GetWindowText(${SYSTYPE_PTR}r1, t.r2, ir0)'
StrCmp $2 "$(^SetupCaption)" 0 loop
SendMessage $1 0x112 0xF120 0 /TIMEOUT=2000 ; WM_SYSCOMMAND:SC_RESTORE to restore the window if it is minimized
System::Call "user32::SetForegroundWindow(${SYSTYPE_PTR}r1)"
notfound:
Abort
launch:
!macroend
!macro CHECK_APP_RUNNING
!ifmacrodef customCheckAppRunning
!insertmacro customCheckAppRunning
!else
!insertmacro _CHECK_APP_RUNNING
!endif
!macroend
!macro _CHECK_APP_RUNNING
${GetProcessInfo} 0 $pid $1 $2 $3 $4
${if} $3 != "${APP_EXECUTABLE_FILENAME}"
${if} ${isUpdated}
# allow app to exit without explicit kill
Sleep 300
${endIf}
${nsProcess::FindProcess} "${APP_EXECUTABLE_FILENAME}" $R0
${if} $R0 == 0
${if} ${isUpdated}
# allow app to exit without explicit kill
Sleep 1000
Goto doStopProcess
${endIf}
MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "$(appRunning)" /SD IDOK IDOK doStopProcess
Quit
doStopProcess:
DetailPrint `Closing running "${PRODUCT_NAME}"...`
# https://github.com/electron-userland/electron-builder/issues/2516#issuecomment-372009092
nsExec::Exec `taskkill /t /im "${APP_EXECUTABLE_FILENAME}" /fi "PID ne $pid"` $R0
# to ensure that files are not "in-use"
Sleep 300
${nsProcess::FindProcess} "${APP_EXECUTABLE_FILENAME}" $R0
${if} $R0 == 0
# wait to give a chance to exit gracefully
Sleep 1000
nsExec::Exec `taskkill /f /t /im "${APP_EXECUTABLE_FILENAME}" /fi "PID ne $pid"` $R0
${If} $R0 != 0
DetailPrint `Waiting for "${PRODUCT_NAME}" to close (taskkill exit code $R0).`
Sleep 2000
${endIf}
${endIf}
${endIf}
${endIf}
!macroend

View File

@ -0,0 +1,91 @@
!macro extractEmbeddedAppPackage
!ifdef COMPRESS
SetCompress off
!endif
Var /GLOBAL packageArch
!ifdef APP_64
!ifdef APP_ARM64
StrCpy $packageArch "ARM64"
!else
StrCpy $packageArch "64"
!endif
!insertmacro compute_files_for_current_arch
!else
!insertmacro ia32_app_files
!endif
!ifdef COMPRESS
SetCompress "${COMPRESS}"
!endif
!ifdef ZIP_COMPRESSION
nsisunz::Unzip "$PLUGINSDIR\app-$packageArch.zip" "$INSTDIR"
!else
!insertmacro extractUsing7za "$PLUGINSDIR\app-$packageArch.7z"
!endif
# after decompression
${if} $packageArch == "ARM64"
!ifmacrodef customFiles_arm64
!insertmacro customFiles_arm64
!endif
${elseif} $packageArch == "64"
!ifmacrodef customFiles_x64
!insertmacro customFiles_x64
!endif
${else}
!ifmacrodef customFiles_ia32
!insertmacro customFiles_ia32
!endif
${endIf}
!macroend
!macro compute_files_for_current_arch
!ifdef APP_32
!ifdef APP_ARM64
${if} ${IsNativeARM64}
!insertmacro arm64_app_files
${elseif} ${RunningX64}
!insertmacro x64_app_files
${else}
!insertmacro ia32_app_files
${endIf}
!else
${if} ${RunningX64}
!insertmacro x64_app_files
${else}
!insertmacro ia32_app_files
${endIf}
!endif
!else
!ifdef APP_ARM64
${if} ${IsNativeARM64}
!insertmacro arm64_app_files
${else}
!insertmacro x64_app_files
${endIf}
!else
!insertmacro x64_app_files
!endif
!endif
!macroend
!macro arm64_app_files
File /oname=$PLUGINSDIR\app-arm64.${COMPRESSION_METHOD} "${APP_ARM64}"
!macroend
!macro x64_app_files
File /oname=$PLUGINSDIR\app-64.${COMPRESSION_METHOD} "${APP_64}"
!macroend
!macro ia32_app_files
StrCpy $packageArch "32"
File /oname=$PLUGINSDIR\app-32.${COMPRESSION_METHOD} "${APP_32}"
!macroend
!macro extractUsing7za FILE
Nsis7z::Extract "${FILE}"
!macroend

View File

@ -0,0 +1,157 @@
; NSIS PROCESS INFO LIBRARY - GetProcessInfo.nsh
; Version 1.1 - Mar 28th, 2011
;
; Description:
; Gets process information.
;
; Usage example:
; ${GetProcessInfo} 0 $0 $1 $2 $3 $4
; DetailPrint "pid=$0 parent_pid=$1 priority=$2 process_name=$3 exe=$4"
;
; History:
; 1.1 - 28/03/2011 - Added uninstall function, include guards, file header. Fixed getting full exe path on pre vista systems. (Sergius)
;
!ifndef GETPROCESSINFO_INCLUDED
!define GETPROCESSINFO_INCLUDED
!define PROCESSINFO.TH32CS_SNAPPROCESS 2
!define PROCESSINFO.INVALID_HANDLE_VALUE -1
!define GetProcessInfo '!insertmacro GetProcessInfo'
;@in pid_in - if 0 - get current process info
;@out pid_out - real process id (may be useful, if pid_in=0)
;@out ppid - parent process id
;@out priority
;@out name - name of process
;@out fullname - fully-qualified path of process
!macro GetProcessInfo pid_in pid_out ppid priority name fullname
Push ${pid_in}
!ifdef BUILD_UNINSTALLER
Call un._GetProcessInfo
!else
Call _GetProcessInfo
!endif
;name;pri;ppid;fname;pid;
Pop ${name}
Pop ${priority}
Pop ${ppid}
Pop ${fullname}
Pop ${pid_out}
!macroend
!macro FUNC_GETPROCESSINFO
Exch $R3 ;pid
Push $0
Push $1
Push $2
Push $3
Push $4
Push $5
Push $R0 ;hSnapshot
Push $R1 ;result
Push $R9 ;PROCESSENTRY32;MODULEENTRY32 and so on
Push $R8
;zero registers to waste trash, if error occurred
StrCpy $0 ""
StrCpy $1 ""
StrCpy $2 ""
StrCpy $3 ""
StrCpy $4 ""
StrCpy $5 ""
IntCmp $R3 0 0 skip_pid_detection skip_pid_detection
System::Call 'kernel32::GetCurrentProcess() i.R0'
System::Call "Kernel32::GetProcessId(i R0) i.R3"
skip_pid_detection:
System::Call 'Kernel32::CreateToolhelp32Snapshot(i ${PROCESSINFO.TH32CS_SNAPPROCESS},i R3) i.R0'
IntCmp $R0 ${PROCESSINFO.INVALID_HANDLE_VALUE} end ;someting wrong
;$R9=PROCESSENTRY32
;typedef struct tagPROCESSENTRY32 {
; DWORD dwSize;
; DWORD cntUsage;
; DWORD th32ProcessID;
; ULONG_PTR th32DefaultHeapID;
; DWORD th32ModuleID;
; DWORD cntThreads;
; DWORD th32ParentProcessID;
; LONG pcPriClassBase;
; DWORD dwFlags;
; TCHAR szExeFile[MAX_PATH];
;}PROCESSENTRY32, *PPROCESSENTRY32;
;dwSize=4*9+2*260
System::Alloc 1024
pop $R9
System::Call "*$R9(i 556)"
System::Call 'Kernel32::Process32FirstW(i R0, i $R9) i.R1'
StrCmp $R1 0 end
nnext_iteration:
System::Call "*$R9(i,i,i.R1)" ;get PID
IntCmp $R1 $R3 exitloop
System::Call 'Kernel32::Process32NextW(i R0, i $R9) i.R1'
IntCmp $R1 0 0 nnext_iteration nnext_iteration
exitloop:
;$0 - pid
;$1 - threads
;$2 - ppid
;$3 - priority
;$4 - process name
System::Call "*$R9(i,i,i.r0,i,i,i.r1,i.r2,i.r3,i,&w256.r4)" ; Get next module
;free:
System::Free $R9
System::Call "Kernel32::CloseToolhelp32Snapshot(i R0)"
;===============
;now get full path and commandline
System::Call "Kernel32::OpenProcess(i 1040, i 0, i r0)i .R0"
StrCmp $R0 0 end
IntOp $R8 0 + 256
System::Call "psapi::GetModuleFileNameExW(i R0,i 0,t .r5, *i $R8)i .R1"
end:
Pop $R8
Pop $R9
Pop $R1
Pop $R0
Exch $5
Exch 1
Exch $4
Exch 2
Exch $3
Exch 3
Exch $2
Exch 4
Pop $1
Exch 4
Exch $0
Exch 5
Pop $R3
!macroend ;FUNC_GETPROCESSINFO
!ifndef BUILD_UNINSTALLER
Function _GetProcessInfo
!insertmacro FUNC_GETPROCESSINFO
FunctionEnd
!endif
!ifdef BUILD_UNINSTALLER
Function un._GetProcessInfo
!insertmacro FUNC_GETPROCESSINFO
FunctionEnd
!endif
!endif ;GETPROCESSINFO_INCLUDED

View File

@ -0,0 +1,192 @@
!macro moveFile FROM TO
ClearErrors
Rename `${FROM}` `${TO}`
${if} ${errors}
# not clear - can NSIS rename on another drive or not, so, in case of error, just copy
ClearErrors
!insertmacro copyFile `${FROM}` `${TO}`
Delete `${FROM}`
${endif}
!macroend
!macro copyFile FROM TO
${StdUtils.GetParentPath} $R5 `${TO}`
CreateDirectory `$R5`
ClearErrors
CopyFiles /SILENT `${FROM}` `${TO}`
!macroend
Function GetInQuotes
Exch $R0
Push $R1
Push $R2
Push $R3
StrCpy $R2 -1
IntOp $R2 $R2 + 1
StrCpy $R3 $R0 1 $R2
StrCmp $R3 "" 0 +3
StrCpy $R0 ""
Goto Done
StrCmp $R3 '"' 0 -5
IntOp $R2 $R2 + 1
StrCpy $R0 $R0 "" $R2
StrCpy $R2 0
IntOp $R2 $R2 + 1
StrCpy $R3 $R0 1 $R2
StrCmp $R3 "" 0 +3
StrCpy $R0 ""
Goto Done
StrCmp $R3 '"' 0 -5
StrCpy $R0 $R0 $R2
Done:
Pop $R3
Pop $R2
Pop $R1
Exch $R0
FunctionEnd
!macro GetInQuotes Var Str
Push "${Str}"
Call GetInQuotes
Pop "${Var}"
!macroend
Function GetFileParent
Exch $R0
Push $R1
Push $R2
Push $R3
StrCpy $R1 0
StrLen $R2 $R0
loop:
IntOp $R1 $R1 + 1
IntCmp $R1 $R2 get 0 get
StrCpy $R3 $R0 1 -$R1
StrCmp $R3 "\" get
Goto loop
get:
StrCpy $R0 $R0 -$R1
Pop $R3
Pop $R2
Pop $R1
Exch $R0
FunctionEnd
Var /GLOBAL isTryToKeepShortcuts
!macro setIsTryToKeepShortcuts
StrCpy $isTryToKeepShortcuts "true"
!ifdef allowToChangeInstallationDirectory
${ifNot} ${isUpdated}
StrCpy $isTryToKeepShortcuts "false"
${endIf}
!endif
!macroend
# https://nsis-dev.github.io/NSIS-Forums/html/t-172971.html
!macro readReg VAR ROOT_KEY SUB_KEY NAME
${if} "${ROOT_KEY}" == "SHELL_CONTEXT"
ReadRegStr "${VAR}" SHELL_CONTEXT "${SUB_KEY}" "${NAME}"
${elseif} "${ROOT_KEY}" == "HKEY_CURRENT_USER"
ReadRegStr "${VAR}" HKEY_CURRENT_USER "${SUB_KEY}" "${NAME}"
${elseif} "${ROOT_KEY}" == "HKEY_LOCAL_MACHINE"
ReadRegStr "${VAR}" HKEY_LOCAL_MACHINE "${SUB_KEY}" "${NAME}"
${else}
MessageBox MB_OK "Unsupported ${ROOT_KEY}"
${endif}
!macroend
# http://stackoverflow.com/questions/24595887/waiting-for-nsis-uninstaller-to-finish-in-nsis-installer-either-fails-or-the-uni
Function uninstallOldVersion
Var /GLOBAL uninstallerFileName
Var /Global uninstallerFileNameTemp
Var /GLOBAL installationDir
Var /GLOBAL uninstallString
Var /GLOBAL rootKey
ClearErrors
Exch $rootKey
!insertmacro readReg $uninstallString "$rootKey" "${UNINSTALL_REGISTRY_KEY}" UninstallString
${if} $uninstallString == ""
!ifdef UNINSTALL_REGISTRY_KEY_2
!insertmacro readReg $uninstallString "$rootKey" "${UNINSTALL_REGISTRY_KEY_2}" UninstallString
!endif
${if} $uninstallString == ""
Goto Done
${endif}
${endif}
# uninstaller should be copied out of app installation dir (because this dir will be deleted), so, extract uninstaller file name
!insertmacro GetInQuotes $uninstallerFileName "$uninstallString"
!insertmacro readReg $installationDir "$rootKey" "${INSTALL_REGISTRY_KEY}" InstallLocation
${if} $installationDir == ""
${andIf} $uninstallerFileName != ""
# https://github.com/electron-userland/electron-builder/issues/735#issuecomment-246918567
Push $uninstallerFileName
Call GetFileParent
Pop $installationDir
${endif}
${if} $installationDir == ""
${andIf} $uninstallerFileName == ""
Goto Done
${endif}
${if} $installMode == "CurrentUser"
${orIf} $rootKey == "HKEY_CURRENT_USER"
StrCpy $0 "/currentuser"
${else}
StrCpy $0 "/allusers"
${endif}
!insertMacro setIsTryToKeepShortcuts
${if} $isTryToKeepShortcuts == "true"
!insertmacro readReg $R5 "$rootKey" "${INSTALL_REGISTRY_KEY}" KeepShortcuts
# if true, it means that old uninstaller supports --keep-shortcuts flag
${if} $R5 == "true"
${andIf} ${FileExists} "$appExe"
StrCpy $0 "$0 --keep-shortcuts"
${endIf}
${endIf}
${if} ${isDeleteAppData}
StrCpy $0 "$0 --delete-app-data"
${else}
# always pass --updated flag - to ensure that if DELETE_APP_DATA_ON_UNINSTALL is defined, user data will be not removed
StrCpy $0 "$0 --updated"
${endif}
StrCpy $uninstallerFileNameTemp "$PLUGINSDIR\old-uninstaller.exe"
!insertmacro copyFile "$uninstallerFileName" "$uninstallerFileNameTemp"
ExecWait '"$uninstallerFileNameTemp" /S /KEEP_APP_DATA $0 _?=$installationDir' $R0
ifErrors 0 ExecErrorHandler
# the execution failed - might have been caused by some group policy restrictions
# we try to execute the uninstaller in place
ExecWait '"$uninstallerFileName" /S /KEEP_APP_DATA $0 _?=$installationDir' $R0
ifErrors 0 ExecErrorHandler
# this also failed...
DetailPrint `Aborting, uninstall was not successful. Not able to launch uninstaller!`
ExecErrorHandler:
${if} $R0 != 0
DetailPrint `Aborting, uninstall was not successful. Uninstaller error code: $R0.`
${endif}
Done:
FunctionEnd
!macro uninstallOldVersion ROOT_KEY
Push "${ROOT_KEY}"
Call uninstallOldVersion
!macroend

View File

@ -0,0 +1,227 @@
# functions (nsis macro) for installer
!include "extractAppPackage.nsh"
!ifdef APP_PACKAGE_URL
!include webPackage.nsh
!endif
!macro installApplicationFiles
!ifdef APP_BUILD_DIR
File /r "${APP_BUILD_DIR}\*.*"
!else
!ifdef APP_PACKAGE_URL
Var /GLOBAL packageFile
Var /GLOBAL isPackageFileExplicitlySpecified
${StdUtils.GetParameter} $packageFile "package-file" ""
${if} $packageFile == ""
!ifdef APP_64_NAME
!ifdef APP_32_NAME
!ifdef APP_ARM64_NAME
${if} ${IsNativeARM64}
StrCpy $packageFile "${APP_ARM64_NAME}"
StrCpy $1 "${APP_ARM64_HASH}"
${elseif} ${IsNativeAMD64}
StrCpy $packageFile "${APP_64_NAME}"
StrCpy $1 "${APP_64_HASH}"
${else}
StrCpy $packageFile "${APP_32_NAME}"
StrCpy $1 "${APP_32_HASH}"
${endif}
!else
${if} ${RunningX64}
StrCpy $packageFile "${APP_64_NAME}"
StrCpy $1 "${APP_64_HASH}"
${else}
StrCpy $packageFile "${APP_32_NAME}"
StrCpy $1 "${APP_32_HASH}"
${endif}
!endif
!else
StrCpy $packageFile "${APP_64_NAME}"
StrCpy $1 "${APP_64_HASH}"
!endif
!else
StrCpy $packageFile "${APP_32_NAME}"
StrCpy $1 "${APP_32_HASH}"
!endif
StrCpy $4 "$packageFile"
StrCpy $packageFile "$EXEDIR/$packageFile"
StrCpy $isPackageFileExplicitlySpecified "false"
${else}
StrCpy $isPackageFileExplicitlySpecified "true"
${endIf}
# we do not check file hash is specifed explicitly using --package-file because it is clear that user definitely want to use this file and it is user responsibility to check
# 1. auto-updater uses --package-file and validates checksum
# 2. user can user another package file (use case - one installer suitable for any app version (use latest version))
${if} ${FileExists} "$packageFile"
${if} $isPackageFileExplicitlySpecified == "true"
Goto fun_extract
${else}
${StdUtils.HashFile} $3 "SHA2-512" "$packageFile"
${if} $3 == $1
Goto fun_extract
${else}
MessageBox MB_OK "Package file $4 found locally, but checksum doesn't match — expected $1, actual $3.$\r$\nLocal file is ignored and package will be downloaded from Internet."
${endIf}
${endIf}
${endIf}
!insertmacro downloadApplicationFiles
fun_extract:
!insertmacro extractUsing7za "$packageFile"
# electron always uses per user app data
${if} $installMode == "all"
SetShellVarContext current
${endif}
!insertmacro moveFile "$packageFile" "$LOCALAPPDATA\${APP_PACKAGE_STORE_FILE}"
${if} $installMode == "all"
SetShellVarContext all
${endif}
!else
!insertmacro extractEmbeddedAppPackage
# electron always uses per user app data
${if} $installMode == "all"
SetShellVarContext current
${endif}
!insertmacro copyFile "$EXEPATH" "$LOCALAPPDATA\${APP_INSTALLER_STORE_FILE}"
${if} $installMode == "all"
SetShellVarContext all
${endif}
!endif
!endif
File "/oname=${UNINSTALL_FILENAME}" "${UNINSTALLER_OUT_FILE}"
!macroend
!macro registryAddInstallInfo
WriteRegStr SHELL_CONTEXT "${INSTALL_REGISTRY_KEY}" InstallLocation "$INSTDIR"
WriteRegStr SHELL_CONTEXT "${INSTALL_REGISTRY_KEY}" KeepShortcuts "true"
WriteRegStr SHELL_CONTEXT "${INSTALL_REGISTRY_KEY}" ShortcutName "${SHORTCUT_NAME}"
!ifdef MENU_FILENAME
WriteRegStr SHELL_CONTEXT "${INSTALL_REGISTRY_KEY}" MenuDirectory "${MENU_FILENAME}"
!endif
${if} $installMode == "all"
StrCpy $0 "/allusers"
StrCpy $1 ""
${else}
StrCpy $0 "/currentuser"
StrCpy $1 ""
${endIf}
WriteRegStr SHELL_CONTEXT "${UNINSTALL_REGISTRY_KEY}" DisplayName "${UNINSTALL_DISPLAY_NAME}$1"
# https://github.com/electron-userland/electron-builder/issues/750
StrCpy $2 "$INSTDIR\${UNINSTALL_FILENAME}"
WriteRegStr SHELL_CONTEXT "${UNINSTALL_REGISTRY_KEY}" UninstallString '"$2" $0'
WriteRegStr SHELL_CONTEXT "${UNINSTALL_REGISTRY_KEY}" QuietUninstallString '"$2" $0 /S'
WriteRegStr SHELL_CONTEXT "${UNINSTALL_REGISTRY_KEY}" "DisplayVersion" "${VERSION}"
!ifdef UNINSTALLER_ICON
WriteRegStr SHELL_CONTEXT "${UNINSTALL_REGISTRY_KEY}" "DisplayIcon" "$INSTDIR\uninstallerIcon.ico"
!else
WriteRegStr SHELL_CONTEXT "${UNINSTALL_REGISTRY_KEY}" "DisplayIcon" "$appExe,0"
!endif
!ifdef COMPANY_NAME
WriteRegStr SHELL_CONTEXT "${UNINSTALL_REGISTRY_KEY}" "Publisher" "${COMPANY_NAME}"
!endif
WriteRegDWORD SHELL_CONTEXT "${UNINSTALL_REGISTRY_KEY}" NoModify 1
WriteRegDWORD SHELL_CONTEXT "${UNINSTALL_REGISTRY_KEY}" NoRepair 1
# allow user to define ESTIMATED_SIZE to avoid GetSize call
!ifdef ESTIMATED_SIZE
IntFmt $0 "0x%08X" ${ESTIMATED_SIZE}
!else
${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
IntFmt $0 "0x%08X" $0
!endif
WriteRegDWORD SHELL_CONTEXT "${UNINSTALL_REGISTRY_KEY}" "EstimatedSize" "$0"
!macroend
!macro cleanupOldMenuDirectory
${if} $oldMenuDirectory != ""
!ifdef MENU_FILENAME
${if} $oldMenuDirectory != "${MENU_FILENAME}"
RMDir "$SMPROGRAMS\$oldMenuDirectory"
${endIf}
!else
RMDir "$SMPROGRAMS\$oldMenuDirectory"
!endif
${endIf}
!macroend
!macro createMenuDirectory
!ifdef MENU_FILENAME
CreateDirectory "$SMPROGRAMS\${MENU_FILENAME}"
ClearErrors
!endif
!macroend
!macro addStartMenuLink keepShortcuts
!ifndef DO_NOT_CREATE_START_MENU_SHORTCUT
# The keepShortcuts mechanism is NOT enabled.
# Menu shortcut will be recreated.
${if} $keepShortcuts == "false"
!insertmacro cleanupOldMenuDirectory
!insertmacro createMenuDirectory
CreateShortCut "$newStartMenuLink" "$appExe" "" "$appExe" 0 "" "" "${APP_DESCRIPTION}"
# clear error (if shortcut already exists)
ClearErrors
WinShell::SetLnkAUMI "$newStartMenuLink" "${APP_ID}"
# The keepShortcuts mechanism IS enabled.
# The menu shortcut could either not exist (it shouldn't be recreated) or exist in an obsolete location.
${elseif} $oldStartMenuLink != $newStartMenuLink
${andIf} ${FileExists} "$oldStartMenuLink"
!insertmacro createMenuDirectory
Rename $oldStartMenuLink $newStartMenuLink
WinShell::UninstShortcut "$oldStartMenuLink"
WinShell::SetLnkAUMI "$newStartMenuLink" "${APP_ID}"
!insertmacro cleanupOldMenuDirectory
${endIf}
!endif
!macroend
!macro addDesktopLink keepShortcuts
!ifndef DO_NOT_CREATE_DESKTOP_SHORTCUT
# https://github.com/electron-userland/electron-builder/pull/1432
${ifNot} ${isNoDesktopShortcut}
# The keepShortcuts mechanism is NOT enabled.
# Shortcuts will be recreated.
${if} $keepShortcuts == "false"
CreateShortCut "$newDesktopLink" "$appExe" "" "$appExe" 0 "" "" "${APP_DESCRIPTION}"
ClearErrors
WinShell::SetLnkAUMI "$newDesktopLink" "${APP_ID}"
# The keepShortcuts mechanism IS enabled.
# The desktop shortcut could exist in an obsolete location (due to name change).
${elseif} $oldDesktopLink != $newDesktopLink
${orIf} ${FileExists} "$oldDesktopLink"
Rename $oldDesktopLink $newDesktopLink
WinShell::UninstShortcut "$oldDesktopLink"
WinShell::SetLnkAUMI "$newDesktopLink" "${APP_ID}"
!ifdef RECREATE_DESKTOP_SHORTCUT
${elseif} $oldDesktopLink != $newDesktopLink
${orIfNot} ${FileExists} "$oldDesktopLink"
${ifNot} ${isUpdated}
CreateShortCut "$newDesktopLink" "$appExe" "" "$appExe" 0 "" "" "${APP_DESCRIPTION}"
ClearErrors
WinShell::SetLnkAUMI "$newDesktopLink" "${APP_ID}"
${endIf}
!endif
${endIf}
System::Call 'Shell32::SHChangeNotify(i 0x8000000, i 0, i 0, i 0)'
${endIf}
!endif
!macroend

View File

@ -0,0 +1,28 @@
!define nsProcess::FindProcess `!insertmacro nsProcess::FindProcess`
!macro nsProcess::FindProcess _FILE _ERR
nsProcess::_FindProcess /NOUNLOAD `${_FILE}`
Pop ${_ERR}
!macroend
!define nsProcess::KillProcess `!insertmacro nsProcess::KillProcess`
!macro nsProcess::KillProcess _FILE _ERR
nsProcess::_KillProcess /NOUNLOAD `${_FILE}`
Pop ${_ERR}
!macroend
!define nsProcess::CloseProcess `!insertmacro nsProcess::CloseProcess`
!macro nsProcess::CloseProcess _FILE _ERR
nsProcess::_CloseProcess /NOUNLOAD `${_FILE}`
Pop ${_ERR}
!macroend
!define nsProcess::Unload `!insertmacro nsProcess::Unload`
!macro nsProcess::Unload
nsProcess::_Unload
!macroend

View File

@ -0,0 +1,64 @@
!macro downloadApplicationFiles
Var /GLOBAL packageUrl
Var /GLOBAL packageArch
StrCpy $packageUrl "${APP_PACKAGE_URL}"
StrCpy $packageArch "${APP_PACKAGE_URL}"
!ifdef APP_PACKAGE_URL_IS_INCOMLETE
!ifdef APP_64_NAME
!ifdef APP_32_NAME
!ifdef APP_ARM64_NAME
${if} ${IsNativeARM64}
StrCpy $packageUrl "$packageUrl/${APP_ARM64_NAME}"
${elseif} ${IsNativeAMD64}
StrCpy $packageUrl "$packageUrl/${APP_64_NAME}"
${else}
StrCpy $packageUrl "$packageUrl/${APP_32_NAME}"
${endif}
!else
${if} ${IsNativeAMD64}
StrCpy $packageUrl "$packageUrl/${APP_64_NAME}"
${else}
StrCpy $packageUrl "$packageUrl/${APP_32_NAME}"
${endif}
!endif
!else
StrCpy $packageUrl "$packageUrl/${APP_64_NAME}"
!endif
!else
StrCpy $packageUrl "$packageUrl/${APP_32_NAME}"
!endif
!endif
${if} ${IsNativeARM64}
StrCpy $packageArch "ARM64"
${elseif} ${IsNativeAMD64}
StrCpy $packageArch "64"
${else}
StrCpy $packageArch "32"
${endif}
download:
inetc::get /USERAGENT "electron-builder (Mozilla)" /HEADER "X-Arch: $packageArch" /RESUME "" "$packageUrl" "$PLUGINSDIR\package.7z" /END
Pop $0
${if} $0 == "Cancelled"
Quit
${endif}
${if} $0 != "OK"
# try without proxy
inetc::get /NOPROXY /USERAGENT "electron-builder (Mozilla)" /HEADER "X-Arch: $packageArch" /RESUME "" "$packageUrl" "$PLUGINSDIR\package.7z" /END
Pop $0
${endif}
${if} $0 == "Cancelled"
quit
${elseif} $0 != "OK"
Messagebox MB_RETRYCANCEL|MB_ICONEXCLAMATION "Unable to download application package from $packageUrl (status: $0).$\r$\n$\r$\nPlease check you Internet connection and retry." IDRETRY download
Quit
${endif}
StrCpy $packageFile "$PLUGINSDIR\package.7z"
!macroend

View File

@ -0,0 +1,104 @@
!include installer.nsh
InitPluginsDir
${IfNot} ${Silent}
SetDetailsPrint none
${endif}
StrCpy $appExe "$INSTDIR\${APP_EXECUTABLE_FILENAME}"
# must be called before uninstallOldVersion
!insertmacro setLinkVars
!ifdef ONE_CLICK
!ifdef HEADER_ICO
File /oname=$PLUGINSDIR\installerHeaderico.ico "${HEADER_ICO}"
!endif
${IfNot} ${Silent}
!ifdef HEADER_ICO
SpiderBanner::Show /MODERN /ICON "$PLUGINSDIR\installerHeaderico.ico"
!else
SpiderBanner::Show /MODERN
!endif
FindWindow $0 "#32770" "" $hwndparent
FindWindow $0 "#32770" "" $hwndparent $0
GetDlgItem $0 $0 1000
SendMessage $0 ${WM_SETTEXT} 0 "STR:$(installing)"
${endif}
!insertmacro CHECK_APP_RUNNING
!else
${ifNot} ${UAC_IsInnerInstance}
!insertmacro CHECK_APP_RUNNING
${endif}
!endif
Var /GLOBAL keepShortcuts
StrCpy $keepShortcuts "false"
!insertMacro setIsTryToKeepShortcuts
${if} $isTryToKeepShortcuts == "true"
ReadRegStr $R1 SHELL_CONTEXT "${INSTALL_REGISTRY_KEY}" KeepShortcuts
${if} $R1 == "true"
${andIf} ${FileExists} "$appExe"
StrCpy $keepShortcuts "true"
${endIf}
${endif}
!insertmacro uninstallOldVersion SHELL_CONTEXT
${if} $installMode == "all"
!insertmacro uninstallOldVersion HKEY_CURRENT_USER
${endIf}
SetOutPath $INSTDIR
!ifdef UNINSTALLER_ICON
File /oname=uninstallerIcon.ico "${UNINSTALLER_ICON}"
!endif
!insertmacro installApplicationFiles
!insertmacro registryAddInstallInfo
!insertmacro addStartMenuLink $keepShortcuts
!insertmacro addDesktopLink $keepShortcuts
${if} ${FileExists} "$newStartMenuLink"
StrCpy $launchLink "$newStartMenuLink"
${else}
StrCpy $launchLink "$INSTDIR\${APP_EXECUTABLE_FILENAME}"
${endIf}
!ifmacrodef registerFileAssociations
!insertmacro registerFileAssociations
!endif
!ifmacrodef customInstall
!insertmacro customInstall
!endif
!macro doStartApp
# otherwise app window will be in background
HideWindow
!insertmacro StartApp
!macroend
!ifdef ONE_CLICK
# https://github.com/electron-userland/electron-builder/pull/3093#issuecomment-403734568
!ifdef RUN_AFTER_FINISH
${ifNot} ${Silent}
${orIf} ${isForceRun}
!insertmacro doStartApp
${endIf}
!else
${if} ${isForceRun}
!insertmacro doStartApp
${endIf}
!endif
!insertmacro quitSuccess
!else
# for assisted installer run only if silent, because assisted installer has run after finish option
${if} ${isForceRun}
${andIf} ${Silent}
!insertmacro doStartApp
${endIf}
!endif

View File

@ -0,0 +1,90 @@
Var newStartMenuLink
Var oldStartMenuLink
Var newDesktopLink
Var oldDesktopLink
Var oldShortcutName
Var oldMenuDirectory
!include "common.nsh"
!include "MUI2.nsh"
!include "multiUser.nsh"
!include "allowOnlyOneInstallerInstance.nsh"
!ifdef INSTALL_MODE_PER_ALL_USERS
!ifdef BUILD_UNINSTALLER
RequestExecutionLevel user
!else
RequestExecutionLevel admin
!endif
!else
RequestExecutionLevel user
!endif
!ifdef BUILD_UNINSTALLER
SilentInstall silent
!else
Var appExe
Var launchLink
!endif
!ifdef ONE_CLICK
!include "oneClick.nsh"
!else
!include "assistedInstaller.nsh"
!endif
!insertmacro addLangs
!ifmacrodef customHeader
!insertmacro customHeader
!endif
Function .onInit
!ifmacrodef preInit
!insertmacro preInit
!endif
!ifdef DISPLAY_LANG_SELECTOR
!insertmacro MUI_LANGDLL_DISPLAY
!endif
!ifdef BUILD_UNINSTALLER
WriteUninstaller "${UNINSTALLER_OUT_FILE}"
!insertmacro quitSuccess
!else
!insertmacro check64BitAndSetRegView
!ifdef ONE_CLICK
!insertmacro ALLOW_ONLY_ONE_INSTALLER_INSTANCE
!else
${IfNot} ${UAC_IsInnerInstance}
!insertmacro ALLOW_ONLY_ONE_INSTALLER_INSTANCE
${EndIf}
!endif
!insertmacro initMultiUser
!ifmacrodef customInit
!insertmacro customInit
!endif
!ifmacrodef addLicenseFiles
InitPluginsDir
!insertmacro addLicenseFiles
!endif
!endif
FunctionEnd
!ifndef BUILD_UNINSTALLER
!include "installUtil.nsh"
!endif
Section "install"
!ifndef BUILD_UNINSTALLER
!include "installSection.nsh"
!endif
SectionEnd
!ifdef BUILD_UNINSTALLER
!include "uninstaller.nsh"
!endif

View File

@ -0,0 +1,112 @@
# one-click installer messages, see assistedMessages.yml for assisted installer messages
# en must be first (https://github.com/electron-userland/electron-builder/issues/2517)
win7Required:
en: Windows 7 and above is required
de: Windows 7 oder höher wird vorausgesetzt
it: È necessario disporre del sistema operativo Windows 7 e successivi
fr: Windows 7 (ou une version ultérieure) est requis
ja: Windows 7 以降が必要です
ko: Windows 7 이상이 필요합니다
ru: Требуется Windows 7 и выше
sk: Iba Windows 7 a vyššie je podporovaný
cs: Jsou podporovány pouze Windows 7 a vyšší
hu: Windows 7 vagy újabb szükséges
pl: Windows 7 lub nowszy jest wymagany
pt_BR: Requer Windows 7 ou superior
zh_CN: 需要 Windows 7 或以上系统
zh_TW: 需要 Windows 7 或以上系統
tr_TR: Windows 7 ve üstü gereklidir
sv_SE: Windows 7 eller högre krävs
no: Windows 7 og over er nødvendig
nl_NL: Windows 7 en hoger is vereist
fi: Windows 7 tai uudempi vaaditaan
es: Se necesita Windows 7 o una versión superior.
da: Windows 7 og højere er nødvendig
x64WinRequired:
en: 64-bit Windows is required
de: 64-Bit-Windows wird vorausgesetzt
it: È necessario disporre di un sistema operativo Windows a 64 bit
fr: Windows 64 bits est requis
ja: 64 ビット バージョンの Windows が必要です
ko: 64 비트 버전의 Windows가 필요합니다
ru: Требуется Windows 64-bit
sk: Potrebujete 64-bit Windows
cs: Potřebujete 64-bit Windows
hu: 64-bit Windows szükséges
pl: Windows 64-bitowy jest wymagany
pt_BR: Requer Windows 64 bits
zh_CN: 需要 64 位 Windows 系统
zh_TW: 需要 64 位 Windows 系統
tr_TR: 64 bit Windows gerekli
sv_SE: 64-bitars Windows krävs
no: 64-biters Windows er nødvendig
nl_NL: 64-bit Windows is vereist
fi: 64-bittinen Windows on pakollinen
es: Windows de 64 bits es requerido
da: 64-bit Windows er påkrævet
appRunning:
en: "${PRODUCT_NAME} is running.\nClick OK to close it."
de: "${PRODUCT_NAME} ist geöffnet. \nKlicken Sie zum Schliessen auf «OK»."
it: "${PRODUCT_NAME} è in esecuzione. \nPremi OK per chiudere."
fr: "${PRODUCT_NAME} est en cours dutilisation. \nCliquez sur «OK» pour fermer ce programme."
ja: "${PRODUCT_NAME} が実行中です。\nOK をクリックすると終了します。"
ko: "${PRODUCT_NAME}이(가) 실행 중입니다. \nOK을 클릭하면 종료됩니다."
ru: "Приложение ${PRODUCT_NAME} уже запущено.\nНажмите OK для закрытия."
sk: "${PRODUCT_NAME} práve beží.\nUkončite ho kliknutím na OK."
cs: "${PRODUCT_NAME} právě běží.\nUkončíte jej kliknutím na OK."
hu: "${PRODUCT_NAME} éppen fut. \nKattiontson az «OK»-ra a bezárásához."
pl: "${PRODUCT_NAME} jest otwarty. Aby zamknąć kliknij na OK."
pt_BR: "${PRODUCT_NAME} está em execução.\nClique em OK para fechar."
zh_CN: "${PRODUCT_NAME} 正在运行.\n点击“确定”关闭."
zh_TW: "${PRODUCT_NAME} 正在運行.\n點擊“確定”關閉."
tr_TR: "${PRODUCT_NAME} çalışıyor.\nKapatmak için Tamam'ı tıklayın."
sv_SE: "${PRODUCT_NAME} körs. \nKlicka på OK för att stänga det."
no: "${PRODUCT_NAME} kjører. \nKlikk OK for å lukke det."
nl_NL: "${PRODUCT_NAME} draait. \nKlik op 'OK' om het te sluiten."
fi: "${PRODUCT_NAME} on käynnissä. Napsauta OK sulkeaksesi sen."
es: "${PRODUCT_NAME} se está ejecutando. Haz clic en Aceptar para cerrarlo."
da: "${PRODUCT_NAME} er i gang. Klik OK for at lukke."
installing:
en: Installing, please wait...
de: Installation läuft, bitte warten...
it: Attendere prego. Installazione in corso...
fr: En cours dinstallation... Veuillez patienter s'il vous plaît.
ja: インストールしています。しばらくお待ちください...
ko: 설치하고 있습니다. 잠시 기다려주십시오...
ru: Установка, пожалуйста, подождите...
sk: Inštalujem, prosím počkajte...
cs: Instalování, prosím počkejte...
hu: Telepítés, kérem várjon...
pl: Zaczekaj na ukończenie instalacji...
pt_BR: Instalando, por favor aguarde...
zh_CN: 正在安装, 请稍候...
zh_TW: 正在安裝, 請稍候...
tr_TR: Yükleniyor, lütfen bekleyin...
sv_SE: Installerar, vänligen vänta...
no: Installerer, vennligst vent...
nl_NL: Installeren, even geduld...
fi: Asennetaan, odota...
es: Instalando, espera un momento...
da: Installerer, vent venligst...
areYouSureToUninstall:
en: Are you sure you want to uninstall ${PRODUCT_NAME}?
de: Sind Sie sicher, dass Sie ${PRODUCT_NAME} deinstallieren möchten?
it: Sicuro di voler procedere alla disinstallazione di ${PRODUCT_NAME}?
fr: Etes-vous sûr(e) de vouloir désinstaller ${PRODUCT_NAME}?
ja: ${PRODUCT_NAME} をアンインストールしてもよろしいですか?
ko: ${PRODUCT_NAME}을(를) 제거 하시겠습니까?
ru: Вы уверены, что хотите удалить ${PRODUCT_NAME}?
sk: Ste si istý že chcete odinštalovať ${PRODUCT_NAME}?
cs: Jste si jistí, že chcete odinstalovat ${PRODUCT_NAME}?
hu: Biztos benne, hogy szeretné eltávolítani a ${PRODUCT_NAME} alkalmazást?
pl: Czy na pewno chcesz odinstalować ${PRODUCT_NAME}?
pt_BR: Tem certeza que deseja desinstalar ${PRODUCT_NAME}?
zh_CN: 确定卸载 ${PRODUCT_NAME} 吗?
zh_TW: 確定卸載 ${PRODUCT_NAME} 嗎?
tr_TR: ${PRODUCT_NAME} kaldırmak istediğinize Eminmisiniz?
sv_SE: Är du säker på att du vill avinstallera ${PRODUCT_NAME}?
no: Er du sikker på at du vil avinstallere ${PRODUCT_NAME}?
nl_NL: Weet je zeker dat je ${PRODUCT_NAME} wilt verwijderen?
fi: Oletko varma, että haluat poistaa ${PRODUCT_NAME} asennuksen?
es: ¿Seguro que quieres desinstalar ${PRODUCT_NAME}?
da: Er du sikker på, at du vil afinstallere ${PRODUCT_NAME}?

View File

@ -0,0 +1,93 @@
!include FileFunc.nsh
!include UAC.nsh
!define FOLDERID_UserProgramFiles {5CD7AEE2-2219-4A67-B85D-6C9CE15660CB}
!define KF_FLAG_CREATE 0x00008000
# allow user to define own custom
!define /ifndef INSTALL_REGISTRY_KEY "Software\${APP_GUID}"
!define /ifndef UNINSTALL_REGISTRY_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINSTALL_APP_KEY}"
# current Install Mode ("all" or "CurrentUser")
Var installMode
!ifndef INSTALL_MODE_PER_ALL_USERS
!ifndef ONE_CLICK
Var hasPerUserInstallation
Var hasPerMachineInstallation
!endif
Var PerUserInstallationFolder
!macro setInstallModePerUser
StrCpy $installMode CurrentUser
SetShellVarContext current
# сhecks registry for previous installation path
ReadRegStr $perUserInstallationFolder HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation
${if} $perUserInstallationFolder != ""
StrCpy $INSTDIR $perUserInstallationFolder
${else}
StrCpy $0 "$LocalAppData\Programs"
System::Store S
# Win7 has a per-user programfiles known folder and this can be a non-default location
System::Call 'SHELL32::SHGetKnownFolderPath(g "${FOLDERID_UserProgramFiles}", i ${KF_FLAG_CREATE}, p 0, *p .r2)i.r1'
${If} $1 == 0
System::Call '*$2(&w${NSIS_MAX_STRLEN} .s)'
StrCpy $0 $1
System::Call 'OLE32::CoTaskMemFree(p r2)'
${endif}
System::Store L
StrCpy $INSTDIR "$0\${APP_FILENAME}"
${endif}
# allow /D switch to override installation path https://github.com/electron-userland/electron-builder/issues/1551
${StdUtils.GetParameter} $R0 "D" ""
${If} $R0 != ""
StrCpy $INSTDIR $R0
${endif}
!macroend
!endif
!ifdef INSTALL_MODE_PER_ALL_USERS_REQUIRED
Var perMachineInstallationFolder
!macro setInstallModePerAllUsers
StrCpy $installMode all
SetShellVarContext all
!ifdef BUILD_UNINSTALLER
${IfNot} ${UAC_IsAdmin}
ShowWindow $HWNDPARENT ${SW_HIDE}
!insertmacro UAC_RunElevated
Quit
${endif}
!endif
# сheck registry for previous installation path
ReadRegStr $perMachineInstallationFolder HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation
${if} $perMachineInstallationFolder != ""
StrCpy $INSTDIR $perMachineInstallationFolder
${else}
StrCpy $0 "$PROGRAMFILES"
!ifdef APP_64
${if} ${RunningX64}
StrCpy $0 "$PROGRAMFILES64"
${endif}
!endif
!ifdef MENU_FILENAME
StrCpy $0 "$0\${MENU_FILENAME}"
!endif
StrCpy $INSTDIR "$0\${APP_FILENAME}"
${endif}
# allow /D switch to override installation path https://github.com/electron-userland/electron-builder/issues/1551
${StdUtils.GetParameter} $R0 "D" ""
${If} $R0 != ""
StrCpy $INSTDIR $R0
${endif}
!macroend
!endif

View File

@ -0,0 +1,230 @@
!include nsDialogs.nsh
Var HasTwoAvailableOptions
Var RadioButtonLabel1
Var isForceMachineInstall
Var isForceCurrentInstall
!macro PAGE_INSTALL_MODE
!insertmacro MUI_PAGE_INIT
!insertmacro MUI_SET MULTIUSER_${MUI_PAGE_UNINSTALLER_PREFIX}INSTALLMODEPAGE ""
Var MultiUser.InstallModePage
Var MultiUser.InstallModePage.Text
Var MultiUser.InstallModePage.AllUsers
Var MultiUser.InstallModePage.CurrentUser
Var MultiUser.InstallModePage.ReturnValue
!ifndef BUILD_UNINSTALLER
!insertmacro FUNCTION_INSTALL_MODE_PAGE_FUNCTION MultiUser.InstallModePre_${MUI_UNIQUEID} MultiUser.InstallModeLeave_${MUI_UNIQUEID} ""
PageEx custom
PageCallbacks MultiUser.InstallModePre_${MUI_UNIQUEID} MultiUser.InstallModeLeave_${MUI_UNIQUEID}
Caption " "
PageExEnd
!else
!insertmacro FUNCTION_INSTALL_MODE_PAGE_FUNCTION MultiUser.InstallModePre_${MUI_UNIQUEID} MultiUser.InstallModeLeave_${MUI_UNIQUEID} un.
UninstPage custom un.multiUser.InstallModePre_${MUI_UNIQUEID} un.MultiUser.InstallModeLeave_${MUI_UNIQUEID}
!endif
!macroend
!macro FUNCTION_INSTALL_MODE_PAGE_FUNCTION PRE LEAVE UNINSTALLER_FUNCPREFIX
Function "${UNINSTALLER_FUNCPREFIX}${PRE}"
${if} ${UAC_IsInnerInstance}
${andIf} ${UAC_IsAdmin}
# inner Process (and Admin) - skip selection, inner process is always used for elevation (machine-wide)
!insertmacro setInstallModePerAllUsers
Abort
${endIf}
StrCpy $isForceMachineInstall "0"
StrCpy $isForceCurrentInstall "0"
!ifmacrodef customInstallmode
!insertmacro customInstallMode
!endif
${if} $isForceMachineInstall == "1"
${OrIf} ${isForAllUsers}
StrCpy $hasPerMachineInstallation "1"
StrCpy $hasPerUserInstallation "0"
${ifNot} ${UAC_IsAdmin}
ShowWindow $HWNDPARENT ${SW_HIDE}
!insertmacro UAC_RunElevated
Quit
${endIf}
!insertmacro setInstallModePerAllUsers
Abort
${endIf}
${if} $isForceCurrentInstall == "1"
${OrIf} ${isForCurrentUser}
StrCpy $hasPerMachineInstallation "0"
StrCpy $hasPerUserInstallation "1"
!insertmacro setInstallModePerUser
Abort
${endIf}
# If uninstalling, will check if there is both a per-user and per-machine installation. If there is only one, will skip the form.
# If uninstallation was invoked from the "add/remove programs" Windows will automatically requests elevation (depending if uninstall keys are in HKLM or HKCU)
# so (for uninstallation) just checking UAC_IsAdmin would probably be enought to determine if it's a per-user or per-machine. However, user can run the uninstall.exe from the folder itself
!ifdef BUILD_UNINSTALLER
${if} $hasPerUserInstallation == "1"
${andif} $hasPerMachineInstallation == "0"
!insertmacro setInstallModePerUser
Abort
${elseIf} $hasPerUserInstallation == "0"
${andIf} $hasPerMachineInstallation == "1"
${IfNot} ${UAC_IsAdmin}
ShowWindow $HWNDPARENT ${SW_HIDE}
!insertmacro UAC_RunElevated
Quit
${endIf}
!insertmacro setInstallModePerAllUsers
Abort
${endIf}
!insertmacro MUI_HEADER_TEXT "$(chooseUninstallationOptions)" "$(whichInstallationShouldBeRemoved)"
!else
!insertmacro MUI_HEADER_TEXT "$(chooseInstallationOptions)" "$(whoShouldThisApplicationBeInstalledFor)"
!endif
!insertmacro MUI_PAGE_FUNCTION_CUSTOM PRE
nsDialogs::Create 1018
Pop $MultiUser.InstallModePage
!ifndef BUILD_UNINSTALLER
${NSD_CreateLabel} 0u 0u 300u 20u "$(selectUserMode)"
StrCpy $8 "$(forAll)"
StrCpy $9 "$(onlyForMe)"
!else
${NSD_CreateLabel} 0u 0u 300u 20u "$(whichInstallationRemove)"
StrCpy $8 "$(forAll)"
StrCpy $9 "$(onlyForMe)"
!endif
Pop $MultiUser.InstallModePage.Text
${NSD_CreateRadioButton} 10u 30u 280u 20u "$8"
Pop $MultiUser.InstallModePage.AllUsers
${IfNot} ${UAC_IsAdmin}
!ifdef MULTIUSER_INSTALLMODE_ALLOW_ELEVATION
StrCpy $HasTwoAvailableOptions 1
!else
# since radio button is disabled, we add that comment to the disabled control itself
SendMessage $MultiUser.InstallModePage.AllUsers ${WM_SETTEXT} 0 "STR:$8 (must run as admin)"
EnableWindow $MultiUser.InstallModePage.AllUsers 0 # start out disabled
StrCpy $HasTwoAvailableOptions 0
!endif
${else}
StrCpy $HasTwoAvailableOptions 1
${endif}
System::Call "advapi32::GetUserName(t.r0,*i${NSIS_MAX_STRLEN})i"
${NSD_CreateRadioButton} 10u 50u 280u 20u "$9 ($0)"
Pop $MultiUser.InstallModePage.CurrentUser
nsDialogs::SetUserData $MultiUser.InstallModePage.AllUsers 1 ; Install for All Users (1, pra exibir o icone SHIELD de elevation)
nsDialogs::SetUserData $MultiUser.InstallModePage.CurrentUser 0 ; Install for Single User (0 pra não exibir)
${if} $HasTwoAvailableOptions == "1" ; if there are 2 available options, bind to radiobutton change
${NSD_OnClick} $MultiUser.InstallModePage.CurrentUser ${UNINSTALLER_FUNCPREFIX}InstModeChange
${NSD_OnClick} $MultiUser.InstallModePage.AllUsers ${UNINSTALLER_FUNCPREFIX}InstModeChange
${endif}
${NSD_CreateLabel} 0u 110u 280u 50u ""
Pop $RadioButtonLabel1
${if} $installMode == "all"
SendMessage $MultiUser.InstallModePage.AllUsers ${BM_SETCHECK} ${BST_CHECKED} 0 ; set as default
SendMessage $MultiUser.InstallModePage.AllUsers ${BM_CLICK} 0 0 ; trigger click event
${else}
SendMessage $MultiUser.InstallModePage.CurrentUser ${BM_SETCHECK} ${BST_CHECKED} 0 ; set as default
SendMessage $MultiUser.InstallModePage.CurrentUser ${BM_CLICK} 0 0 ; trigger click event
${endif}
!insertmacro MUI_PAGE_FUNCTION_CUSTOM SHOW
nsDialogs::Show
FunctionEnd
Function "${UNINSTALLER_FUNCPREFIX}${LEAVE}"
SendMessage $MultiUser.InstallModePage.AllUsers ${BM_GETCHECK} 0 0 $MultiUser.InstallModePage.ReturnValue
${if} $MultiUser.InstallModePage.ReturnValue = ${BST_CHECKED}
${IfNot} ${UAC_IsAdmin}
ShowWindow $HWNDPARENT ${SW_HIDE}
!insertmacro UAC_RunElevated
${Switch} $0
${Case} 0
${If} $1 = 1
Quit ;we are the outer process, the inner process has done its work (ExitCode is $2), we are done
${EndIf}
${If} $1 = 3 ;RunAs completed successfully, but with a non-admin user
${OrIf} $2 = 0x666666 ;our special return, the new process was not admin after all
MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "$(loginWithAdminAccount)"
${EndIf}
${Break}
${Case} 1223 ;user aborted
;MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "This option requires admin privileges, aborting!"
;Quit ; instead of quit just abort going to the next page, and stay in the radiobuttons
${Break}
${Case} 1062
MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "Logon service not running, aborting!" ; "Unable to elevate, Secondary Logon service not running!"
;Quit ; instead of quit just abort going to the next page, and stay in the radiobuttons
${Break}
${Default}
MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "Unable to elevate, error $0"
;Quit ; instead of quit just abort going to the next page, and stay in the radiobuttons
${Break}
${EndSwitch}
ShowWindow $HWNDPARENT ${SW_SHOW}
BringToFront
Abort
${else}
!insertmacro setInstallModePerAllUsers
${endif}
${else}
!insertmacro setInstallModePerUser
${endif}
!insertmacro MUI_PAGE_FUNCTION_CUSTOM LEAVE
FunctionEnd
Function "${UNINSTALLER_FUNCPREFIX}InstModeChange"
pop $1
nsDialogs::GetUserData $1
pop $1
GetDlgItem $0 $hwndParent 1 ; get item 1 (next button) at parent window, store in $0 - (0 is back, 1 is next .. what about CANCEL? http://nsis.sourceforge.net/Buttons_Header )
StrCpy $7 ""
${if} "$1" == "0" ; current user
${if} $hasPerUserInstallation == "1"
!ifndef BUILD_UNINSTALLER
StrCpy $7 "$(perUserInstallExists)($perUserInstallationFolder)$\r$\n$(reinstallUpgrade)"
!else
StrCpy $7 "$(perUserInstall)($perUserInstallationFolder)$\r$\n$(uninstall)"
!endif
${else}
StrCpy $7 "$(freshInstallForCurrent)"
${endif}
SendMessage $0 ${BCM_SETSHIELD} 0 0 ; hide SHIELD
${else} ; all users
${if} $hasPerMachineInstallation == "1"
!ifndef BUILD_UNINSTALLER
StrCpy $7 "$(perMachineInstallExists)($perMachineInstallationFolder)$\r$\n$(reinstallUpgrade)"
!else
StrCpy $7 "$(perMachineInstall)($perMachineInstallationFolder)$\r$\n$(uninstall)"
!endif
${else}
StrCpy $7 "$(freshInstallForAll)"
${endif}
${ifNot} ${UAC_IsAdmin}
StrCpy $7 "$7"
SendMessage $0 ${BCM_SETSHIELD} 0 1 ; display SHIELD
${else}
SendMessage $0 ${BCM_SETSHIELD} 0 0 ; hide SHIELD
${endif}
${endif}
SendMessage $RadioButtonLabel1 ${WM_SETTEXT} 0 "STR:$7"
FunctionEnd
!macroend

View File

@ -0,0 +1,19 @@
!ifndef BUILD_UNINSTALLER
!ifmacrodef licensePage
!insertmacro skipPageIfUpdated
!insertmacro licensePage
!endif
!endif
!insertmacro MUI_PAGE_INSTFILES
!ifdef BUILD_UNINSTALLER
!insertmacro MUI_UNPAGE_INSTFILES
!endif
!macro initMultiUser
!ifdef INSTALL_MODE_PER_ALL_USERS
!insertmacro setInstallModePerAllUsers
!else
!insertmacro setInstallModePerUser
!endif
!macroend

View File

@ -0,0 +1,87 @@
!include "common.nsh"
!include "extractAppPackage.nsh"
# https://github.com/electron-userland/electron-builder/issues/3972#issuecomment-505171582
CRCCheck off
WindowIcon Off
AutoCloseWindow True
RequestExecutionLevel ${REQUEST_EXECUTION_LEVEL}
Function .onInit
!ifndef SPLASH_IMAGE
SetSilent silent
!endif
!insertmacro check64BitAndSetRegView
FunctionEnd
Function .onGUIInit
InitPluginsDir
!ifdef SPLASH_IMAGE
File /oname=$PLUGINSDIR\splash.bmp "${SPLASH_IMAGE}"
BgImage::SetBg $PLUGINSDIR\splash.bmp
BgImage::Redraw
!endif
FunctionEnd
Section
!ifdef SPLASH_IMAGE
HideWindow
!endif
StrCpy $INSTDIR "$TEMP\${UNPACK_DIR_NAME}"
RMDir /r $INSTDIR
SetOutPath $INSTDIR
!ifdef APP_DIR_64
!ifdef APP_DIR_ARM64
!ifdef APP_DIR_32
${if} ${IsNativeARM64}
File /r "${APP_DIR_ARM64}\*.*"
${elseif} ${RunningX64}
File /r "${APP_DIR_64}\*.*"
${else}
File /r "${APP_DIR_32}\*.*"
${endIf}
!else
${if} ${IsNativeARM64}
File /r "${APP_DIR_ARM64}\*.*"
${else}
File /r "${APP_DIR_64}\*.*"
{endIf}
!endif
!else
!ifdef APP_DIR_32
${if} ${RunningX64}
File /r "${APP_DIR_64}\*.*"
${else}
File /r "${APP_DIR_32}\*.*"
${endIf}
!else
File /r "${APP_DIR_64}\*.*"
!endif
!endif
!else
!ifdef APP_DIR_32
File /r "${APP_DIR_32}\*.*"
!else
!insertmacro extractEmbeddedAppPackage
!endif
!endif
System::Call 'Kernel32::SetEnvironmentVariable(t, t)i ("PORTABLE_EXECUTABLE_DIR", "$EXEDIR").r0'
System::Call 'Kernel32::SetEnvironmentVariable(t, t)i ("PORTABLE_EXECUTABLE_FILE", "$EXEPATH").r0'
System::Call 'Kernel32::SetEnvironmentVariable(t, t)i ("PORTABLE_EXECUTABLE_APP_FILENAME", "${APP_FILENAME}").r0'
${StdUtils.GetAllParameters} $R0 0
!ifdef SPLASH_IMAGE
BgImage::Destroy
!endif
ExecWait "$INSTDIR\${APP_EXECUTABLE_FILENAME} $R0" $0
SetErrorLevel $0
SetOutPath $PLUGINSDIR
RMDir /r $INSTDIR
SectionEnd

View File

@ -0,0 +1,36 @@
It is developer documentation. See [user documentation](https://electron.build/configuration/nsis).
http://www.mathiaswestin.net/2012/09/how-to-make-per-user-installation-with.html
https://msdn.microsoft.com/en-us/library/windows/desktop/dd378457(v=vs.85).aspx#FOLDERID_UserProgramFiles
https://github.com/Drizin/NsisMultiUser
NSIS vs Inno Setup — it is not easy to choose because both are far from ideal, e.g. inno also doesn't have built-in per-user installation implementation — http://stackoverflow.com/questions/34330668/inno-setup-custom-dialog-with-per-user-or-per-machine-installation.
http://stackoverflow.com/questions/2565215/checking-if-the-application-is-running-in-nsis-before-uninstalling
One-click installer: http://forums.winamp.com/showthread.php?t=300479
# GUID
See [docs](https://electron.build/configuration/nsis).
We use UUID v5 to generate sha-1 name-based UUID.
http://stackoverflow.com/questions/3029994/convert-uri-to-guid
https://alexandrebrisebois.wordpress.com/2013/11/14/create-predictable-guids-for-your-windows-azure-table-storage-entities/
https://github.com/Squirrel/Squirrel.Windows/pull/658
# Compression
NSIS LZMA compression is slower and worse compared to external `7za` compression. Slower because `7za` is multi-threaded, worse because LZMA codec implementation is outdated and BCJ2 filter is not enabled.
Difference for test app — 4 MB (before: 36.3 after: 32.8).
And compression time is also greatly reduced.
Since NSIS is awesome, no disadvantages in our approach — [compression is disabled](http://nsis.sourceforge.net/Reference/SetCompress) before `File /oname=app.7z "${APP_ARCHIVE}"` and enabled after (it is the reasons why `SOLID` compression is not used).
So, opposite to Squirrel.Windows, archive is not twice compressed.
So, in your custom NSIS scripts you should not use any compression instructions. Only `SetCompress` if you need to disable compression for already archived file.

View File

@ -0,0 +1,110 @@
Function un.onInit
!insertmacro check64BitAndSetRegView
${IfNot} ${Silent}
!ifdef ONE_CLICK
MessageBox MB_OKCANCEL "$(areYouSureToUninstall)" IDOK +2
Quit
# one-click installer executes uninstall section in the silent mode, but we must show message dialog if silent mode was not explicitly set by user (using /S flag)
!insertmacro CHECK_APP_RUNNING
SetSilent silent
!endif
${endIf}
!insertmacro initMultiUser
!ifmacrodef customUnInit
!insertmacro customUnInit
!endif
FunctionEnd
Section "un.install"
!ifndef ONE_CLICK
# for assisted installer we check it here to show progress
!insertmacro CHECK_APP_RUNNING
!endif
!insertmacro setLinkVars
${ifNot} ${isKeepShortcuts}
WinShell::UninstAppUserModelId "${APP_ID}"
!ifndef DO_NOT_CREATE_DESKTOP_SHORTCUT
WinShell::UninstShortcut "$oldDesktopLink"
Delete "$oldDesktopLink"
!endif
!ifndef DO_NOT_CREATE_START_MENU_SHORTCUT
WinShell::UninstShortcut "$oldStartMenuLink"
Delete "$oldStartMenuLink"
ReadRegStr $R1 SHELL_CONTEXT "${INSTALL_REGISTRY_KEY}" MenuDirectory
${ifNot} $R1 == ""
RMDir "$SMPROGRAMS\$R1"
${endIf}
!endif
${endIf}
# refresh the desktop
System::Call 'shell32::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
!ifmacrodef unregisterFileAssociations
!insertmacro unregisterFileAssociations
!endif
# delete the installed files
!ifmacrodef customRemoveFiles
!insertmacro customRemoveFiles
!else
RMDir /r $INSTDIR
!endif
Var /GLOBAL isDeleteAppData
StrCpy $isDeleteAppData "0"
ClearErrors
${GetParameters} $R0
${GetOptions} $R0 "--delete-app-data" $R1
${if} ${Errors}
!ifdef DELETE_APP_DATA_ON_UNINSTALL
${ifNot} ${isUpdated}
StrCpy $isDeleteAppData "1"
${endif}
!endif
${else}
StrCpy $isDeleteAppData "1"
${endIf}
${if} $isDeleteAppData == "1"
# electron always uses per user app data
${if} $installMode == "all"
SetShellVarContext current
${endif}
RMDir /r "$APPDATA\${APP_FILENAME}"
!ifdef APP_PRODUCT_FILENAME
RMDir /r "$APPDATA\${APP_PRODUCT_FILENAME}"
!endif
# electron use package.json name for cache,indexdb etc.
!ifdef APP_PACKAGE_NAME
RMDir /r "$APPDATA\${APP_PACKAGE_NAME}"
!endif
${if} $installMode == "all"
SetShellVarContext all
${endif}
${endif}
DeleteRegKey SHELL_CONTEXT "${UNINSTALL_REGISTRY_KEY}"
!ifdef UNINSTALL_REGISTRY_KEY_2
DeleteRegKey SHELL_CONTEXT "${UNINSTALL_REGISTRY_KEY_2}"
!endif
DeleteRegKey SHELL_CONTEXT "${INSTALL_REGISTRY_KEY}"
!ifmacrodef customUnInstall
!insertmacro customUnInstall
!endif
!ifdef ONE_CLICK
!insertmacro quitSuccess
!endif
SectionEnd