Skip to content

Commit

Permalink
feat(nsis): boring per-machine only installer
Browse files Browse the repository at this point in the history
  • Loading branch information
develar committed Aug 29, 2016
1 parent b7b18bc commit a4eeade
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 68 deletions.
6 changes: 2 additions & 4 deletions docs/Options.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ In the development `package.json` custom `build` field can be specified to custo
As you can see, you need to customize MacOS options only if you want to provide custom `x, y`.
Don't customize paths to background and icon, — just follow conventions.

Here documented only `electron-builder` specific options:

<!-- do not edit. start of generated block -->

<a name="AppMetadata"></a>
Expand All @@ -50,7 +48,7 @@ Here documented only `electron-builder` specific options:
## `.build`
| Name | Description
| --- | ---
| appId | <a name="BuildMetadata-appId"></a><p>The application id. Used as [CFBundleIdentifier](https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-102070) for MacOS and as [Application User Model ID](https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx) for Windows.</p> <p>For windows only NSIS target supports it. Squirrel.Windows is not fixed yet.</p> <p>Defaults to <code>com.electron.${name}</code>. It is strongly recommended that an explicit ID be set.</p>
| appId | <a name="BuildMetadata-appId"></a><p>The application id. Used as [CFBundleIdentifier](https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-102070) for MacOS and as [Application User Model ID](https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx) for Windows (NSIS target only, Squirrel.Windows not supported).</p> <p>Defaults to <code>com.electron.${name}</code>. It is strongly recommended that an explicit ID be set.</p>
| category | <a name="BuildMetadata-category"></a><p>*macOS-only.* The application category type, as shown in the Finder via *View -&gt; Arrange by Application Category* when viewing the Applications directory.</p> <p>For example, <code>&quot;category&quot;: &quot;public.app-category.developer-tools&quot;</code> will set the application category to *Developer Tools*.</p> <p>Valid values are listed in [Apple’s documentation](https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/LaunchServicesKeys.html#//apple_ref/doc/uid/TP40009250-SW8).</p>
| copyright | <a name="BuildMetadata-copyright"></a>The human-readable copyright line for the app. Defaults to `Copyright © year author`.
| asar | <a name="BuildMetadata-asar"></a><p>Whether to package the application’s source code into an archive, using [Electron’s archive format](https://github.com/electron/asar). Defaults to <code>true</code>. Reasons why you may want to disable this feature are described in [an application packaging tutorial in Electron’s documentation](http://electron.atom.io/docs/latest/tutorial/application-packaging/#limitations-on-node-api/).</p> <p>Or you can pass object of any asar options.</p> <p>Node modules, that must be unpacked, will be detected automatically, you don’t need to explicitly set <code>asar.unpackDir</code> - please file issue if this doesn’t work.</p>
Expand Down Expand Up @@ -136,7 +134,7 @@ See [NSIS target notes](https://github.com/electron-userland/electron-builder/wi
| Name | Description
| --- | ---
| oneClick | <a name="NsisOptions-oneClick"></a>One-click installation. Defaults to `true`.
| perMachine | <a name="NsisOptions-perMachine"></a>Install per all users (per-machine). Defaults to `false`.
| perMachine | <a name="NsisOptions-perMachine"></a><p>Defaults to <code>false</code>.</p> <p>If <code>oneClick</code> is <code>true</code> (default): Install per all users (per-machine).</p> <p>If <code>oneClick</code> is <code>false</code>: no install mode installer page (choice per-machine or per-user), always install per-machine.</p>
| allowElevation | <a name="NsisOptions-allowElevation"></a>*boring installer only.* Allow requesting for elevation. If false, user will have to restart installer with elevated permissions. Defaults to `true`.
| runAfterFinish | <a name="NsisOptions-runAfterFinish"></a>*one-click installer only.* Run application after finish. Defaults to `true`.
| guid | <a name="NsisOptions-guid"></a>See [GUID vs Application Name](https://github.com/electron-userland/electron-builder/wiki/NSIS#guid-vs-application-name).
Expand Down
10 changes: 6 additions & 4 deletions src/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,7 @@ export interface BuildMetadata {
/*
The application id. Used as
[CFBundleIdentifier](https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-102070) for MacOS and as
[Application User Model ID](https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx) for Windows.
For windows only NSIS target supports it. Squirrel.Windows is not fixed yet.
[Application User Model ID](https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx) for Windows (NSIS target only, Squirrel.Windows not supported).
Defaults to `com.electron.${name}`. It is strongly recommended that an explicit ID be set.
*/
Expand Down Expand Up @@ -388,7 +386,11 @@ export interface NsisOptions {
readonly oneClick?: boolean | null

/*
Install per all users (per-machine). Defaults to `false`.
Defaults to `false`.
If `oneClick` is `true` (default): Install per all users (per-machine).
If `oneClick` is `false`: no install mode installer page (choice per-machine or per-user), always install per-machine.
*/
readonly perMachine?: boolean | null

Expand Down
6 changes: 5 additions & 1 deletion src/packager/mac.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,13 @@ export async function createApp(opts: ElectronPackagerOptions, appOutDir: string
const protocols = asArray(packager.devMetadata.build.protocols).concat(asArray(packager.platformSpecificBuildOptions.protocols))
if (protocols.length > 0) {
appPlist.CFBundleURLTypes = protocols.map(protocol => {
const schemes = asArray(protocol.schemes)
if (schemes.length === 0) {
throw new Error(`Protocol "${protocol.name}": must be at least one scheme specified`)
}
return {
CFBundleURLName: protocol.name,
CFBundleURLSchemes: protocol.schemes.slice()
CFBundleURLSchemes: schemes.slice()
}
})
}
Expand Down
109 changes: 60 additions & 49 deletions templates/nsis/boringInstaller.nsh
Original file line number Diff line number Diff line change
@@ -1,78 +1,89 @@
!include multiUserUi.nsh
!include UAC.nsh

!ifndef INSTALL_MODE_PER_ALL_USERS
!include multiUserUi.nsh
!endif

!ifndef BUILD_UNINSTALLER
Function StartApp
!insertmacro UAC_AsUser_ExecShell "" "$SMPROGRAMS\${PRODUCT_FILENAME}.lnk" "" "" ""
FunctionEnd

Function GuiInit
!insertmacro UAC_PageElevation_OnGuiInit
FunctionEnd

!define MUI_FINISHPAGE_RUN
!define MUI_FINISHPAGE_RUN_FUNCTION "StartApp"

!define MUI_CUSTOMFUNCTION_GUIINIT GuiInit
!ifndef INSTALL_MODE_PER_ALL_USERS
!insertmacro PAGE_INSTALL_MODE
Function GuiInit
!insertmacro UAC_PageElevation_OnGuiInit
FunctionEnd

!insertmacro PAGE_INSTALL_MODE
!define MUI_CUSTOMFUNCTION_GUIINIT GuiInit
!endif
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!else
!insertmacro PAGE_INSTALL_MODE
!ifndef INSTALL_MODE_PER_ALL_USERS
!insertmacro PAGE_INSTALL_MODE
!endif
!insertmacro MUI_UNPAGE_INSTFILES
!endif

!macro initMultiUser
!insertmacro UAC_PageElevation_OnInit
!ifdef INSTALL_MODE_PER_ALL_USERS
!insertmacro setInstallModePerAllUsers
!else
!insertmacro UAC_PageElevation_OnInit

${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}
${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_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_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
!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"
# 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}
# 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}
ReadRegStr $perUserInstallationFolder HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation
${if} $perUserInstallationFolder != ""
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
${if} $hasPerUserInstallation == "1"
${andif} $hasPerMachineInstallation == "0"
!insertmacro setInstallModePerUser
!endif
${endif}
${elseif} $hasPerUserInstallation == "0"
${andif} $hasPerMachineInstallation == "1"
!insertmacro setInstallModePerAllUsers
${else}
# if there is no installation, or there is both per-user and per-machine
!ifdef INSTALL_MODE_PER_ALL_USERS
!insertmacro setInstallModePerAllUsers
!else
!insertmacro setInstallModePerUser
!endif
${endif}
!endif
!macroend

!include "langs.nsh"
8 changes: 7 additions & 1 deletion templates/nsis/install.nsh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ ${IfNot} ${Silent}
!endif
${endif}

!insertmacro CHECK_APP_RUNNING "install"
!ifdef ONE_CLICK
!insertmacro CHECK_APP_RUNNING "install"
!else
${IfNot} ${UAC_IsInnerInstance}
!insertmacro CHECK_APP_RUNNING "install"
${endif}
!endif

ReadRegStr $R0 SHCTX "${UNINSTALL_REGISTRY_KEY}" UninstallString
${if} $R0 != ""
Expand Down
6 changes: 6 additions & 0 deletions templates/nsis/installer.nsi
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
!include "multiUser.nsh"
!include "allowOnlyOneInstallerInstace.nsh"

!ifdef INSTALL_MODE_PER_ALL_USERS
RequestExecutionLevel admin
!else
RequestExecutionLevel user
!endif

!ifdef ONE_CLICK
!include "oneClick.nsh"
!else
Expand Down
3 changes: 0 additions & 3 deletions templates/nsis/multiUserUi.nsh
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
!include nsDialogs.nsh
!include UAC.nsh

RequestExecutionLevel user

Var HasTwoAvailableOptions
Var RadioButtonLabel1
Expand Down
6 changes: 0 additions & 6 deletions templates/nsis/oneClick.nsh
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,6 @@

!insertmacro MUI_LANGUAGE "English"

!ifdef INSTALL_MODE_PER_ALL_USERS
RequestExecutionLevel admin
!else
RequestExecutionLevel user
!endif

!macro initMultiUser
!ifdef INSTALL_MODE_PER_ALL_USERS
!insertmacro setInstallModePerAllUsers
Expand Down
12 changes: 12 additions & 0 deletions test/src/nsisTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,18 @@ test.ifNotCiOsx("boring", app({
}
}, {signed: true}))

test.ifNotCiOsx("boring, only perMachine", app({
targets: nsisTarget,
devMetadata: {
build: {
nsis: {
oneClick: false,
perMachine: true,
}
}
}
}))

test.ifNotCiOsx("installerHeaderIcon", () => {
let headerIconPath: string | null = null
return assertPack("test-app-one", {
Expand Down

0 comments on commit a4eeade

Please sign in to comment.