From df8e269d5ce0a401a975b01fd11044d4f346230b Mon Sep 17 00:00:00 2001 From: softworkz Date: Mon, 15 Dec 2025 09:34:47 +0100 Subject: [PATCH 01/10] Core: Introduce cross-platform npm restore and check mismatch on publish --- .../build/ElectronNET.LateImport.targets | 80 ++++++++++++++----- 1 file changed, 61 insertions(+), 19 deletions(-) diff --git a/src/ElectronNET/build/ElectronNET.LateImport.targets b/src/ElectronNET/build/ElectronNET.LateImport.targets index d82dcbd8..b906ea3b 100644 --- a/src/ElectronNET/build/ElectronNET.LateImport.targets +++ b/src/ElectronNET/build/ElectronNET.LateImport.targets @@ -297,12 +297,58 @@ + + + + x64 + ia32 + arm64 + x64 + armv7l + arm64 + x64 + arm64 + + win + linux + mac + + + win32 + linux + darwin + + + $(ElectronArch) + arm + + <_CurrentOSPlatform Condition="$([MSBuild]::IsOSPlatform('Windows'))">win + <_CurrentOSPlatform Condition="$([MSBuild]::IsOSPlatform('Linux'))">linux + <_CurrentOSPlatform Condition="$([MSBuild]::IsOSPlatform('OSX'))">mac + + + + + false + true + + <_IsCrossCompileAllowed>false + + <_IsCrossCompileAllowed Condition="'$(_CurrentOSPlatform)' == 'win' AND '$(ElectronPlatform)' == 'linux' AND '$(IsLinuxWsl)' == 'true'">true + + <_IsPlatformMismatch>false + <_IsPlatformMismatch Condition="'$(_CurrentOSPlatform)' != '$(ElectronPlatform)' AND '$(_IsCrossCompileAllowed)' != 'true'">true + + + + + @@ -316,10 +362,9 @@ $([System.IO.Path]::GetFullPath('$(ElectronOutDir)')) - linux - false - true <_NpmCmd>npm install --no-bin-links + + <_NpmCmd Condition="'$(_IsPlatformMismatch)' == 'true'">$(_NpmCmd) --os=$(NpmOs) --cpu=$(NpmCpu) --arch=$(NpmCpu) --platform=$(NpmOs) <_NpmCmd Condition="'$(IsLinuxWsl)' == 'true'">wsl bash -ic '$(_NpmCmd)' @@ -367,7 +412,7 @@ <_ElectronPublishAppAfterTarget Condition="'$(UsingMicrosoftNETSdkWeb)' != 'true'">Publish - + $(_OriginalPublishDir) @@ -376,21 +421,18 @@ - - - x64 - ia32 - arm64 - x64 - armv7l - arm64 - x64 - arm64 + win - linux - mac - +Electron applications must be built on the target operating system: +- Windows targets (win-x64, win-x86, win-arm64) must be built on Windows +- Linux targets (linux-x64, linux-arm, linux-arm64) must be built on Linux (or Windows with WSL) +- macOS targets (osx-x64, osx-arm64) must be built on macOS + +EXCEPTION: Linux targets can be built on Windows using WSL (Windows Subsystem for Linux). + +For more information, see: https://github.com/ElectronNET/Electron.NET/wiki/Migration-Checks#8-cross-platform-build-validation" /> From 2d6d4e23208d3334249dd7d6d88876499417c63e Mon Sep 17 00:00:00 2001 From: softworkz Date: Mon, 15 Dec 2025 11:13:31 +0100 Subject: [PATCH 02/10] Fix up incorrect symlinks created by npm on Windows --- .../build/ElectronNET.LateImport.targets | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/ElectronNET/build/ElectronNET.LateImport.targets b/src/ElectronNET/build/ElectronNET.LateImport.targets index b906ea3b..f5e655fc 100644 --- a/src/ElectronNET/build/ElectronNET.LateImport.targets +++ b/src/ElectronNET/build/ElectronNET.LateImport.targets @@ -380,6 +380,23 @@ + + + <_ElectronFrameworksDir>$(ElectronOutDir)node_modules\electron\dist\Electron.app\Contents\Frameworks + + + + <_ElectronFrameworkDirs Include="$(_ElectronFrameworksDir)\Electron Framework.framework" /> + <_ElectronFrameworkDirs Include="$(_ElectronFrameworksDir)\Mantle.framework" /> + <_ElectronFrameworkDirs Include="$(_ElectronFrameworksDir)\ReactiveObjC.framework" /> + <_ElectronFrameworkDirs Include="$(_ElectronFrameworksDir)\Squirrel.framework" /> + + + + + + + From 1d6ef7a250d2542803a035007dc460ce653e2ef8 Mon Sep 17 00:00:00 2001 From: softworkz Date: Mon, 15 Dec 2025 12:12:05 +0100 Subject: [PATCH 03/10] ElectronProcessActive: Mark binaries as executable when debugging --- .../ElectronProcess/ElectronProcessActive.cs | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/ElectronNET.API/Runtime/Services/ElectronProcess/ElectronProcessActive.cs b/src/ElectronNET.API/Runtime/Services/ElectronProcess/ElectronProcessActive.cs index 61cae062..a7516e68 100644 --- a/src/ElectronNET.API/Runtime/Services/ElectronProcess/ElectronProcessActive.cs +++ b/src/ElectronNET.API/Runtime/Services/ElectronProcess/ElectronProcessActive.cs @@ -5,8 +5,11 @@ using System; using System.ComponentModel; using System.IO; + using System.Linq; using System.Runtime.InteropServices; using System.Threading.Tasks; + using ElectronNET.Common; + using ElectronNET.Runtime.Data; /// /// Launches and manages the Electron app process. @@ -33,7 +36,7 @@ public ElectronProcessActive(bool isUnpackaged, string electronBinaryName, strin this.socketPort = socketPort; } - protected override Task StartCore() + protected override async Task StartCore() { var dir = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory); string startCmd, args, workingDir; @@ -41,6 +44,32 @@ protected override Task StartCore() if (this.isUnpackaged) { var electrondir = Path.Combine(dir.FullName, ".electron"); + + ProcessRunner chmodRunner = null; + + try + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + var distFolder = Path.Combine(electrondir, "node_modules", "electron", "dist"); + + chmodRunner = new ProcessRunner("ElectronRunner-Chmod"); + chmodRunner.Run("chmod", "-R +x " + distFolder, electrondir); + await chmodRunner.WaitForExitAsync().ConfigureAwait(true); + + if (chmodRunner.LastExitCode != 0) + { + throw new Exception("Failed to set executable permissions on Electron dist folder."); + } + } + } + catch (Exception ex) + { + Console.Error.WriteLine("[StartCore]: Exception: " + chmodRunner?.StandardError); + Console.Error.WriteLine("[StartCore]: Exception: " + chmodRunner?.StandardOutput); + Console.Error.WriteLine("[StartCore]: Exception: " + ex); + } + startCmd = Path.Combine(electrondir, "node_modules", "electron", "dist", "electron"); if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) @@ -53,7 +82,7 @@ protected override Task StartCore() } else { - dir = dir.Parent?.Parent; + dir = dir.Parent!.Parent!; startCmd = Path.Combine(dir.FullName, this.electronBinaryName); args = $"-dotnetpacked -electronforcedport={this.socketPort:D} " + this.extraArguments; workingDir = dir.FullName; From 9d0378798b6af1ba9bee9a9bc7c190f072b8c4bf Mon Sep 17 00:00:00 2001 From: softworkz Date: Mon, 15 Dec 2025 12:12:42 +0100 Subject: [PATCH 04/10] ElectronProcessActive: Add check for platform mismatch --- .../ElectronProcess/ElectronProcessActive.cs | 62 +++++++++++++++++-- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/src/ElectronNET.API/Runtime/Services/ElectronProcess/ElectronProcessActive.cs b/src/ElectronNET.API/Runtime/Services/ElectronProcess/ElectronProcessActive.cs index a7516e68..b2d32a9e 100644 --- a/src/ElectronNET.API/Runtime/Services/ElectronProcess/ElectronProcessActive.cs +++ b/src/ElectronNET.API/Runtime/Services/ElectronProcess/ElectronProcessActive.cs @@ -1,7 +1,5 @@ namespace ElectronNET.Runtime.Services.ElectronProcess { - using ElectronNET.Common; - using ElectronNET.Runtime.Data; using System; using System.ComponentModel; using System.IO; @@ -43,6 +41,8 @@ protected override async Task StartCore() if (this.isUnpackaged) { + this.CheckRuntimeIdentifier(); + var electrondir = Path.Combine(dir.FullName, ".electron"); ProcessRunner chmodRunner = null; @@ -88,11 +88,65 @@ protected override async Task StartCore() workingDir = dir.FullName; } - // We don't await this in order to let the state transition to "Starting" Task.Run(async () => await this.StartInternal(startCmd, args, workingDir).ConfigureAwait(false)); + } - return Task.CompletedTask; + private void CheckRuntimeIdentifier() + { + var buildInfoRid = ElectronNetRuntime.BuildInfo.RuntimeIdentifier; + if (string.IsNullOrEmpty(buildInfoRid)) + { + return; + } + + var osPart = buildInfoRid.Split('-').First(); + + var mismatch = false; + + switch (osPart) + { + case "win": + + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + mismatch = true; + } + + break; + + case "linux": + + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + mismatch = true; + } + + break; + + case "osx": + + if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + mismatch = true; + } + + break; + + case "freebsd": + + if (!RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD)) + { + mismatch = true; + } + + break; + } + + if (mismatch) + { + throw new PlatformNotSupportedException($"This Electron.NET application was built for '{buildInfoRid}'. It cannot run on this platform."); + } } protected override Task StopCore() From d9c8e04b5c75890e68848ad3462d77c2b3a34e17 Mon Sep 17 00:00:00 2001 From: Florian Rappl Date: Wed, 17 Dec 2025 16:40:46 +0100 Subject: [PATCH 05/10] Meta for 0.4.0 --- Changelog.md | 6 ++++++ docs/GettingStarted/Console-App.md | 2 +- src/ElectronNET.ConsoleApp/ElectronNET.ConsoleApp.csproj | 2 +- src/ElectronNET.WebApp/ElectronNET.WebApp.csproj | 4 ++-- src/common.props | 2 +- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Changelog.md b/Changelog.md index b9df15c7..716b8346 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,9 @@ +# 0.4.0 + +## ElectronNET.Core + +- Added cross-platform npm restore and check mismatch on publish (#988) @softworkz + # 0.3.1 ## ElectronNET.Core diff --git a/docs/GettingStarted/Console-App.md b/docs/GettingStarted/Console-App.md index bb59d64d..ec8a6043 100644 --- a/docs/GettingStarted/Console-App.md +++ b/docs/GettingStarted/Console-App.md @@ -54,7 +54,7 @@ Add the Electron.NET configuration to your `.csproj` file: - + ``` diff --git a/src/ElectronNET.ConsoleApp/ElectronNET.ConsoleApp.csproj b/src/ElectronNET.ConsoleApp/ElectronNET.ConsoleApp.csproj index 5c48a427..f0cb290c 100644 --- a/src/ElectronNET.ConsoleApp/ElectronNET.ConsoleApp.csproj +++ b/src/ElectronNET.ConsoleApp/ElectronNET.ConsoleApp.csproj @@ -70,7 +70,7 @@ - + diff --git a/src/ElectronNET.WebApp/ElectronNET.WebApp.csproj b/src/ElectronNET.WebApp/ElectronNET.WebApp.csproj index 8a615e57..4d37bd91 100644 --- a/src/ElectronNET.WebApp/ElectronNET.WebApp.csproj +++ b/src/ElectronNET.WebApp/ElectronNET.WebApp.csproj @@ -76,8 +76,8 @@ - - + + diff --git a/src/common.props b/src/common.props index 047dfb8a..aaaae347 100644 --- a/src/common.props +++ b/src/common.props @@ -1,6 +1,6 @@ - 0.3.1 + 0.4.0 ElectronNET.Core Gregor Biswanger, Florian Rappl, softworkz Electron.NET From 69048d5565b978c21ef7198c2556f014156eb7c6 Mon Sep 17 00:00:00 2001 From: softworkz Date: Thu, 18 Dec 2025 15:12:21 +0100 Subject: [PATCH 06/10] Set PackageId from ElectronPackageId --- src/ElectronNET/build/ElectronNET.Core.targets | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ElectronNET/build/ElectronNET.Core.targets b/src/ElectronNET/build/ElectronNET.Core.targets index 9385fa54..59b754d1 100644 --- a/src/ElectronNET/build/ElectronNET.Core.targets +++ b/src/ElectronNET/build/ElectronNET.Core.targets @@ -12,6 +12,10 @@ <_IsMsAspNetProject Condition="'$(UsingMicrosoftNETSdkWeb)' == 'true'">True + + $(ElectronPackageId) + + From 30037fce69e146cf1ccf403297259d17ad837968 Mon Sep 17 00:00:00 2001 From: softworkz Date: Thu, 18 Dec 2025 15:51:45 +0100 Subject: [PATCH 07/10] Fix ElectronSingleInstance handling --- src/ElectronNET.API/Runtime/Data/BuildInfo.cs | 2 +- src/ElectronNET.API/Runtime/StartupManager.cs | 8 ++------ src/ElectronNET.Host/main.js | 2 +- src/ElectronNET/build/ElectronNET.LateImport.targets | 2 +- src/ElectronNET/build/package.template.json | 2 +- 5 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/ElectronNET.API/Runtime/Data/BuildInfo.cs b/src/ElectronNET.API/Runtime/Data/BuildInfo.cs index cb71aa08..75febe06 100644 --- a/src/ElectronNET.API/Runtime/Data/BuildInfo.cs +++ b/src/ElectronNET.API/Runtime/Data/BuildInfo.cs @@ -8,7 +8,7 @@ public class BuildInfo public string RuntimeIdentifier { get; internal set; } - public string ElectronSingleInstance { get; internal set; } + public bool ElectronSingleInstance { get; internal set; } public string Title { get; internal set; } diff --git a/src/ElectronNET.API/Runtime/StartupManager.cs b/src/ElectronNET.API/Runtime/StartupManager.cs index 125b6dee..91fed9a2 100644 --- a/src/ElectronNET.API/Runtime/StartupManager.cs +++ b/src/ElectronNET.API/Runtime/StartupManager.cs @@ -165,13 +165,9 @@ private BuildInfo GatherBuildInfo() ElectronNetRuntime.DotnetAppType = DotnetAppType.AspNetCoreApp; } - if (isSingleInstance?.Length > 0 && bool.TryParse(isSingleInstance, out var isSingleInstanceActive) && isSingleInstanceActive) + if (bool.TryParse(isSingleInstance, out var parsedBool)) { - buildInfo.ElectronSingleInstance = "yes"; - } - else - { - buildInfo.ElectronSingleInstance = "no"; + buildInfo.ElectronSingleInstance = parsedBool; } if (httpPort?.Length > 0 && int.TryParse(httpPort, out var port)) diff --git a/src/ElectronNET.Host/main.js b/src/ElectronNET.Host/main.js index 2562ca7b..9ea21ded 100644 --- a/src/ElectronNET.Host/main.js +++ b/src/ElectronNET.Host/main.js @@ -93,7 +93,7 @@ app.on('will-finish-launching', () => { const manifestJsonFile = require(manifestJsonFilePath); -if (manifestJsonFile.singleInstance === "yes") { +if (manifestJsonFile.singleInstance) { const mainInstance = app.requestSingleInstanceLock(); app.on('second-instance', (events, args = []) => { args.forEach((parameter) => { diff --git a/src/ElectronNET/build/ElectronNET.LateImport.targets b/src/ElectronNET/build/ElectronNET.LateImport.targets index 8144389e..5adc6d64 100644 --- a/src/ElectronNET/build/ElectronNET.LateImport.targets +++ b/src/ElectronNET/build/ElectronNET.LateImport.targets @@ -135,7 +135,7 @@ - + diff --git a/src/ElectronNET/build/package.template.json b/src/ElectronNET/build/package.template.json index 41837302..0f559489 100644 --- a/src/ElectronNET/build/package.template.json +++ b/src/ElectronNET/build/package.template.json @@ -23,7 +23,7 @@ }, "license": "$(License)", "executable": "$(TargetName)", - "singleInstance": "$(ElectronSingleInstance)", + "singleInstance": $(ElectronSingleInstance), "homepage": "$(ProjectUrl)", "splashscreen": { "imageFile": "$(ElectronSplashScreen)" From 73c56e245035a7a2dafd93c475f31f3acfdbd18d Mon Sep 17 00:00:00 2001 From: softworkz Date: Thu, 18 Dec 2025 16:13:04 +0100 Subject: [PATCH 08/10] Try fix retry-test-jobs --- .github/workflows/retry-test-jobs.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/retry-test-jobs.yml b/.github/workflows/retry-test-jobs.yml index 4078b70b..fc7600b8 100644 --- a/.github/workflows/retry-test-jobs.yml +++ b/.github/workflows/retry-test-jobs.yml @@ -32,19 +32,18 @@ jobs: echo "Jobs and conclusions:" echo "$jobs_json" | jq '.jobs[] | {name: .name, conclusion: .conclusion}' - failed_matrix_jobs=$(echo "$jobs_json" | jq ' + failed_matrix_jobs=$(echo "$jobs_json" | jq -r ' [ .jobs[] | select(.conclusion == "failure" and (.name | contains(" API-"))) ] - | length + | length // 0 ') + failed_matrix_jobs=${failed_matrix_jobs:-0} - echo "Failed Integration Tests matrix jobs: $failed_matrix_jobs" - - if [ "$failed_matrix_jobs" -gt 0 ]; then + if [ "${failed_matrix_jobs}" -gt 0 ]; then echo "Detected failing Integration Tests jobs – re-running failed jobs for this run." - gh run rerun -R $REPO "$RUN_ID" --failed + gh run rerun -R "$REPO" "$RUN_ID" --failed else echo "Only non-matrix jobs (like Test Results) failed – not auto-rerunning." fi From 25770db138b84939cb0ce97d74a8e7d751a9cdec Mon Sep 17 00:00:00 2001 From: softworkz <4985349+softworkz@users.noreply.github.com> Date: Thu, 18 Dec 2025 17:25:52 +0100 Subject: [PATCH 09/10] Update src/ElectronNET/build/ElectronNET.Core.targets Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/ElectronNET/build/ElectronNET.Core.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ElectronNET/build/ElectronNET.Core.targets b/src/ElectronNET/build/ElectronNET.Core.targets index 59b754d1..962ed6fa 100644 --- a/src/ElectronNET/build/ElectronNET.Core.targets +++ b/src/ElectronNET/build/ElectronNET.Core.targets @@ -13,7 +13,7 @@ - $(ElectronPackageId) + $(ElectronPackageId) From 29fdbb5315a2211c98d5510f82694ab55015fd83 Mon Sep 17 00:00:00 2001 From: Florian Rappl Date: Thu, 18 Dec 2025 23:58:04 +0100 Subject: [PATCH 10/10] Updated changelog --- Changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changelog.md b/Changelog.md index 716b8346..18871751 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,6 +2,8 @@ ## ElectronNET.Core +- Fixed ElectronSingleInstance handling (#996) @softworkz +- Fixed `PackageId` handling (#993) @softworkz - Added cross-platform npm restore and check mismatch on publish (#988) @softworkz # 0.3.1