main funcions fixes

This commit is contained in:
2025-09-29 22:06:11 +09:00
parent 40e016e128
commit c8c3274527
7995 changed files with 1517998 additions and 1057 deletions

View File

@@ -0,0 +1,47 @@
# NSIS
⚠️ **It is developer documentation.** If your are looking for usage guide, see [user documentation](https://electron.build/nsis).
NSIS stands for Nullsoft Scriptable Install System. electron-builder utilizes a [customized version](https://github.com/electron-userland/electron-builder-binaries) of it and uses `NsisMultiUser` plugin to handle installation for single user or all users on the computer.
## Some links
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
## Localization (l10n)
For translators, the strings to be displayed are included in [`assistedMessages.yml`](https://github.com/electron-userland/electron-builder/blob/master/packages/app-builder-lib/templates/nsis/assistedMessages.yml) and [`messages.yml`]https://github.com/electron-userland/electron-builder/blob/master/packages/app-builder-lib/templates/nsis/messages.yml).
As for other strings in NSIS, head to [electron-userland/electron-builder-binaries](https://github.com/electron-userland/electron-builder-binaries) or the upstream repository on [Sorceforge](https://sourceforge.net/p/nsis/code/HEAD/tree/).
## GUID
See [docs](https://electron.build/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,154 @@
!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
${StrContains} $0 "${APP_FILENAME}" $INSTDIR
${If} $0 == ""
StrCpy $INSTDIR "$INSTDIR\${APP_FILENAME}"
${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
!ifndef removeDefaultUninstallWelcomePage
!ifmacrodef customUnWelcomePage
!insertmacro customUnWelcomePage
!else
!insertmacro MUI_UNPAGE_WELCOME
!endif
!endif
!ifndef INSTALL_MODE_PER_ALL_USERS
!insertmacro PAGE_INSTALL_MODE
!endif
!insertmacro MUI_UNPAGE_INSTFILES
!ifmacrodef customUninstallPage
!insertmacro customUninstallPage
!endif
!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
!ifdef INSTALL_MODE_PER_ALL_USERS_DEFAULT
!insertmacro setInstallModePerAllUsers
!else
!insertmacro setInstallModePerUser
!endif
!endif
${endif}
!endif
!macroend

View File

@@ -0,0 +1,368 @@
# 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: インストールオプションの選択
ko: 설치 옵션 선택
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: アンインストールオプションの選択
ko: 제거 옵션 선택
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 být odstraněna?
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: どれをアンインストールしますか?
ko: 어떤 설치 버전을 제거할까요?
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: どのユーザーにインストールしますか?
ko : 이 프로그램의 사용자는 누구인가요?
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 pro Vá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: このソフトウェアをすべてのユーザーが使用できるようにするか、現在のユーザーのみ使用するかを選択してください
ko : 이 프로그램을 모든 사용자가 사용할 수 있도록 할 것인지 아니면 자신만 사용할 수 있도록 할 것인지 선택하십시오.
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 instalaci 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どちらを削除しますか
ko: 이 프로그램은 시스템당(모든 사용자)또는 사용자별로 설치됩니다.\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. (Bude potrebovať prihlásenie administrátora)
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: すべてのユーザーに新規インストール(管理者権限が必要)
ko: 모든 사용자를 위해 새로 설치. (관리자 자격 증명을 묻는 메시지가 표시됨)
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: 現在のユーザーのみ新規インストール
ko: 현재 사용자만 새로 설치합니다.
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: 現在のユーザーのみにインストールする
ko: &me 전용
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: このコンピューターを使用しているすべてのユーザー用にインストールする
ko: 이 컴퓨터를 사용하는 모든 사람(&모든 사용자)
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 úč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: 続行するには、管理者権限アカウントでログインする必要があります...
ko: 계속하려면 관리자 그룹의 구성원인 계정으로 로그인해야 합니다...
perUserInstallExists:
en: There is already a per-user installation.
de: Es existiert bereits eine Installation 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: すでに現在のユーザーにインストールされています。
ko: 이미 사용자별 설치가 있습니다.
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: ユーザーごとのインストールがあります。
ko: 사용자별로 설치되어 있습니다.
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: 既にすべてのユーザー用にインストールされています。
ko: 이미 머신별로 설치되어 있습니다.
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: すべてのユーザー用のインストールがあります。
ko: 머신별로 설치되어 있습니다.
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: 再インストール/アップグレードします。
ko: 재설치/업그레이드합니다.
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: アンインストールします。
ko: 제거합니다.

View File

@@ -0,0 +1,147 @@
!include x64.nsh
!include WinVer.nsh
BrandingText "${PRODUCT_NAME} ${VERSION}"
ShowInstDetails nevershow
!ifdef BUILD_UNINSTALLER
ShowUninstDetails nevershow
!endif
FileBufSize 64
# Allows for a product name to display properly if it has an ampersand
# Doesn't affect anything if there is no double ampersand
!searchreplace DoubleAmpersand "${PRODUCT_NAME}" "&" "&&"
Name "${PRODUCT_NAME}" "${DoubleAmpersand}"
!define APP_EXECUTABLE_FILENAME "${PRODUCT_FILENAME}.exe"
!define UNINSTALL_FILENAME "Uninstall ${PRODUCT_FILENAME}.exe"
!macro setSpaceRequired SECTION_ID
!ifdef APP_64_UNPACKED_SIZE
!ifdef APP_32_UNPACKED_SIZE
!ifdef APP_ARM64_UNPACKED_SIZE
${if} ${IsNativeARM64}
SectionSetSize ${SECTION_ID} ${APP_ARM64_UNPACKED_SIZE}
${elseif} ${IsNativeAMD64}
SectionSetSize ${SECTION_ID} ${APP_64_UNPACKED_SIZE}
${else}
SectionSetSize ${SECTION_ID} ${APP_32_UNPACKED_SIZE}
${endif}
!else
${if} ${RunningX64}
SectionSetSize ${SECTION_ID} ${APP_64_UNPACKED_SIZE}
${else}
SectionSetSize ${SECTION_ID} ${APP_32_UNPACKED_SIZE}
${endif}
!endif
!else
SectionSetSize ${SECTION_ID} ${APP_64_UNPACKED_SIZE}
!endif
!else
!ifdef APP_32_UNPACKED_SIZE
SectionSetSize ${SECTION_ID} ${APP_32_UNPACKED_SIZE}
!endif
!endif
!macroend
!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
!define LogSet "!insertmacro LogSetMacro"
!macro LogSetMacro SETTING
!ifdef ENABLE_LOGGING_ELECTRON_BUILDER
SetOutPath $INSTDIR
LogSet ${SETTING}
!endif
!macroend
!define LogText "!insertmacro LogTextMacroEB"
!macro LogTextMacroEB INPUT_TEXT
!ifdef ENABLE_LOGGING_ELECTRON_BUILDER
LogText ${INPUT_TEXT}
!endif
!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,118 @@
!ifndef nsProcess::FindProcess
!include "nsProcess.nsh"
!endif
!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 FIND_PROCESS _FILE _ERR
!ifdef INSTALL_MODE_PER_ALL_USERS
${nsProcess::FindProcess} "${_FILE}" ${_ERR}
!else
# find process owned by current user
nsExec::Exec `"$SYSDIR\cmd.exe" /c tasklist /FI "USERNAME eq %USERNAME%" /FI "IMAGENAME eq ${_FILE}" /FO csv | "$SYSDIR\find.exe" "${_FILE}"`
Pop ${_ERR}
!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}
!insertmacro FIND_PROCESS "${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
!ifdef INSTALL_MODE_PER_ALL_USERS
nsExec::Exec `taskkill /im "${APP_EXECUTABLE_FILENAME}" /fi "PID ne $pid"`
!else
nsExec::Exec `"$SYSDIR\cmd.exe" /c taskkill /im "${APP_EXECUTABLE_FILENAME}" /fi "PID ne $pid" /fi "USERNAME eq %USERNAME%"`
!endif
# to ensure that files are not "in-use"
Sleep 300
# Retry counter
StrCpy $R1 0
loop:
IntOp $R1 $R1 + 1
!insertmacro FIND_PROCESS "${APP_EXECUTABLE_FILENAME}" $R0
${if} $R0 == 0
# wait to give a chance to exit gracefully
Sleep 1000
!ifdef INSTALL_MODE_PER_ALL_USERS
nsExec::Exec `taskkill /f /im "${APP_EXECUTABLE_FILENAME}" /fi "PID ne $pid"`
!else
nsExec::Exec `"$SYSDIR\cmd.exe" /c taskkill /f /im "${APP_EXECUTABLE_FILENAME}" /fi "PID ne $pid" /fi "USERNAME eq %USERNAME%"`
!endif
!insertmacro FIND_PROCESS "${APP_EXECUTABLE_FILENAME}" $R0
${If} $R0 == 0
DetailPrint `Waiting for "${PRODUCT_NAME}" to close.`
Sleep 2000
${else}
Goto not_running
${endIf}
${else}
Goto not_running
${endIf}
# App likely running with elevated permissions.
# Ask user to close it manually
${if} $R1 > 1
MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION "$(appCannotBeClosed)" /SD IDCANCEL IDRETRY loop
Quit
${else}
Goto loop
${endIf}
not_running:
${endIf}
${endIf}
!macroend

View File

@@ -0,0 +1,138 @@
!macro extractEmbeddedAppPackage
!ifdef COMPRESS
SetCompress off
!endif
Var /GLOBAL packageArch
!insertmacro identify_package
!insertmacro compute_files_for_current_arch
!ifdef COMPRESS
SetCompress "${COMPRESS}"
!endif
!insertmacro decompress
!insertmacro custom_files_post_decompression
!macroend
!macro identify_package
!ifdef APP_32
StrCpy $packageArch "32"
!endif
!ifdef APP_64
${if} ${RunningX64}
${OrIf} ${IsNativeARM64}
StrCpy $packageArch "64"
${endif}
!endif
!ifdef APP_ARM64
${if} ${IsNativeARM64}
StrCpy $packageArch "ARM64"
${endif}
!endif
!macroend
!macro compute_files_for_current_arch
${if} $packageArch == "ARM64"
!ifdef APP_ARM64
!insertmacro arm64_app_files
!endif
${elseif} $packageArch == "64"
!ifdef APP_64
!insertmacro x64_app_files
!endif
${else}
!ifdef APP_32
!insertmacro ia32_app_files
!endif
${endIf}
!macroend
!macro custom_files_post_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 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
File /oname=$PLUGINSDIR\app-32.${COMPRESSION_METHOD} "${APP_32}"
!macroend
!macro decompress
!ifdef ZIP_COMPRESSION
nsisunz::Unzip "$PLUGINSDIR\app-$packageArch.zip" "$INSTDIR"
Pop $R0
StrCmp $R0 "success" +3
MessageBox MB_OK|MB_ICONEXCLAMATION "$(decompressionFailed)$\n$R0"
Quit
!else
!insertmacro extractUsing7za "$PLUGINSDIR\app-$packageArch.7z"
!endif
!macroend
!macro extractUsing7za FILE
Push $OUTDIR
CreateDirectory "$PLUGINSDIR\7z-out"
ClearErrors
SetOutPath "$PLUGINSDIR\7z-out"
Nsis7z::Extract "${FILE}"
Pop $R0
SetOutPath $R0
# Retry counter
StrCpy $R1 0
LoopExtract7za:
IntOp $R1 $R1 + 1
# Attempt to copy files in atomic way
CopyFiles /SILENT "$PLUGINSDIR\7z-out\*" $OUTDIR
IfErrors 0 DoneExtract7za
DetailPrint `Can't modify "${PRODUCT_NAME}"'s files.`
${if} $R1 < 5
# Try copying a few times before asking for a user action.
Goto RetryExtract7za
${else}
MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION "$(appCannotBeClosed)" /SD IDRETRY IDCANCEL AbortExtract7za
${endIf}
# As an absolutely last resort after a few automatic attempts and user
# intervention - we will just overwrite everything with `Nsis7z::Extract`
# even though it is not atomic and will ignore errors.
# Clear the temporary folder first to make sure we don't use twice as
# much disk space.
RMDir /r "$PLUGINSDIR\7z-out"
Nsis7z::Extract "${FILE}"
Goto DoneExtract7za
AbortExtract7za:
Quit
RetryExtract7za:
Sleep 1000
Goto LoopExtract7za
DoneExtract7za:
!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,248 @@
!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
Function handleUninstallResult
Var /GLOBAL rootKey_uninstallResult
Exch $rootKey_uninstallResult
${if} "$rootKey_uninstallResult" == "SHELL_CONTEXT"
!ifmacrodef customUnInstallCheck
!insertmacro customUnInstallCheck
Return
!endif
${elseif} "$rootKey_uninstallResult" == "HKEY_CURRENT_USER"
!ifmacrodef customUnInstallCheckCurrentUser
!insertmacro customUnInstallCheckCurrentUser
Return
!endif
${endif}
IfErrors 0 +3
DetailPrint `Uninstall was not successful. Not able to launch uninstaller!`
Return
${if} $R0 != 0
MessageBox MB_OK|MB_ICONEXCLAMATION "$(uninstallFailed): $R0"
DetailPrint `Uninstall was not successful. Uninstaller error code: $R0.`
SetErrorLevel 2
Quit
${endif}
FunctionEnd
!macro handleUninstallResult ROOT_KEY
Push "${ROOT_KEY}"
Call handleUninstallResult
!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
Push 0
Pop $R0
!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 == ""
ClearErrors
Return
${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 == ""
ClearErrors
Return
${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"
# Retry counter
StrCpy $R5 0
UninstallLoop:
IntOp $R5 $R5 + 1
${if} $R5 > 5
MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION "$(appCannotBeClosed)" /SD IDCANCEL IDRETRY OneMoreAttempt
Return
${endIf}
OneMoreAttempt:
ExecWait '"$uninstallerFileNameTemp" /S /KEEP_APP_DATA $0 _?=$installationDir' $R0
ifErrors TryInPlace CheckResult
TryInPlace:
# 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 DoesNotExist
CheckResult:
${if} $R0 == 0
Return
${endIf}
Sleep 1000
Goto UninstallLoop
DoesNotExist:
SetErrors
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
${andIf} ${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_INCOMPLETE
!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 your internet connection and retry." IDRETRY download
Quit
${endif}
StrCpy $packageFile "$PLUGINSDIR\package.7z"
!macroend

View File

@@ -0,0 +1,110 @@
!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)"
StrCpy $1 $hwndparent
System::Call 'user32::ShutdownBlockReasonCreate(${SYSTYPE_PTR}r1, w "$(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
!insertmacro handleUninstallResult SHELL_CONTEXT
${if} $installMode == "all"
!insertmacro uninstallOldVersion HKEY_CURRENT_USER
!insertmacro handleUninstallResult 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,125 @@
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
Call setInstallSectionSpaceRequired
SetOutPath $INSTDIR
${LogSet} on
!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" INSTALL_SECTION_ID
!ifndef BUILD_UNINSTALLER
# If we're running a silent upgrade of a per-machine installation, elevate so extracting the new app will succeed.
# For a non-silent install, the elevation will be triggered when the install mode is selected in the UI,
# but that won't be executed when silent.
!ifndef INSTALL_MODE_PER_ALL_USERS
!ifndef ONE_CLICK
${if} $hasPerMachineInstallation == "1" # set in onInit by initMultiUser
${andIf} ${Silent}
${ifNot} ${UAC_IsAdmin}
ShowWindow $HWNDPARENT ${SW_HIDE}
!insertmacro UAC_RunElevated
${Switch} $0
${Case} 0
${Break}
${Case} 1223 ;user aborted
${Break}
${Default}
MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "Unable to elevate, error $0"
${Break}
${EndSwitch}
Quit
${else}
!insertmacro setInstallModePerAllUsers
${endIf}
${endIf}
!endif
!endif
!include "installSection.nsh"
!endif
SectionEnd
Function setInstallSectionSpaceRequired
!insertmacro setSpaceRequired ${INSTALL_SECTION_ID}
FunctionEnd
!ifdef BUILD_UNINSTALLER
!include "uninstaller.nsh"
!endif

View File

@@ -0,0 +1,237 @@
# 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.\nIf it doesn't close, try closing it manually."
ar: "‫إن ${PRODUCT_NAME} يعمل حاليا.\nيُرجى الضغط على « موافق » لغلقه.\nإذا لم يُغلَق، يُرجى محاولة إغلاقه يدويا."
az: "${PRODUCT_NAME} işləyir.\nBağlamaq üçün \"Oldu\"ya klikləyin.\nƏgər bağlanmasa, əllə bağlamağa çalışın."
ca: "${PRODUCT_NAME}s'executa.\nFeu clic a D'acord per tancar-la.\nSi no es tanca, proveu de tancar-la manualment."
cs: "${PRODUCT_NAME} běží.\nPotvrďte zavření stisknutím OK.\nPokud se aplikace nezavře sama, zavřete ji ručně."
cy: "Mae ${PRODUCT_NAME} yn rhedeg.\nCliciwch Iawn i'w gau.\nOs na fydd yn cau, ceisiwch ei gau â llaw."
da: "${PRODUCT_NAME} kører.\nKlik OK for at lukke den.\nHvis den ikke lukker, kan du prøve at lukke den manuelt."
de: "${PRODUCT_NAME} wird gerade ausgeführt.\nKlicke auf »OK«, um es zu schließen.\nFalls es sich nicht schließen lässt, versuche es manuell zu schließen."
el: "Το ${PRODUCT_NAME} εκτελείται ήδη. \nΚάντε κλικ στο ΟΚ για κλείσιμο.\nΑν δεν κλείνει, δοκιμάστε να το κλείσετε εσείς."
eo: "${PRODUCT_NAME} funkcias.\nAlklaku Bone („OK“) por fermi ĝin.\nSe ĝi ne fermiĝas, provu fermi ĝin permane."
es: "${PRODUCT_NAME} está activa.\nHaz clic en Aceptar para cerrarla.\nSi no se cierra, inténtalo manualmente."
fi: "${PRODUCT_NAME} on käynnissä.\nValitse OK sulkeaksesi sen.\nJos se ei sulkeudu, yritä sulkea se manuaalisesti."
fr: "${PRODUCT_NAME} est en cours dutilisation. \nCliquez sur «OK» pour fermer ce programme."
he: "${PRODUCT_NAME} רץ.\nלחץ בסדר כדי לסגור אותו.\nאם הוא לא נסגר, נסה לסגור אותו באופן ידני."
hu: "A ${PRODUCT_NAME} alkalmazás fut.\nKattints az OK gombra a bezárásához.\nHa így sem áll le, zárd be manuálisan."
it: "${PRODUCT_NAME} è in esecuzione.\nClicca su OK per chiuderla.\nSe non si chiude, prova a chiuderla manualmente."
ja: "${PRODUCT_NAME} が起動しています。\nOKをクリックして、閉じてください。\n閉じない場合は、手動で閉じてください。"
ko: "${PRODUCT_NAME}이(가) 실행 중입니다. \nOK을 클릭하면 종료됩니다."
lt: "${PRODUCT_NAME} vis dar veikia.\nSpustelėkite „Gerai“, kad ją užvertumėte.\nJeigu ji neužsiveria, pabandykite ją užverti rankiniu būdu."
nl_NL: "${PRODUCT_NAME} is nog actief.\nKlik op OK om de applicatie te sluiten.\nAls de applicatie vervolgens nog niet sluit, probeer dan om de applicatie zelf te sluiten."
no: "${PRODUCT_NAME} kjører. \nKlikk OK for å lukke det."
pl: "Aplikacja ${PRODUCT_NAME} jest uruchomiona.\nKliknij OK, aby ją zamknąć.\nJeśli nie zostanie zamknięta, spróbuj zamknąć ją ręcznie."
pt_BR: "${PRODUCT_NAME} está funcionando.\nClique no OK para fechar.\nSe não fechar, tente fechá-lo manualmente."
pt_PT: "${PRODUCT_NAME} está a correr.\nClique em OK para o encerrar.\nSe não encerrar, tente encerrá-lo manualmente."
ro: "${PRODUCT_NAME} este pornit.\nApasă OK pentru a-l opri.\nDacă nu se oprește, încearcă să-l oprești manual."
ru: "Приложение ${PRODUCT_NAME} запущено.\nНажмите «OK», чтобы закрыть его.\nЕсли оно не закрывается, попробуйте закрыть его вручную."
sk: "${PRODUCT_NAME} beží.\nKliknutím na tlačidlo OK ho zatvoríte.\nAk sa nezavrie, skúste ho zatvoriť ručne."
sl: "${PRODUCT_NAME} teče.\nKliknite OK za prekinitev.\nČe se ne zapre, ga poskusite zapreti ročno."
sq: "${PRODUCT_NAME} po xhiron.\nKlikoni mbi OK që të mbyllet.\nNëse smbyllet, provoni dorazi."
sr: "${PRODUCT_NAME} је у току.\nКликнути OK да би се затворило.\nАко се не затвори, покушајте да га ручно затворите."
sv_SE: "${PRODUCT_NAME} är igång.\nKlicka på OK för att stänga det.\nOm det inte stängs, försök att stänga det manuellt."
tr_TR: "${PRODUCT_NAME} çalışıyor.\nKapatmak için Tamam'ı tıklayın."
uk: "${PRODUCT_NAME} запущено.\nКлацніть ОК для завершення.\nЯкщо завершення не вдалось — спробуйте вручну."
zh_CN: "${PRODUCT_NAME} 正在运行.\n点击“确定”关闭."
zh_TW: "${PRODUCT_NAME} 正在執行。\n點擊 OK 關閉。\n如果無法關閉試著手動關閉。"
appCannotBeClosed:
en: "${PRODUCT_NAME} cannot be closed. \nPlease close it manually and click Retry to continue."
ar: "‫لم يتمكن من إغلاق ${PRODUCT_NAME} \nيُرجى إغلاقه يدويا ثم الضغط مرة أخرى على إعادة المحاولة للاستمرار."
az: "${PRODUCT_NAME}, bağlanıla bilmir. \nZəhmət olmasa əllə bağlayın və davam etmək üçün \"Yenidən sına\"ya klikləyin."
af: "${PRODUCT_NAME} kan nie toegemaak word nie. \nMaak dit asb. handmatig toe en klik Probeer weer om voort te gaan."
bn: "${PRODUCT_NAME} বন্ধ করা যাবে না। \nঅনুগ্রহ করে ম্যানুয়ালি এটি বন্ধ করুন এবং চালিয়ে যেতে Retry এ ক্লিক করুন।"
ca: "No es pot tancar el ${PRODUCT_NAME}. \nTanqueu-lo manualment i cliqueu a tornar-ho a provar per continuar."
cs: "Aplikaci ${PRODUCT_NAME} se nepodařilo zavřít. \nZavřete ji ručně a poté klikněte na Opakovat pro pokračování."
cy: "Nid oes modd cau ${PRODUCT_NAME}. \nCaewch ef â llaw a chliciwch ar Ailgynnig i barhau."
da: "${PRODUCT_NAME} kan ikke afsluttes \nLuk den manuelt og klik Prøv igen for at fortsætte"
de: "${PRODUCT_NAME} kann nicht geschlossen werden. \nSchließ es bitte manuell und klicke auf »Wiederholen«, um fortzufahren."
eo: "${PRODUCT_NAME} ne povas esti fermita. \nFermu ĝin permane, kaj alklaku „Reprovi“ por daŭrigi."
el: "Το ${PRODUCT_NAME} δεν μπορεί να κλείσει. \nΠαρακαλώ κλείστο χειροκίνητα και πάτα Δοκιμή Ξανά για να συνεχίσεις."
es: "No se puede cerrar ${PRODUCT_NAME}. \nPor favor cierra la aplicación manualmente y haz clic en reintentar para continuar."
et: "${PRODUCT_NAME} ei saa sulgeda. \nPalun sulge see käsitsi ja klõpsa jätkamiseks \"Proovi uuesti\"."
fa: "سیگنال بسته نمی شود \nلطفاً آن را بصورت دستی ببندید و برای ادامه روی تلاش مجدد کلیک کنید"
fi: "${PRODUCT_NAME} ei voi sulkea. \nSulje se itse ja napsauta Yritä uudelleen jatkaaksesi."
fr: "${PRODUCT_NAME} ne peut pas être fermé. \nVeuillez la fermer manuellement et cliquez sur Réessayer pour continuer."
gd: "Cha b urrainn dhuinn ${PRODUCT_NAME} a dhùnadh. \nDùin a làimh e agus briog air “Feuch ris a-rithist” a leantainn air adhart."
he: "${PRODUCT_NAME} לא יכול להיסגר. \nאנא סגור אותו באופן ידני ולחץ על נסה שוב כדי להמשיך."
hi: "सिग्नल बंद नहीं किया जा सकता. \nकृपया इसे मैन्युअल रूप से बंद करें और जारी रखने के लिए रिट्राई पर क्लिक करें."
hu: "Nem sikerült bezárni a ${PRODUCT_NAME}t. \nZárd be kézzel, majd kattints az Újra gombra a folytatáshoz!"
id: "${PRODUCT_NAME} tidak dapat ditutup. \nMohon tutup secara manual dan klik Coba Lagi untuk melanjutkan."
is: "Ekki er hægt að loka ${PRODUCT_NAME}. \nLokaðu því handvirkt og ýttu á 'Reyna aftur' til að halda áfram."
it: "${PRODUCT_NAME} non può essere chiuso. \nPer favore, chiudilo manualmente e clicca su Riprova per continuare."
ja: "${PRODUCT_NAME}が終了できません。\n手動で閉じて、『再試行』をクリックしてください。"
lt: "Nepavyksta užverti ${PRODUCT_NAME}. \nPabandykite ją užverti rankiniu būdu ir norėdami tęsti spustelėkite „Bandyti dar kartą“."
mr: "${PRODUCT_NAME} बंद करता येत नाही. \nकृपया हाताने/मॅन्युअली बंद करा आणि पुढे चालू ठेवण्यासाठी पुन्हा प्रयत्न/रिट्राय वर क्लिक करा"
ms: "${PRODUCT_NAME} tidak boleh ditutup. \nSila tutup secara manual dan klik Cuba Semula untuk meneruskan."
nl_NL: "${PRODUCT_NAME} kan niet automatisch worden afgesloten. \nSluit zelf de ${PRODUCT_NAME} app en klik vervolgens op Opnieuw proberen."
nn: "Kan ikkje lukka ${PRODUCT_NAME}. \nPlease close it manually and click Retry to continue."
pl: "Nie można zamknąć ${PRODUCT_NAME}. \nZamknij aplikację i kliknij Ponów, aby kontynuować."
ps: "${PRODUCT_NAME} نشي تړل کېدای. \nد مهرباني له مخې په مانول ډول یې وتړئ او د ادامې لپاره پر بیا هڅې باندې کلیک وکړئ."
pt_BR: "Não é possível fechar o ${PRODUCT_NAME}. \nFeche a janela do ${PRODUCT_NAME} e clique em Repetir para continuar."
pt_PT: "Não é possível fechar o ${PRODUCT_NAME}. \nPor favor, feche-o manualmente e clique em ´Tentar novamente' para continuar."
ro: "${PRODUCT_NAME} nu poate fi închis \nVă rugăm închideți-l manual și apăsați Reîncercare pentru a continua."
ru: "Не удалось закрыть ${PRODUCT_NAME}. \nПожалуйста, закройте ${PRODUCT_NAME} вручную и нажмите «Повторить», чтобы продолжить."
sk: "${PRODUCT_NAME} nie je možné zatvoriť. \nZatvorte ho ručne a pokračujte kliknutím na položku Opakovať."
sl: "${PRODUCT_NAME} se ne more zapreti. \nPoskusite ga zapreti ročno in kliknite Ponovi za nadaljevanje."
sq: "${PRODUCT_NAME} smund të mbyllet. \nQë të vazhdohet, ju lutemi, mbylleni dorazi dhe klikoni mbi Riprovo."
sr: "${PRODUCT_NAME} не може да се затвори. \nЗатворите га ручно и кликните на Покушај да наставите."
sv: "${PRODUCT_NAME} går inte att stängas. \nVänligen stäng det manuellt och klicka på Försök igen för att fortsätta."
tr: "${PRODUCT_NAME} kapatılamaz. \nLütfen elle kapatın ve devam etmek için Tekrar'a tıklayın"
uk: "Неможливо закрити ${PRODUCT_NAME}. \nЗакрийте його вручну та натисніть Повторити, щоб продовжити."
vi: "${PRODUCT_NAME} không thể đóng \nVui lòng đóng nó theo cách thủ công và nhấp vào Thử lại để tiếp tục."
zh_CN: "${PRODUCT_NAME} 无法关闭。\n请手动关闭它然后单击重试以继续。"
zh_TW: "${PRODUCT_NAME} 無法關閉。\n請手動關閉它然後按一下重試以繼續。"
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: Instaluje se, prosím vyč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 jisti, ž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}?
decompressionFailed:
en: Failed to decompress files. Please try running the installer again.
ar: "‫لقد فشل وينْدوزْ في فك ضغط الملفات. يُرجى محاولة تشغيل أداة التثبيت مرة أخرى."
az: Faylların sıxışdırmasıılmadı. Zəhmət olmasa quraşdırıcını yenidən işə salmağa çalışın.
ca: No s'han pogut descomprimir els fitxers. Si us plau, proveu d'executar l'instal·lador un altre cop.
cs: Nepodařilo se rozbalit soubory. Zkuste prosím instalátor spustit znovu.
cy: Wedi methu â datgywasgu ffeiliau. Ceisiwch redeg y gosodwr eto.
da: Det lykkedes ikke at udpakke filer. Prøv venligst at køre installationsprogrammet igen.
de: Die Dateien konnten nicht entpackt werden. Bitte versuche, das Installationsprogramm erneut auszuführen.
el: Αποτυχία αποσυμπίεσης των αρχείων. Παρακαλούμε ξαναπροσπαθήστε την εγκατάσταση.
eo: Maldensigo de dosieroj malsukcesis. Provu relanĉi la instalilon.
es: Fallo al descomprimir archivos. Inténtalo de nuevo más tarde.
fi: Tiedostojen purkaminen ei onnistunut. Yritä ajaa asennusohjelma uudelleen.
fr: Échec de décompression des fichiers. Veuillez réessayer dexécuter l'installeur.
he: נכשל בחילוץ קבצים. אנא נסה להריץ את המתקין שוב.
hu: Kicsomagolási hiba. Kérlek futtasd a telepítőt újra!
it: Impossibile decomprimere i file. Per favore, prova ad eseguire di nuovo il programma di installazione.
ja: ファイルの解凍に失敗しました。もう一度インストーラーを実行してみてください。
lt: Nepavyko išglaudinti failų. Bandykite paleisti diegimo programą dar kartą.
nl_NL: Het decomprimeren van bestanden is mislukt. Voer het installatiebestand opnieuw uit om te proberen dit probleem te verhelpen.
pl: Nie udało się rozpakować plików. Spróbuj ponownie uruchomić instalator.
pt_BR: Falha ao descompactar os arquivos. Por favor, tente iniciar o instalador novamente.
pt_PT: Falha ao descomprimir ficheiros. Por favor, experimente correr o instalador de novo.
ro: Fișierele nu au putut fi dezarhivate. Te rugăm să încerci din nou instalarea.
ru: Не удалось разархивировать файлы. Пожалуйста, попробуйте запустить установщик заново.
sk: Nepodarilo sa rozbaliť súbory. Skúste znova spustiť inštalačný program.
sl: Neuspešno razširjanje datotek. Poskusite ponovno zagnati inštalacijo.
sq: Su arrit të çngjeshen kartela. Ju lutemi, provoni të xhironi sërish instaluesin.
sr: Декомпримовање датотека није успело. Покушајте поново да покренете инсталатер.
sv_SE: Det gick inte att dekomprimera filer. Försök att köra installationsprogrammet igen.
uk: Не вдалось розархівувати файли. Будь ласка, спробуйте запустити встановлювач знов.
zh_TW: 解壓縮檔案失敗。 請嘗試再次執行安裝程式。
uninstallFailed:
en: Failed to uninstall old application files. Please try running the installer again.
ar: ‫لقد فشل إلغاء التثبيت ملفات التطبيق. يُرجى محاولة تشغيل أداة التثبيت مرة أخرى.
az: Köhnə tətbiq faylları silinmədi. Zəhmət olmasa quraşdırıcını yenidən işə salmağa çalışın.
ca: No s'han pogut desinstal·lar els fitxers d'aplicacions antics. Si us plau, proveu d'executar l'instal·lador un altre cop.
cs: Nepodařilo se odinstalovat staré soubory aplikace. Zkuste prosím instalátor spustit znovu.
cy: Wedi methu â dadosod hen ffeiliau rhaglen. Ceisiwch redeg y gosodwr eto.
da: Det lykkedes ikke at afinstallere gamle applikationsfiler. Prøv venligst at køre installationsprogrammet igen.
de: Die alten Anwendungsdateien konnten nicht deinstalliert werden. Bitte versuche, das Installationsprogramm erneut auszuführen.
el: Δεν ήταν δυνατή η απεγκατάσταση των παλιών αρχείων εφαρμογής. Ξαναπροσπαθήστε την απεγκατάσταση αργότερα.
eo: Malinstalo de malnovaj aplikaĵaj dosieroj malsukcesis. Provu relanĉi la instalilon.
es: Fallo al desinstalar archivos antiguos de la aplicación. Inténtalo de nuevo más tarde.
fi: Vanhojen sovellustiedostojen poisto epäonnistui. Yritä ajaa asennusohjelma uudelleen.
fr: Échec de désinstallation des anciens fichiers d'application . Veuillez réessayer dexécuter l'installeur.
he: נכשל בהסרת קבצים של היישום הישן. אנא נסה להריץ את המתקין שוב.
hu: A régi alkalmazás állományait nem sikerült törölni. Kérlek futtasd a telepítőt újra!
it: Impossibile disinstallare i vecchi file dell'applicazione. Per favore, prova ad eseguire di nuovo il programma di installazione.
ja: 古いアプリケーションファイルのアンインストールに失敗しました。もう一度インストーラーを実行してみてください。
lt: Nepavyko pašalinti senos programos failų. Bandykite paleisti diegimo programą dar kartą.
nl: Het deïnstalleren van oude applicatiebestanden is mislukt. Voer het installatiebestand opnieuw uit om te proberen dit probleem te verhelpen.
pl: Nie udało się usunąć plików starej wersji aplikacji. Spróbuj ponownie uruchomić instalator.
pt_BR: Falha ao desinstalar os arquivos do aplicativo antigo. Por favor, tente iniciar o instalador novamente.
pt_PT: Falha ao desinstalar os ficheiros da aplicação antiga. Por favor, experimente correr novamente o instalador.
ro: Nu s-a putut dezinstala vechea aplicație. Te rugăm să încerci din nou instalarea.
ru: Не удалось удалить старые файлы приложения. Пожалуйста, попробуйте запустить установщик заново.
sk: Nepodarilo sa odinštalovať staré súbory aplikácie. Skúste znova spustiť inštalačný program.
sl: Neuspešno odnameščanje starih datotek. Poskusite ponovno zagnati inštalacijo.
sq: Su arrit të çinstalohen kartela të vjetra aplikacioni. Ju lutemi, xhironi sërish instaluesin.
sr: Деинсталирање старих датотека апликације није успело. Покушајте поново да покренете инсталатер.
sv: Det gick inte att avinstallera gamla programfiler. Försök att köra installationsprogrammet igen.
uk: Не вдалось видалити старі файли застосунку. Будь ласка, спробуйте запустити встановлювач знов.
zh_TW: 無法俺安裝舊的應用程式檔案。 請嘗試再次執行安裝程式。

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,91 @@
!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 "$PLUGINSDIR\app"
!ifdef UNPACK_DIR_NAME
StrCpy $INSTDIR "$TEMP\${UNPACK_DIR_NAME}"
!endif
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 $EXEDIR
RMDir /r $INSTDIR
SectionEnd

View File

@@ -0,0 +1,245 @@
Function un.checkAppRunning
!insertmacro CHECK_APP_RUNNING
FunctionEnd
Function un.onInit
SetOutPath $INSTDIR
${LogSet} on
!insertmacro check64BitAndSetRegView
${If} ${Silent}
call un.checkAppRunning
${else}
!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)
call un.checkAppRunning
SetSilent silent
!endif
${endIf}
!insertmacro initMultiUser
!ifmacrodef customUnInit
!insertmacro customUnInit
!endif
FunctionEnd
Function un.atomicRMDir
Exch $R0
Push $R1
Push $R2
Push $R3
StrCpy $R3 "$INSTDIR$R0\*.*"
FindFirst $R1 $R2 $R3
loop:
StrCmp $R2 "" break
StrCmp $R2 "." continue
StrCmp $R2 ".." continue
IfFileExists "$INSTDIR$R0\$R2\*.*" isDir isNotDir
isDir:
CreateDirectory "$PLUGINSDIR\old-install$R0\$R2"
Push "$R0\$R2"
Call un.atomicRMDir
Pop $R3
${if} $R3 != 0
Goto done
${endIf}
Goto continue
isNotDir:
ClearErrors
Rename "$INSTDIR$R0\$R2" "$PLUGINSDIR\old-install$R0\$R2"
# Ignore errors when renaming ourselves.
StrCmp "$R0\$R2" "${UNINSTALL_FILENAME}" 0 +2
ClearErrors
IfErrors 0 +3
StrCpy $R3 "$INSTDIR$R0\$R2"
Goto done
continue:
FindNext $R1 $R2
Goto loop
break:
StrCpy $R3 0
done:
FindClose $R1
StrCpy $R0 $R3
Pop $R3
Pop $R2
Pop $R1
Exch $R0
FunctionEnd
Function un.restoreFiles
Exch $R0
Push $R1
Push $R2
Push $R3
StrCpy $R3 "$PLUGINSDIR\old-install$R0\*.*"
FindFirst $R1 $R2 $R3
loop:
StrCmp $R2 "" break
StrCmp $R2 "." continue
StrCmp $R2 ".." continue
IfFileExists "$INSTDIR$R0\$R2\*.*" isDir isNotDir
isDir:
CreateDirectory "$INSTDIR$R0\$R2"
Push "$R0\$R2"
Call un.restoreFiles
Pop $R3
Goto continue
isNotDir:
Rename "$PLUGINSDIR\old-install$R0\$R2" "$INSTDIR$R0\$R2"
continue:
FindNext $R1 $R2
Goto loop
break:
StrCpy $R0 0
FindClose $R1
Pop $R3
Pop $R2
Pop $R1
Exch $R0
FunctionEnd
Section "un.install"
# for assisted installer we check it here to show progress
!ifndef ONE_CLICK
${IfNot} ${Silent}
call un.checkAppRunning
${endIf}
!endif
!insertmacro setLinkVars
# delete the installed files
!ifmacrodef customRemoveFiles
!insertmacro customRemoveFiles
!else
${if} ${isUpdated}
CreateDirectory "$PLUGINSDIR\old-install"
Push ""
Call un.atomicRMDir
Pop $R0
${if} $R0 != 0
DetailPrint "File is busy, aborting: $R0"
# Attempt to restore previous directory
Push ""
Call un.restoreFiles
Pop $R0
Abort `Can't rename "$INSTDIR" to "$PLUGINSDIR\old-install".`
${endif}
${endif}
# Remove all files (or remaining shallow directories from the block above)
RMDir /r $INSTDIR
!endif
${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
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