This commit is contained in:
root
2025-11-25 09:56:15 +03:00
commit 68c8f0e80d
23717 changed files with 3200521 additions and 0 deletions

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<!--suppress XmlUnusedNamespaceDeclaration -->
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities">
<!-- use single quotes to avoid double quotes escaping in the publisher value -->
<Identity Name="${identityName}"
ProcessorArchitecture="${arch}"
Publisher='${publisher}'
Version="${version}" />
<Properties>
<DisplayName>${displayName}</DisplayName>
<PublisherDisplayName>${publisherDisplayName}</PublisherDisplayName>
<Description>${description}</Description>
<Logo>${logo}</Logo>
</Properties>
<Resources>
${resourceLanguages}
</Resources>
<Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="${minVersion}" MaxVersionTested="${maxVersionTested}" />
</Dependencies>
<Capabilities>
<rescap:Capability Name="runFullTrust"/>
</Capabilities>
<Applications>
<Application Id="${applicationId}" Executable="${executable}" EntryPoint="Windows.FullTrustApplication">
<uap:VisualElements
BackgroundColor="${backgroundColor}"
DisplayName="${displayName}"
Square150x150Logo="${square150x150Logo}"
Square44x44Logo="${square44x44Logo}"
Description="${description}">
${lockScreen}
${defaultTile}
${splashScreen}
</uap:VisualElements>
${extensions}
</Application>
</Applications>
</Package>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<resources targetOsVersion="10.0.0" majorVersion="1">
<packaging>
<autoResourcePackage qualifier="Language"/>
<autoResourcePackage qualifier="Scale"/>
<autoResourcePackage qualifier="DXFeatureLevel"/>
</packaging>
<index root="\" startIndexAt="\">
<default>
<qualifier name="Language" value="en-US"/>
<qualifier name="Contrast" value="standard"/>
<qualifier name="Scale" value="100"/>
<qualifier name="HomeRegion" value="001"/>
<qualifier name="TargetSize" value="256"/>
<qualifier name="LayoutDirection" value="LTR"/>
<qualifier name="Theme" value="dark"/>
<qualifier name="AlternateForm" value=""/>
<qualifier name="DXFeatureLevel" value="DX9"/>
<qualifier name="Configuration" value=""/>
<qualifier name="DeviceFamily" value="Universal"/>
<qualifier name="Custom" value=""/>
</default>
<indexer-config type="folder" foldernameAsQualifier="true" filenameAsQualifier="true" qualifierDelimiter="."/>
<indexer-config type="resw" convertDotsToSlashes="true" initialPath=""/>
<indexer-config type="resjson" initialPath=""/>
<indexer-config type="PRI"/>
</index>
</resources>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- https://github.com/electron/electron-notarize#prerequisites -->
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<!-- https://github.com/electron-userland/electron-builder/issues/3940 -->
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 832 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 630 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

View File

@ -0,0 +1,20 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-13 -13 58.2 58.4">
<style>
.st0{
fill: #000;
}
.circ{
stroke: #000;
fill: white;
stroke-wdith: 1;
}
</style>
<circle class="circ" cx="16.1" cy="16.1" r="25"/>
<g> <!-- viewBox="0 0 32.2 32.4" -->
<circle class="st0" cx="5.5" cy="5.5" r="5.5"/>
<circle class="st0" cx="26.6" cy="5.5" r="5.5"/>
<circle class="st0" cx="5.5" cy="26.9" r="5.5"/>
<circle class="st0" cx="26.6" cy="26.9" r="5.5"/>
<path transform="rotate(-45.361 16.087 16.23)" class="st0" d="M1.1 15.1h30v2.3h-30z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 575 B

View File

@ -0,0 +1,22 @@
#!/bin/bash
if type update-alternatives 2>/dev/null >&1; then
# Remove previous link if it doesn't use update-alternatives
if [ -L '/usr/bin/${executable}' -a -e '/usr/bin/${executable}' -a "`readlink '/usr/bin/${executable}'`" != '/etc/alternatives/${executable}' ]; then
rm -f '/usr/bin/${executable}'
fi
update-alternatives --install '/usr/bin/${executable}' '${executable}' '/opt/${sanitizedProductName}/${executable}' 100 || ln -sf '/opt/${sanitizedProductName}/${executable}' '/usr/bin/${executable}'
else
ln -sf '/opt/${sanitizedProductName}/${executable}' '/usr/bin/${executable}'
fi
# SUID chrome-sandbox for Electron 5+
chmod 4755 '/opt/${sanitizedProductName}/chrome-sandbox' || true
if hash update-mime-database 2>/dev/null; then
update-mime-database /usr/share/mime || true
fi
if hash update-desktop-database 2>/dev/null; then
update-desktop-database /usr/share/applications || true
fi

