diff --git a/packages/electron-builder-squirrel-windows/src/SquirrelWindowsTarget.ts b/packages/electron-builder-squirrel-windows/src/SquirrelWindowsTarget.ts
index 178c4657aef..a78509c49a1 100644
--- a/packages/electron-builder-squirrel-windows/src/SquirrelWindowsTarget.ts
+++ b/packages/electron-builder-squirrel-windows/src/SquirrelWindowsTarget.ts
@@ -161,18 +161,76 @@ export default class SquirrelWindowsTarget extends Target {
fs.copyFileSync(path.join(vendorDirectory, `7z-${resolvedArch}.dll`), path.join(vendorDirectory, "7z.dll"))
}
- private async createNuspecTemplateWithProjectUrl() {
+ private async createNuspecTemplateWithProjectUrl(additionalFiles: { src: string; target: string }[]) {
const templatePath = path.resolve(__dirname, "..", "template.nuspectemplate")
const projectUrl = await this.packager.appInfo.computePackageUrl()
+
+ // Always create a customized template to include additionalFiles
+ const nuspecTemplate = await this.packager.info.tempDirManager.getTempFile({ prefix: "template", suffix: ".nuspectemplate" })
+ let templateContent = await fs.promises.readFile(templatePath, "utf8")
+
+ // Add project URL if available
if (projectUrl != null) {
- const nuspecTemplate = await this.packager.info.tempDirManager.getTempFile({ prefix: "template", suffix: ".nuspectemplate" })
- let templateContent = await fs.promises.readFile(templatePath, "utf8")
const searchString = "<%- copyright %>"
templateContent = templateContent.replace(searchString, `${searchString}\n ${projectUrl}`)
- await fs.promises.writeFile(nuspecTemplate, templateContent)
- return nuspecTemplate
}
- return templatePath
+
+ // Replace the additionalFiles loop with the actual files
+ if (additionalFiles.length > 0) {
+ const additionalFilesContent = additionalFiles.map(f => ` `).join("\n")
+ templateContent = templateContent.replace('<% file src="additionalFiles.src" target="additionalFiles.target" / %>', additionalFilesContent)
+ } else {
+ templateContent = templateContent.replace('<% file src="additionalFiles.src" target="additionalFiles.target" / %>', "")
+ }
+
+ await fs.promises.writeFile(nuspecTemplate, templateContent)
+ return nuspecTemplate
+ }
+
+ private async getAdditionalFiles(appOutDir: string) {
+ const files = await fs.promises.readdir(appOutDir, { withFileTypes: true })
+ const appExe = `${this.exeName}.exe`
+
+ const additionalFiles = files.filter(f => {
+ if (f.isDirectory()) {
+ // Filter out directories already included in template
+ return f.name !== "resources" && f.name !== "locales"
+ }
+
+ // Filter out files already included in template.nuspectemplate
+ const fileName = f.name
+
+ // Files explicitly included in template
+ if (
+ fileName.endsWith(".bin") ||
+ fileName.endsWith(".dll") ||
+ fileName.endsWith(".pak") ||
+ fileName.endsWith(".exe.config") ||
+ fileName.endsWith(".exe.sig") ||
+ fileName.endsWith("_ExecutionStub.exe") ||
+ fileName === "icudtl.dat" ||
+ fileName === "Squirrel.exe" ||
+ fileName === "LICENSE.electron.txt" ||
+ fileName === "LICENSES.chromium.html" ||
+ fileName === appExe
+ ) {
+ return false
+ }
+ return true
+ })
+
+ return additionalFiles.map(f => {
+ if (f.isDirectory()) {
+ return {
+ src: `${f.name}\\**`,
+ target: `lib\\net45\\${f.name}`,
+ }
+ }
+ return {
+ src: f.name,
+ target: `lib\\net45\\${f.name}`,
+ }
+ })
}
async computeEffectiveDistOptions(appDirectory: string, outputDirectory: string, setupFile: string): Promise {
@@ -189,6 +247,7 @@ export default class SquirrelWindowsTarget extends Target {
}
}
+ const additionalFiles = await this.getAdditionalFiles(appDirectory)
checkConflictingOptions(this.options)
const appInfo = packager.appInfo
const options: SquirrelOptions = {
@@ -200,7 +259,7 @@ export default class SquirrelWindowsTarget extends Target {
description: appInfo.description,
exe: `${appInfo.productFilename || this.options.name || appInfo.productName}.exe`,
authors: appInfo.companyName || "",
- nuspecTemplate: await this.createNuspecTemplateWithProjectUrl(),
+ nuspecTemplate: await this.createNuspecTemplateWithProjectUrl(additionalFiles),
iconUrl,
copyright: appInfo.copyright,
noMsi: !this.options.msi,
diff --git a/packages/electron-builder-squirrel-windows/template.nuspectemplate b/packages/electron-builder-squirrel-windows/template.nuspectemplate
index 688a369d20d..f7442db51a3 100644
--- a/packages/electron-builder-squirrel-windows/template.nuspectemplate
+++ b/packages/electron-builder-squirrel-windows/template.nuspectemplate
@@ -25,8 +25,6 @@
- <% additionalFiles.forEach(function(f) { %>
-
- <% }); %>
+ <% file src="additionalFiles.src" target="additionalFiles.target" / %>
\ No newline at end of file
diff --git a/test/snapshots/windows/squirrelWindowsTest.js.snap b/test/snapshots/windows/squirrelWindowsTest.js.snap
index 523e46827a9..6971ae4dd52 100644
--- a/test/snapshots/windows/squirrelWindowsTest.js.snap
+++ b/test/snapshots/windows/squirrelWindowsTest.js.snap
@@ -272,6 +272,7 @@ exports[`squirrel.windows > squirrel window x64 msi 2`] = `
"lib/net45/d3dcompiler_47.dll",
"lib/net45/ffmpeg.dll",
"lib/net45/icudtl.dat",
+ "lib/net45/index.html",
"lib/net45/libEGL.dll",
"lib/net45/libGLESv2.dll",
"lib/net45/LICENSE.electron.txt",
diff --git a/test/src/windows/squirrelWindowsTest.ts b/test/src/windows/squirrelWindowsTest.ts
index ba7e5b72b36..f5d273c35d4 100644
--- a/test/src/windows/squirrelWindowsTest.ts
+++ b/test/src/windows/squirrelWindowsTest.ts
@@ -77,6 +77,7 @@ describe("squirrel.windows", { sequential: true }, () => {
squirrelWindows: {
msi: true,
},
+ extraFiles: ["index.html"],
},
},
{ signedWin: true }