Skip to content
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
15ee162
generate stubExecutableExe and sign it
beyondkmp Mar 14, 2025
3e7b26b
generate _ExecutionStub.exe after prepared vendor
beyondkmp Mar 15, 2025
1134394
add vendor files from winows-installer
beyondkmp Mar 15, 2025
c5c41f5
update squirrel window from https://github.com/beyondkmp/Squirrel.Win…
beyondkmp Mar 15, 2025
bcabba8
change default vendor
beyondkmp Mar 15, 2025
faa8df7
update vendor from https://github.com/beyondkmp/Squirrel.Windows/acti…
beyondkmp Mar 15, 2025
d5bdf42
fix ut
beyondkmp Mar 15, 2025
aea79ff
update ut
beyondkmp Mar 15, 2025
03e9201
update ut
beyondkmp Mar 15, 2025
f3f25c1
change to default vendor when custom vendor is empty
beyondkmp Mar 15, 2025
5d29591
Merge branch 'master' into StubExecutable
mmaietta Mar 15, 2025
49a88b7
fix comments
beyondkmp Mar 17, 2025
dc6c1fb
Merge branch 'master' into StubExecutable
beyondkmp Mar 17, 2025
ecfa950
add vendor to package.json
beyondkmp Mar 18, 2025
b954be0
fix comments
beyondkmp Mar 18, 2025
9800401
fix fileNameWithoutExt with basename .exe
beyondkmp Mar 18, 2025
4c7599d
Merge branch 'master' into StubExecutable
beyondkmp Apr 3, 2025
a5733ba
Merge branch 'master' into StubExecutable
beyondkmp May 21, 2025
713d4f3
refactor: update Squirrel.Windows vendor handling and remove obsolete…
beyondkmp May 29, 2025
1825476
Merge branch 'master' into StubExecutable
beyondkmp May 29, 2025
73db025
chore: remove vendor directory from package.json files list to stream…
beyondkmp May 29, 2025
b7b1b58
chore: update Squirrel.Windows binary version to 2.0.1-patched for im…
beyondkmp May 29, 2025
0e5b61c
chore: update Squirrel.Windows binary download method to use new URL …
beyondkmp May 29, 2025
3b9ba8e
fix: update vendor directory resolution for Squirrel.Windows to ensur…
beyondkmp May 29, 2025
4d18d74
fix: correct path for copying custom Squirrel.Windows binaries to ens…
beyondkmp May 29, 2025
634c84c
Merge branch 'master' into StubExecutable
beyondkmp Jun 5, 2025
3dd31a0
Merge branch 'master' into StubExecutable
mmaietta Jun 5, 2025
439c4ce
Merge branch 'master' into StubExecutable
mmaietta Jun 8, 2025
1cd2bc9
fix comments
beyondkmp Jun 16, 2025
e78f7dd
refactor: improve error handling for missing app executable in Squirr…
beyondkmp Jun 18, 2025
69feef9
Merge branch 'master' into StubExecutable
mmaietta Jun 18, 2025
71ee208
Create lovely-brooms-move.md
mmaietta Jun 18, 2025
a08d1db
Merge branch 'master' into StubExecutable
beyondkmp Jun 22, 2025
390f631
refactor(SquirrelWindowsTarget): replace getBin with getBinFromUrl fo…
beyondkmp Jun 22, 2025
eb5d7b3
use getbin
beyondkmp Jun 22, 2025
f92b073
Merge branch 'master' into StubExecutable
mmaietta Jul 12, 2025
3ad8b8a
fix ut
beyondkmp Jul 17, 2025
2b86c16
Merge branch 'master' into StubExecutable
beyondkmp Jul 17, 2025
07badb5
delete log
beyondkmp Jul 31, 2025
afa0513
Merge branch 'master' into StubExecutable
beyondkmp Jul 31, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/lovely-brooms-move.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"electron-builder-squirrel-windows": patch
---

fix: generate stubExecutableExe and sign it for squirrel.windows using new electron-builder-binaries asset
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { InvalidConfigurationError, log, isEmptyOrSpaces } from "builder-util"
import { execWine } from "app-builder-lib/out/wine"
import { getBinFromUrl } from "app-builder-lib/out/binDownload"
import { sanitizeFileName } from "builder-util/out/filename"
import { Arch, getArchSuffix, SquirrelWindowsOptions, Target, WinPackager } from "app-builder-lib"
import * as path from "path"
Expand All @@ -20,31 +22,57 @@ export default class SquirrelWindowsTarget extends Target {
}