View File

@ -0,0 +1,8 @@
#!/bin/bash
# Delete the link to the binary
if type update-alternatives >/dev/null 2>&1; then
update-alternatives --remove '${executable}' '/usr/bin/${executable}'
else
rm -f '/usr/bin/${executable}'
fi

View File

@ -0,0 +1,6 @@
[Desktop Entry]
Name=<%= title %>
Comment=<%= comment %>
Exec=<%= executable %>
Terminal=false
Type=Application

View File

@ -0,0 +1,116 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<!-- https://blogs.msdn.microsoft.com/gremlininthemachine/2006/12/05/msi-wix-and-unicode/ -->
<Product Id="*" Name="${productName}" UpgradeCode="${upgradeCode}" Version="${version}" Language="1033" Codepage="65001" Manufacturer="${manufacturer}">
<Package Compressed="yes" InstallerVersion="500"/>
<Condition Message="Windows 7 and above is required"><![CDATA[Installed OR VersionNT >= 601]]></Condition>
<!--
AllowSameVersionUpgrades:
When set to no (the default), installing a product with the same version and upgrade code (but different product code) is allowed and treated by MSI as two products.
When set to yes, WiX sets the msidbUpgradeAttributesVersionMaxInclusive attribute, which tells MSI to treat a product with the same version as a major upgrade.
So, AllowSameVersionUpgrades="yes" allows to build and test MSI with the same version, and previously installed app will be removed.
-->
<MajorUpgrade AllowSameVersionUpgrades="yes" DowngradeErrorMessage='A newer version of "[ProductName]" is already installed.'/>
<MediaTemplate CompressionLevel="${compressionLevel}" EmbedCab="yes"/>
<Property Id="WIXUI_INSTALLDIR" Value="APPLICATIONFOLDER"/>
<Property Id="ApplicationFolderName" Value="${installationDirectoryWixName}"/>
<Property Id="WixAppFolder" Value="WixPerUserFolder"/>
<Property Id="DISABLEADVTSHORTCUTS" Value="1"/>
{{ if (iconPath) { }}
<Icon Id="${iconId}" SourceFile="${iconPath}"/>
<Property Id="ARPPRODUCTICON" Value="${iconId}"/>
{{ } -}}
{{ if (isRunAfterFinish) { }}
<CustomAction Id="runAfterFinish" FileKey="mainExecutable" ExeCommand="" Execute="immediate" Impersonate="yes" Return="asyncNoWait"/>
{{ if (!isAssisted) { }}
<!-- https://stackoverflow.com/questions/1871531/launch-after-install-with-no-ui -->
<InstallExecuteSequence>
<Custom Action="runAfterFinish" After="InstallFinalize">NOT Installed AND UILevel >= 4</Custom>
</InstallExecuteSequence>
{{ } -}}
{{ } -}}
{{ if (isPerMachine) { }}
<Property Id="ALLUSERS" Secure="yes" Value="1"/>
{{ } else { }}
<Property Id="ALLUSERS" Secure="yes" Value="2"/>
{{ } -}}
<Property Id="MSIINSTALLPERUSER" Secure="yes" Value="1"/>
{{ if (isAssisted) { }}
<WixVariable Id="WixUISupportPerUser" Value="1" Overridable="yes"/>
<WixVariable Id="WixUISupportPerMachine" Value="1" Overridable="yes"/>
{{ if (isPerMachine) { }}
<WixVariable Id="WixUISupportPerUser" Value="0"/>
{{ } -}}
{{ if (isRunAfterFinish) { }}
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value="1"/>
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="Run ${productName}"/>
<UI>
<Publish Dialog="ExitDialog" Control="Finish" Event="DoAction" Value="runAfterFinish">WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 AND NOT Installed</Publish>
</UI>
{{ } -}}
<UIRef Id="WixUI_InstallDir"/>
<UI>
<Publish Dialog="WelcomeDlg" Control="Next" Event="SpawnWaitDialog" Value="WaitForCostingDlg" Order="2">1 OR CostingComplete = 1</Publish>
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="InstallScopeDlg" Order="2">NOT Installed</Publish>
<Publish Dialog="InstallScopeDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="1">1</Publish>
<Publish Dialog="InstallScopeDlg" Control="Next" Property="WixAppFolder" Value="WixPerUserFolder" Order="1">!(wix.WixUISupportPerUser) AND NOT Privileged</Publish>
<Publish Dialog="InstallScopeDlg" Control="Next" Property="WixAppFolder" Value="WixPerMachineFolder" Order="2">NOT !(wix.WixUISupportPerUser)</Publish>
<Publish Dialog="InstallScopeDlg" Control="Next" Property="ALLUSERS" Value="{}" Order="3">WixAppFolder = "WixPerUserFolder"</Publish>
<Publish Dialog="InstallScopeDlg" Control="Next" Property="ALLUSERS" Value="1" Order="4">WixAppFolder = "WixPerMachineFolder"</Publish>
<!-- Run 'FindRelatedProducts' again after changing the install scope, because its first run might have ignored an existing installation based on the default scope at the time. https://stackoverflow.com/a/35064434 -->
<Publish Dialog="InstallScopeDlg" Control="Next" Event="DoAction" Value="FindRelatedProducts" Order="5">1</Publish>
<Publish Dialog="InstallScopeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="6">WixAppFolder = "WixPerUserFolder"</Publish>
<Publish Dialog="InstallScopeDlg" Control="Next" Event="NewDialog" Value="InstallDirDlg" Order="7">WixAppFolder = "WixPerMachineFolder"</Publish>
<Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="InstallScopeDlg" Order="2">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="2">1</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="InstallScopeDlg" Order="2">NOT Installed</Publish>
</UI>
{{ } -}}
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="${programFilesId}">
{{ if (menuCategory) { }}
<Directory Id="COMPANYDIR" Name="${menuCategory}">
{{ } -}}
<Directory Id="APPLICATIONFOLDER" Name="${installationDirectoryWixName}"/>
{{ if (menuCategory) { }}
</Directory>
{{ } -}}
</Directory>
<!-- Desktop link -->
{{ if (isCreateDesktopShortcut) { }}
<Directory Id="DesktopFolder" Name="Desktop"/>
{{ } -}}
<!-- Start menu link -->
{{ if (isCreateStartMenuShortcut) { }}
<Directory Id="ProgramMenuFolder"/>
{{ } }}
</Directory>
<!-- Files -->
<Feature Id="ProductFeature" Absent="disallow">
<ComponentGroupRef Id="ProductComponents"/>
</Feature>
{{-dirs}}
<ComponentGroup Id="ProductComponents" Directory="APPLICATIONFOLDER">
{{-files}}
</ComponentGroup>
</Product>
</Wix>

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<!-- https://blogs.msdn.microsoft.com/gremlininthemachine/2006/12/05/msi-wix-and-unicode/ -->
<!-- https://mistake.computer/2020/04/05/msi-exe-wrapper.html -->
<Product Id="${productId}" Name="${productName}" UpgradeCode="${upgradeCode}" Version="${version}" Language="1033" Codepage="65001" Manufacturer="${manufacturer}">
<Package Compressed="yes" InstallerVersion="500"/>
<Condition Message="Windows 7 and above is required"><![CDATA[Installed OR VersionNT >= 601]]></Condition>
<!--
AllowSameVersionUpgrades:
When set to no (the default), installing a product with the same version and upgrade code (but different product code) is allowed and treated by MSI as two products.
When set to yes, WiX sets the msidbUpgradeAttributesVersionMaxInclusive attribute, which tells MSI to treat a product with the same version as a major upgrade.
So, AllowSameVersionUpgrades="yes" allows to build and test MSI with the same version, and previously installed app will be removed.
-->
<MajorUpgrade AllowSameVersionUpgrades="yes" DowngradeErrorMessage='A newer version of "[ProductName]" is already installed.'/>
<MediaTemplate CompressionLevel="${compressionLevel}" EmbedCab="yes"/>
<Property Id="DISABLEADVTSHORTCUTS" Value="1"/>
{{ if (iconPath) { }}
<Icon Id="${iconId}" SourceFile="${iconPath}"/>
<Property Id="ARPPRODUCTICON" Value="${iconId}"/>
{{ } -}}
<Property Id="MSIINSTALLPERUSER" Secure="yes" Value="1"/>
<!-- Exe path will be embedded directly -->
<Binary Id="WrappedExe" SourceFile="${exeSourcePath}" />
<!-- Custom Action to Execute embedded exe -->
<CustomAction Id="RunInstaller" Return="check" Execute="deferred"
HideTarget="no" Impersonate="${impersonate}" BinaryKey="WrappedExe" ExeCommand="${wrappedInstallerArgs}" />
<!-- This is just a dummy component to allow wrapping the exe installer -->
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="TempFolder">
<Component Id="EmptyComponent" Guid="7145262D-7149-4F1A-9A69-F377E38F04DA" KeyPath="yes">
<CreateFolder />
</Component>
</Directory>
</Directory>
<!-- Setting the feature to level 0 marks it hidden, so it can't be installed.
That prevents getting this MSI registered as an installed product,
because it has no features of its own to install. -->
<Feature Id="EmptyFeature" Level="0">
<ComponentRef Id="EmptyComponent" />
</Feature>
<InstallExecuteSequence>
<Custom Action="RunInstaller" After="ProcessComponents" />
</InstallExecuteSequence>
</Product>
</Wix>

