From df8e269d5ce0a401a975b01fd11044d4f346230b Mon Sep 17 00:00:00 2001 From: softworkz Date: Mon, 15 Dec 2025 09:34:47 +0100 Subject: [PATCH 1/4] 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 2/4] 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 3/4] 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 4/4] 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()