private async prepareSignedVendorDirectory(): Promise<string> {
// If not specified will use the Squirrel.Windows that is shipped with electron-installer(https://github.com/electron/windows-installer/tree/main/vendor)
// After https://github.com/electron-userland/electron-builder-binaries/pull/56 merged, will add `electron-builder-binaries` to get the latest version of squirrel.
let vendorDirectory = this.options.customSquirrelVendorDir || path.join(require.resolve("electron-winstaller/package.json"), "..", "vendor")
if (isEmptyOrSpaces(vendorDirectory) || !fs.existsSync(vendorDirectory)) {
log.warn({ vendorDirectory }, "unable to access Squirrel.Windows vendor directory, falling back to default electron-winstaller")
vendorDirectory = path.join(require.resolve("electron-winstaller/package.json"), "..", "vendor")
}

const customSquirrelVendorDirectory = this.options.customSquirrelVendorDir
const tmpVendorDirectory = await this.packager.info.tempDirManager.createTempDir({ prefix: "squirrel-windows-vendor" })
// Copy entire vendor directory to temp directory
await fs.promises.cp(vendorDirectory, tmpVendorDirectory, { recursive: true })
log.debug({ from: vendorDirectory, to: tmpVendorDirectory }, "copied vendor directory")

const files = await fs.promises.readdir(tmpVendorDirectory)
for (const file of files) {
if (["Squirrel.exe", "StubExecutable.exe"].includes(file)) {
const filePath = path.join(tmpVendorDirectory, file)
log.debug({ file: filePath }, "signing vendor executable")
await this.packager.sign(filePath)
}
if (isEmptyOrSpaces(customSquirrelVendorDirectory) || !fs.existsSync(customSquirrelVendorDirectory)) {
log.warn({ customSquirrelVendorDirectory: customSquirrelVendorDirectory }, "unable to access custom Squirrel.Windows vendor directory, falling back to default vendor ")
const windowInstallerPackage = require.resolve("electron-winstaller/package.json")
const vendorDirectory = path.join(path.dirname(windowInstallerPackage), "vendor")

const squirrelBin = await getBinFromUrl(
"[email protected]",
"squirrel.windows-2.0.1-patched.7z",
"DWijIRRElidu/Rq0yegAKqo2g6aVJUPvcRyvkzUoBPbRasIk61P6xY2fBMdXw6wT17md7NzrTI9/zA1wT9vEqg=="
)

await fs.promises.cp(vendorDirectory, tmpVendorDirectory, { recursive: true })
// copy the patched squirrel to tmp vendor directory
await fs.promises.cp(path.join(squirrelBin, "electron-winstaller", "vendor"), tmpVendorDirectory, { recursive: true })
} else {
// copy the custom squirrel vendor directory to tmp vendor directory
await fs.promises.cp(customSquirrelVendorDirectory, tmpVendorDirectory, { recursive: true })
}

const files = await fs.promises.readdir(tmpVendorDirectory)
const squirrelExe = files.find(f => f === "Squirrel.exe")
if (squirrelExe) {
const filePath = path.join(tmpVendorDirectory, squirrelExe)
log.debug({ file: filePath }, "signing vendor executable")
await this.packager.sign(filePath)
} else {
log.warn("Squirrel.exe not found in vendor directory, skipping signing")
}
return tmpVendorDirectory
}

private async generateStubExecutableExe(appOutDir: string, vendorDir: string) {
const files = await fs.promises.readdir(appOutDir, { withFileTypes: true })
const appExe = files.find(f => f.name === `${this.appName}.exe`)
if (!appExe) {
throw new Error(`App executable not found in app directory: ${appOutDir}`)
}

const filePath = path.join(appOutDir, appExe.name)
log.filePath(filePath)
const stubExePath = path.join(appOutDir, `${this.appName}_ExecutionStub.exe`)
await fs.promises.copyFile(path.join(vendorDir, "StubExecutable.exe"), stubExePath)
await execWine(path.join(vendorDir, "WriteZipToSetup.exe"), null, ["--copy-stub-resources", filePath, stubExePath])
await this.packager.sign(stubExePath)
log.debug({ file: filePath }, "signing app executable")
await this.packager.sign(filePath)
}

async build(appOutDir: string, arch: Arch) {
const packager = this.packager
const version = packager.appInfo.version
Expand All @@ -62,6 +90,7 @@ export default class SquirrelWindowsTarget extends Target {
arch,
})
const distOptions = await this.computeEffectiveDistOptions(appOutDir, installerOutDir, setupFile)
await this.generateStubExecutableExe(appOutDir, distOptions.vendorDirectory!)
await createWindowsInstaller(distOptions)

await packager.signAndEditResources(artifactPath, arch, installerOutDir)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<file src="*.pak" target="lib\net45" />
<file src="*.exe.config" target="lib\net45" />
<file src="*.exe.sig" target="lib\net45" />
<file src="*_ExecutionStub.exe" target="lib\net45" />
<file src="icudtl.dat" target="lib\net45\icudtl.dat" />
<file src="Squirrel.exe" target="lib\net45\squirrel.exe" />
<file src="LICENSE.electron.txt" target="lib\net45\LICENSE.electron.txt" />
Expand Down
Loading