View File

@ -0,0 +1,47 @@
# NSIS
⚠️ **It is developer documentation.** If your are looking for usage guide, see [user documentation](https://electron.build/configuration/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/configuration/nsis).
We use UUID v5 to generate sha-1 name-based UUID.
http://stackoverflow.com/questions/3029994/convert-uri-to-guid
https://alexandrebrisebois.wordpress.com/2013/11/14/create-predictable-guids-for-your-windows-azure-table-storage-entities/
https://github.com/Squirrel/Squirrel.Windows/pull/658
## Compression
NSIS LZMA compression is slower and worse compared to external `7za` compression. Slower because `7za` is multi-threaded, worse because LZMA codec implementation is outdated and BCJ2 filter is not enabled.
Difference for test app — 4 MB (before: 36.3 after: 32.8).
And compression time is also greatly reduced.
Since NSIS is awesome, no disadvantages in our approach — [compression is disabled](http://nsis.sourceforge.net/Reference/SetCompress) before `File /oname=app.7z "${APP_ARCHIVE}"` and enabled after (it is the reasons why `SOLID` compression is not used).
So, opposite to Squirrel.Windows, archive is not twice compressed.
So, in your custom NSIS scripts you should not use any compression instructions. Only `SetCompress` if you need to disable compression for already archived file.

View File

@ -0,0 +1,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 `%SYSTEMROOT%\System32\cmd.exe /c tasklist /FI "USERNAME eq %USERNAME%" /FI "IMAGENAME eq ${_FILE}" /FO csv | %SYSTEMROOT%\System32\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 `%SYSTEMROOT%\System32\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 `%SYSTEMROOT%\System32\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

View File

@ -0,0 +1,148 @@
base: core20
grade: stable
confinement: strict
parts:
launch-scripts:
plugin: dump
source: scripts
gnome-platform-empty-dirs:
plugin: nil
override-build: >
mkdir -p "$SNAPCRAFT_PART_INSTALL/data-dir/themes"
mkdir -p "$SNAPCRAFT_PART_INSTALL/data-dir/icons"
mkdir -p "$SNAPCRAFT_PART_INSTALL/data-dir/sounds"
mkdir $SNAPCRAFT_PART_INSTALL/gnome-platform
app-files:
plugin: dump
source: app
organize:
'*': app/
stage:
- -app/chrome-sandbox
- -LICENSES.chromium.html
app:
plugin: "nil"
# cd ~ && rm -rf ~/squashfs-root && unsquashfs /media/psf/ramdisk/electron-builder-test/dist/__snap-x64/se-wo-template_1.1.0_amd64.snap
# comm -12 <(ls ~/squashfs-root/usr/lib/x86_64-linux-gnu/) <(ls /snap/gnome-3-28-1804/current/usr/lib/x86_64-linux-gnu/) > /media/psf/Home/f.txt
# run snap-exclude-list.js
stage:
- '-usr/lib/python*'
- '-usr/bin/python*'
- '-var/lib/ucf'
- '-usr/include'
- '-usr/lib/X11'
- '-usr/share'
- '-usr/sbin'
- '-usr/bin'
- "-usr/lib/*/libicudata.*"
- "-usr/lib/*/libicui18n.*"
- "-usr/lib/*/libgtk-*"
- "-usr/lib/*/libgdk-*"
- "-usr/lib/*/glib-*"
- "-usr/lib/*/gtk-*"
- "-usr/lib/*/gdk-*"
- "-usr/lib/*/krb5"
- "-usr/lib/systemd"
- "-usr/lib/glib-networking"
- "-usr/lib/dconf"
- "-usr/lib/*/avahi"
- "-usr/lib/*/gio"
- "-usr/lib/*/libatk*"
- "-usr/lib/*/libatspi*"
- "-usr/lib/*/libavahi*"
- "-usr/lib/*/libcairo*"
- "-usr/lib/*/libcolordprivate*"
- "-usr/lib/*/libcolord*"
- "-usr/lib/*/libcroco*"
- "-usr/lib/*/libcups*"
- "-usr/lib/*/libdatrie*"
- "-usr/lib/*/libdconf*"
- "-usr/lib/*/libepoxy*"
- "-usr/lib/*/libexpatw*"
- "-usr/lib/*/libffi*"
- "-usr/lib/*/libfontconfig*"
- "-usr/lib/*/libfreetype*"
- "-usr/lib/*/libgdk_pixbuf*"
- "-usr/lib/*/libgdk_pixbuf_xlib*"
- "-usr/lib/*/libgio*"
- "-usr/lib/*/libglib*"
- "-usr/lib/*/libgmodule*"
- "-usr/lib/*/libgmp*"
- "-usr/lib/*/libgnutls*"
- "-usr/lib/*/libgobject*"
- "-usr/lib/*/libgraphite2*"
- "-usr/lib/*/libgssapi_krb5*"
- "-usr/lib/*/libgthread*"
- "-usr/lib/*/libharfbuzz*"
- "-usr/lib/*/libhogweed*"
- "-usr/lib/*/libicuio*"
- "-usr/lib/*/libicutest*"
- "-usr/lib/*/libicutu*"
- "-usr/lib/*/libicuuc*"
- "-usr/lib/*/libidn2*"
- "-usr/lib/*/libjbig*"
- "-usr/lib/*/libjpeg*"
- "-usr/lib/*/libjson*"
- "-usr/lib/*/libk5crypto*"
- "-usr/lib/*/libkrb5*"
- "-usr/lib/*/libkrb5support*"
- "-usr/lib/*/liblcms2*"
- "-usr/lib/*/libnettle*"
- "-usr/lib/*/libp11*"
- "-usr/lib/*/libpango*"
- "-usr/lib/*/libpangocairo*"
- "-usr/lib/*/libpangoft2*"
- "-usr/lib/*/libpixman*"
- "-usr/lib/*/libpng16*"
- "-usr/lib/*/libproxy*"
- "-usr/lib/*/librest*"
- "-usr/lib/*/librsvg*"
- "-usr/lib/*/libsecret*"
- "-usr/lib/*/libsoup*"
- "-usr/lib/*/libsqlite3*"
- "-usr/lib/*/libtasn1*"
- "-usr/lib/*/libthai*"
- "-usr/lib/*/libtiff*"
- "-usr/lib/*/libunistring*"
- "-usr/lib/*/libwayland*"
- "-usr/lib/*/libX11*"
- "-usr/lib/*/libXau*"
- "-usr/lib/*/libxcb.so*"
- "-usr/lib/*/libxcb-dri2*"
- "-usr/lib/*/libxcb-dri3*"
- "-usr/lib/*/libxcb-glx*"
- "-usr/lib/*/libxcb-present*"
- "-usr/lib/*/libxcb-render*"
- "-usr/lib/*/libxcb-shm*"
- "-usr/lib/*/libxcb-sync*"
- "-usr/lib/*/libxcb-xfixes*"
- "-usr/lib/*/libXcomposite*"
- "-usr/lib/*/libXcursor*"
- "-usr/lib/*/libXdamage*"
- "-usr/lib/*/libXdmcp*"
- "-usr/lib/*/libXext*"
- "-usr/lib/*/libXfixes*"
- "-usr/lib/*/libXinerama*"
- "-usr/lib/*/libXi*"
- "-usr/lib/*/libxkbcommon*"
- "-usr/lib/*/libxml2*"
- "-usr/lib/*/libXrandr*"
- "-usr/lib/*/libXrender*"
plugs:
gnome-3-28-1804:
interface: content
target: $SNAP/gnome-platform
default-provider: gnome-3-28-1804
gtk-3-themes:
interface: content
target: $SNAP/data-dir/themes
default-provider: gtk-common-themes
icon-themes:
interface: content
target: $SNAP/data-dir/icons
default-provider: gtk-common-themes
sound-themes:
interface: content
target: $SNAP/data-dir/sounds
default-provider: gtk-common-themes