diff --git a/docs/NSIS.md b/docs/NSIS.md index 5fd6ec63c81..9efeab241df 100644 --- a/docs/NSIS.md +++ b/docs/NSIS.md @@ -2,6 +2,33 @@ If you build both ia32 and xha arch, you in any case get one installer. Appropriate arch will be installed automatically. +# Custom NSIS script + +Two options are available — [include](https://github.com/electron-userland/electron-builder/wiki/Options#NsisOptions-include) and [script](https://github.com/electron-userland/electron-builder/wiki/Options#NsisOptions-script). `script` allows you to provide completely different NSIS script. For most cases it is not required as you need only to customise some aspects, but still use well-tested and maintained default NSIS script. So, `include` is recommended. + +Keep in mind — if you customize NSIS script, you should always state about it in the issue reports. And don't expect that your issue will be resolved. + +1. Add file `build/installer.nsh`. +2. Define wanted macro to customise: `customHeader`, `customInit`, `customUnInit`, `customInstall`, `customUnInstall`. Example: + ```nsis + !macro customHeader + !system "echo '' > ${BUILD_RESOURCES_DIR}/customHeader" + !macroend + + !macro customInit + !system "echo '' > ${BUILD_RESOURCES_DIR}/customInit" + !macroend + + !macro customInstall + !system "echo '' > ${BUILD_RESOURCES_DIR}/customInstall" + !macroend + ``` + +* `BUILD_RESOURCES_DIR` and `PROJECT_DIR` are defined. +* `build` is added as `addincludedir` (i.e. you don't need to use `BUILD_RESOURCES_DIR` to include files). +* File associations macro `registerFileAssociations` and `unregisterFileAssociations` are still defined. +* All other electron-builder specific flags (e.g. `ONE_CLICK`) are still defined. + # GUID vs Application Name Windows requires to use registry keys (e.g. INSTALL/UNINSTALL info). Squirrel.Windows simply uses application name as key. diff --git a/docs/Options.md b/docs/Options.md index 2710895fd58..778cc5ec99d 100644 --- a/docs/Options.md +++ b/docs/Options.md @@ -133,9 +133,11 @@ See [NSIS target notes](https://github.com/electron-userland/electron-builder/wi | perMachine | Install per all users (per-machine). Defaults to `false`. | allowElevation | *boring installer only.* Allow requesting for elevation. If false, user will have to restart installer with elevated permissions. Defaults to `true`. | runAfterFinish | *one-click installer only.* Run application after finish. Defaults to `true`. +| guid | See [GUID vs Application Name](https://github.com/electron-userland/electron-builder/wiki/NSIS#guid-vs-application-name). | installerHeader | *boring installer only.* `MUI_HEADERIMAGE`, relative to the project directory. Defaults to `build/installerHeader.bmp` | installerHeaderIcon | *one-click installer only.* The path to header icon (above the progress bar), relative to the project directory. Defaults to `build/installerHeaderIcon.ico` or application icon. -| include | The path to NSIS include script to customize installer. Defaults to `build/installer.nsh` +| include | The path to NSIS include script to customize installer. Defaults to `build/installer.nsh`. See [Custom NSIS script](https://github.com/electron-userland/electron-builder/wiki/NSIS#custom-nsis-script). +| script | The path to NSIS script to customize installer. Defaults to `build/installer.nsi`. See [Custom NSIS script](https://github.com/electron-userland/electron-builder/wiki/NSIS#custom-nsis-script). ### `.build.linux` diff --git a/package.json b/package.json index bcbb3dd13b3..861b14dab7a 100644 --- a/package.json +++ b/package.json @@ -120,7 +120,7 @@ "pre-git": "^3.10.0", "should": "^10.0.0", "ts-babel": "^1.0.3", - "tslint": "3.14.0", + "tslint": "3.14.0-dev.1", "typescript": "^2.1.0-dev.20160726", "whitespace": "^2.0.0" }, diff --git a/src/metadata.ts b/src/metadata.ts index d55d84cd2a3..f2836a3cbb9 100755 --- a/src/metadata.ts +++ b/src/metadata.ts @@ -376,6 +376,9 @@ export interface NsisOptions { */ readonly runAfterFinish?: boolean | null + /* + See [GUID vs Application Name](https://github.com/electron-userland/electron-builder/wiki/NSIS#guid-vs-application-name). + */ readonly guid?: string | null /* @@ -389,9 +392,14 @@ export interface NsisOptions { readonly installerHeaderIcon?: string | null /* - The path to NSIS include script to customize installer. Defaults to `build/installer.nsh` + The path to NSIS include script to customize installer. Defaults to `build/installer.nsh`. See [Custom NSIS script](https://github.com/electron-userland/electron-builder/wiki/NSIS#custom-nsis-script). */ readonly include?: string | null + + /* + The path to NSIS script to customize installer. Defaults to `build/installer.nsi`. See [Custom NSIS script](https://github.com/electron-userland/electron-builder/wiki/NSIS#custom-nsis-script). + */ + readonly script?: string | null } /* diff --git a/src/targets/fpm.ts b/src/targets/fpm.ts index c332641a0d7..94fb1e7f9c9 100644 --- a/src/targets/fpm.ts +++ b/src/targets/fpm.ts @@ -33,16 +33,21 @@ export default class FpmTarget extends TargetEx { const tempDir = await tempDirPromise const defaultTemplatesDir = path.join(__dirname, "..", "..", "templates", "linux") + const packager = this.packager const templateOptions = Object.assign({ // old API compatibility - executable: this.packager.appInfo.productFilename, - }, this.packager.platformSpecificBuildOptions) + executable: packager.appInfo.productFilename, + }, packager.platformSpecificBuildOptions) - const afterInstallTemplate = this.packager.platformSpecificBuildOptions.afterInstall || path.join(defaultTemplatesDir, "after-install.tpl") - const afterInstallFilePath = writeConfigFile(tempDir, afterInstallTemplate, templateOptions) + function getResource(value: string | n, defaultFile: string) { + if (value == null) { + return path.join(defaultTemplatesDir, defaultFile) + } + return path.resolve(packager.projectDir, value) + } - const afterRemoveTemplate = this.packager.platformSpecificBuildOptions.afterRemove || path.join(defaultTemplatesDir, "after-remove.tpl") - const afterRemoveFilePath = writeConfigFile(tempDir, afterRemoveTemplate, templateOptions) + const afterInstallFilePath = writeConfigFile(tempDir, getResource(packager.platformSpecificBuildOptions.afterInstall, "after-install.tpl"), templateOptions) + const afterRemoveFilePath = writeConfigFile(tempDir, getResource(packager.platformSpecificBuildOptions.afterRemove, "after-remove.tpl"), templateOptions) return await BluebirdPromise.all([afterInstallFilePath, afterRemoveFilePath]) } diff --git a/src/targets/nsis.ts b/src/targets/nsis.ts index 80bc4ace7b7..e37d6972ddd 100644 --- a/src/targets/nsis.ts +++ b/src/targets/nsis.ts @@ -202,7 +202,7 @@ export default class NsisTarget extends Target { const fileAssociations = asArray(packager.devMetadata.build.fileAssociations).concat(asArray(packager.platformSpecificBuildOptions.fileAssociations)) let registerFileAssociationsScript = "" let unregisterFileAssociationsScript = "" - let script = await readFile(path.join(nsisTemplatesDir, "installer.nsi"), "utf8") + let script = await readFile((await this.getResource(this.options.script, "installer.nsi")) || path.join(nsisTemplatesDir, "installer.nsi"), "utf8") const customInclude = await this.getResource(this.options.include, "installer.nsh") if (customInclude != null) { @@ -223,7 +223,9 @@ export default class NsisTarget extends Target { script = script.replace("!insertmacro registerFileAssociations", registerFileAssociationsScript) script = script.replace("!insertmacro unregisterFileAssociations", unregisterFileAssociationsScript) - debug(script) + if (debug.enabled) { + process.stdout.write("\n\nNSIS script:\n\n" + script + "\n\n---\nEnd of NSIS script.\n\n") + } await new BluebirdPromise((resolve, reject) => { const command = path.join(nsisPath, binDir, process.platform === "win32" ? "makensis.exe" : "makensis") diff --git a/test/fixtures/installer.nsi b/test/fixtures/installer.nsi new file mode 100644 index 00000000000..24509fb7fab --- /dev/null +++ b/test/fixtures/installer.nsi @@ -0,0 +1,4 @@ +!system "echo '' > ${BUILD_RESOURCES_DIR}/customInstallerScript" + +Section +SectionEnd \ No newline at end of file diff --git a/test/src/winPackagerTest.ts b/test/src/winPackagerTest.ts index 2dab43d41e6..3d510269a7f 100755 --- a/test/src/winPackagerTest.ts +++ b/test/src/winPackagerTest.ts @@ -133,7 +133,7 @@ test.ifNotCiOsx("nsis boring, MUI_HEADER as option", () => { tempDirCreated: projectDir => { installerHeaderPath = path.join(projectDir, "foo.bmp") return copy(getTestAsset("installerHeader.bmp"), installerHeaderPath) - } + }, } ) }) @@ -142,6 +142,18 @@ test.ifDevOrLinuxCi("nsis - custom include", () => assertPack("test-app-one", { targets: Platform.WINDOWS.createTarget(["nsis"]), }, { tempDirCreated: projectDir => copy(getTestAsset("installer.nsh"), path.join(projectDir, "build", "installer.nsh")), + packed: projectDir => BluebirdPromise.all([ + assertThat(path.join(projectDir, "build", "customHeader")).isFile(), + assertThat(path.join(projectDir, "build", "customInit")).isFile(), + assertThat(path.join(projectDir, "build", "customInstall")).isFile(), + ]), +})) + +test.ifDevOrLinuxCi("nsis - custom script", () => assertPack("test-app-one", { + targets: Platform.WINDOWS.createTarget(["nsis"]), +}, { + tempDirCreated: projectDir => copy(getTestAsset("installer.nsi"), path.join(projectDir, "build", "installer.nsi")), + packed: projectDir => assertThat(path.join(projectDir, "build", "customInstallerScript")).isFile(), })) // very slow @@ -152,7 +164,7 @@ test.skip("delta and msi", () => assertPack("test-app-one", { win: { remoteReleases: "https://github.com/develar/__test-app-releases", msi: true, - } + }, } }, } diff --git a/tslint.json b/tslint.json index ab5b4252a12..fb8c50b4991 100644 --- a/tslint.json +++ b/tslint.json @@ -1,5 +1,5 @@ { - "extends": "tslint:latest", + "extends": "tslint:recommended", "rules": { "member-ordering": [ "static-before-instance",