Skip to content

Commit a4eeade

Browse files
committed
feat(nsis): boring per-machine only installer
1 parent b7b18bc commit a4eeade

File tree

9 files changed

+98
-68
lines changed

9 files changed

+98
-68
lines changed

docs/Options.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ In the development `package.json` custom `build` field can be specified to custo
2525
As you can see, you need to customize MacOS options only if you want to provide custom `x, y`.
2626
Don't customize paths to background and icon, — just follow conventions.
2727

28-
Here documented only `electron-builder` specific options:
29-
3028
<!-- do not edit. start of generated block -->
3129

3230
<a name="AppMetadata"></a>
@@ -50,7 +48,7 @@ Here documented only `electron-builder` specific options:
5048
## `.build`
5149
| Name | Description
5250
| --- | ---
53-
| 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>
51+
| 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>
5452
| 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>
5553
| copyright | <a name="BuildMetadata-copyright"></a>The human-readable copyright line for the app. Defaults to `Copyright © year author`.
5654
| 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>
@@ -136,7 +134,7 @@ See [NSIS target notes](https://github.com/electron-userland/electron-builder/wi
136134
| Name | Description
137135
| --- | ---
138136
| oneClick | <a name="NsisOptions-oneClick"></a>One-click installation. Defaults to `true`.
139-
| perMachine | <a name="NsisOptions-perMachine"></a>Install per all users (per-machine). Defaults to `false`.
137+
| 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>
140138
| 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`.
141139
| runAfterFinish | <a name="NsisOptions-runAfterFinish"></a>*one-click installer only.* Run application after finish. Defaults to `true`.
142140
| guid | <a name="NsisOptions-guid"></a>See [GUID vs Application Name](https://github.com/electron-userland/electron-builder/wiki/NSIS#guid-vs-application-name).

src/metadata.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,7 @@ export interface BuildMetadata {
8585
/*
8686
The application id. Used as
8787
[CFBundleIdentifier](https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-102070) for MacOS and as
88-
[Application User Model ID](https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx) for Windows.
89-
90-
For windows only NSIS target supports it. Squirrel.Windows is not fixed yet.
88+
[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).
9189
9290
Defaults to `com.electron.${name}`. It is strongly recommended that an explicit ID be set.
9391
*/
@@ -388,7 +386,11 @@ export interface NsisOptions {
388386
readonly oneClick?: boolean | null
389387

390388
/*
391-
Install per all users (per-machine). Defaults to `false`.
389+
Defaults to `false`.
390+
391+
If `oneClick` is `true` (default): Install per all users (per-machine).
392+
393+
If `oneClick` is `false`: no install mode installer page (choice per-machine or per-user), always install per-machine.
392394
*/
393395
readonly perMachine?: boolean | null
394396

src/packager/mac.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,13 @@ export async function createApp(opts: ElectronPackagerOptions, appOutDir: string
9191
const protocols = asArray(packager.devMetadata.build.protocols).concat(asArray(packager.platformSpecificBuildOptions.protocols))
9292
if (protocols.length > 0) {
9393
appPlist.CFBundleURLTypes = protocols.map(protocol => {
94+
const schemes = asArray(protocol.schemes)
95+
if (schemes.length === 0) {
96+
throw new Error(`Protocol "${protocol.name}": must be at least one scheme specified`)
97+
}
9498
return {
9599
CFBundleURLName: protocol.name,
96-
CFBundleURLSchemes: protocol.schemes.slice()
100+
CFBundleURLSchemes: schemes.slice()
97101
}
98102
})
99103
}

templates/nsis/boringInstaller.nsh

Lines changed: 60 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,89 @@
1-
!include multiUserUi.nsh
1+
!include UAC.nsh
2+
3+
!ifndef INSTALL_MODE_PER_ALL_USERS
4+
!include multiUserUi.nsh
5+
!endif
26

37
!ifndef BUILD_UNINSTALLER
48
Function StartApp
59
!insertmacro UAC_AsUser_ExecShell "" "$SMPROGRAMS\${PRODUCT_FILENAME}.lnk" "" "" ""
610
FunctionEnd
711

8-
Function GuiInit
9-
!insertmacro UAC_PageElevation_OnGuiInit
10-
FunctionEnd
11-
1212
!define MUI_FINISHPAGE_RUN
1313
!define MUI_FINISHPAGE_RUN_FUNCTION "StartApp"
1414

15-
!define MUI_CUSTOMFUNCTION_GUIINIT GuiInit
15+
!ifndef INSTALL_MODE_PER_ALL_USERS
16+
!insertmacro PAGE_INSTALL_MODE
17+
Function GuiInit
18+
!insertmacro UAC_PageElevation_OnGuiInit
19+
FunctionEnd
1620

17-
!insertmacro PAGE_INSTALL_MODE
21+
!define MUI_CUSTOMFUNCTION_GUIINIT GuiInit
22+
!endif
1823
!insertmacro MUI_PAGE_INSTFILES
1924
!insertmacro MUI_PAGE_FINISH
2025
!else
21-
!insertmacro PAGE_INSTALL_MODE
26+
!ifndef INSTALL_MODE_PER_ALL_USERS
27+
!insertmacro PAGE_INSTALL_MODE
28+
!endif
2229
!insertmacro MUI_UNPAGE_INSTFILES
2330
!endif
2431

2532
!macro initMultiUser
26-
!insertmacro UAC_PageElevation_OnInit
33+
!ifdef INSTALL_MODE_PER_ALL_USERS
34+
!insertmacro setInstallModePerAllUsers
35+
!else
36+
!insertmacro UAC_PageElevation_OnInit
2737

28-
${If} ${UAC_IsInnerInstance}
29-
${AndIfNot} ${UAC_IsAdmin}
30-
# special return value for outer instance so it knows we did not have admin rights
31-
SetErrorLevel 0x666666
32-
Quit
33-
${EndIf}
38+
${If} ${UAC_IsInnerInstance}
39+
${AndIfNot} ${UAC_IsAdmin}
40+
# special return value for outer instance so it knows we did not have admin rights
41+
SetErrorLevel 0x666666
42+
Quit
43+
${EndIf}
3444

35-
!ifndef MULTIUSER_INIT_TEXT_ADMINREQUIRED
36-
!define MULTIUSER_INIT_TEXT_ADMINREQUIRED "$(^Caption) requires administrator privileges."
37-
!endif
45+
!ifndef MULTIUSER_INIT_TEXT_ADMINREQUIRED
46+
!define MULTIUSER_INIT_TEXT_ADMINREQUIRED "$(^Caption) requires administrator privileges."
47+
!endif
3848

39-
!ifndef MULTIUSER_INIT_TEXT_POWERREQUIRED
40-
!define MULTIUSER_INIT_TEXT_POWERREQUIRED "$(^Caption) requires at least Power User privileges."
41-
!endif
49+
!ifndef MULTIUSER_INIT_TEXT_POWERREQUIRED
50+
!define MULTIUSER_INIT_TEXT_POWERREQUIRED "$(^Caption) requires at least Power User privileges."
51+
!endif
4252

43-
!ifndef MULTIUSER_INIT_TEXT_ALLUSERSNOTPOSSIBLE
44-
!define MULTIUSER_INIT_TEXT_ALLUSERSNOTPOSSIBLE "Your user account does not have sufficient privileges to install $(^Name) for all users of this computer."
45-
!endif
53+
!ifndef MULTIUSER_INIT_TEXT_ALLUSERSNOTPOSSIBLE
54+
!define MULTIUSER_INIT_TEXT_ALLUSERSNOTPOSSIBLE "Your user account does not have sufficient privileges to install $(^Name) for all users of this computer."
55+
!endif
4656

47-
# checks registry for previous installation path (both for upgrading, reinstall, or uninstall)
48-
StrCpy $hasPerMachineInstallation "0"
49-
StrCpy $hasPerUserInstallation "0"
57+
# checks registry for previous installation path (both for upgrading, reinstall, or uninstall)
58+
StrCpy $hasPerMachineInstallation "0"
59+
StrCpy $hasPerUserInstallation "0"
5060

51-
# set installation mode to setting from a previous installation
52-
ReadRegStr $perMachineInstallationFolder HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation
53-
${if} $perMachineInstallationFolder != ""
54-
StrCpy $hasPerMachineInstallation "1"
55-
${endif}
61+
# set installation mode to setting from a previous installation
62+
ReadRegStr $perMachineInstallationFolder HKLM "${INSTALL_REGISTRY_KEY}" InstallLocation
63+
${if} $perMachineInstallationFolder != ""
64+
StrCpy $hasPerMachineInstallation "1"
65+
${endif}
5666

57-
ReadRegStr $perUserInstallationFolder HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation
58-
${if} $perUserInstallationFolder != ""
59-
StrCpy $hasPerUserInstallation "1"
60-
${endif}
67+
ReadRegStr $perUserInstallationFolder HKCU "${INSTALL_REGISTRY_KEY}" InstallLocation
68+
${if} $perUserInstallationFolder != ""
69+
StrCpy $hasPerUserInstallation "1"
70+
${endif}
6171

62-
${if} $hasPerUserInstallation == "1"
63-
${andif} $hasPerMachineInstallation == "0"
64-
!insertmacro setInstallModePerUser
65-
${elseif} $hasPerUserInstallation == "0"
66-
${andif} $hasPerMachineInstallation == "1"
67-
!insertmacro setInstallModePerAllUsers
68-
${else}
69-
# if there is no installation, or there is both per-user and per-machine
70-
!ifdef INSTALL_MODE_PER_ALL_USERS
71-
!insertmacro setInstallModePerAllUsers
72-
!else
72+
${if} $hasPerUserInstallation == "1"
73+
${andif} $hasPerMachineInstallation == "0"
7374
!insertmacro setInstallModePerUser
74-
!endif
75-
${endif}
75+
${elseif} $hasPerUserInstallation == "0"
76+
${andif} $hasPerMachineInstallation == "1"
77+
!insertmacro setInstallModePerAllUsers
78+
${else}
79+
# if there is no installation, or there is both per-user and per-machine
80+
!ifdef INSTALL_MODE_PER_ALL_USERS
81+
!insertmacro setInstallModePerAllUsers
82+
!else
83+
!insertmacro setInstallModePerUser
84+
!endif
85+
${endif}
86+
!endif
7687
!macroend
7788

7889
!include "langs.nsh"

templates/nsis/install.nsh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,13 @@ ${IfNot} ${Silent}
1616
!endif
1717
${endif}
1818

19-
!insertmacro CHECK_APP_RUNNING "install"
19+
!ifdef ONE_CLICK
20+
!insertmacro CHECK_APP_RUNNING "install"
21+
!else
22+
${IfNot} ${UAC_IsInnerInstance}
23+
!insertmacro CHECK_APP_RUNNING "install"
24+
${endif}
25+
!endif
2026

2127
ReadRegStr $R0 SHCTX "${UNINSTALL_REGISTRY_KEY}" UninstallString
2228
${if} $R0 != ""

templates/nsis/installer.nsi

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
!include "multiUser.nsh"
44
!include "allowOnlyOneInstallerInstace.nsh"
55

6+
!ifdef INSTALL_MODE_PER_ALL_USERS
7+
RequestExecutionLevel admin
8+
!else
9+
RequestExecutionLevel user
10+
!endif
11+
612
!ifdef ONE_CLICK
713
!include "oneClick.nsh"
814
!else

templates/nsis/multiUserUi.nsh

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
!include nsDialogs.nsh
2-
!include UAC.nsh
3-
4-
RequestExecutionLevel user
52

63
Var HasTwoAvailableOptions
74
Var RadioButtonLabel1

templates/nsis/oneClick.nsh

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,6 @@
1818

1919
!insertmacro MUI_LANGUAGE "English"
2020

21-
!ifdef INSTALL_MODE_PER_ALL_USERS
22-
RequestExecutionLevel admin
23-
!else
24-
RequestExecutionLevel user
25-
!endif
26-
2721
!macro initMultiUser
2822
!ifdef INSTALL_MODE_PER_ALL_USERS
2923
!insertmacro setInstallModePerAllUsers

test/src/nsisTest.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,18 @@ test.ifNotCiOsx("boring", app({
117117
}
118118
}, {signed: true}))
119119

120+
test.ifNotCiOsx("boring, only perMachine", app({
121+
targets: nsisTarget,
122+
devMetadata: {
123+
build: {
124+
nsis: {
125+
oneClick: false,
126+
perMachine: true,
127+
}
128+
}
129+
}
130+
}))
131+
120132
test.ifNotCiOsx("installerHeaderIcon", () => {
121133
let headerIconPath: string | null = null
122134
return assertPack("test-app-one", {

0 commit comments

Comments
 (0)