diff --git a/src/ElectronNET.API/Runtime/Services/ElectronProcess/ElectronProcessActive.cs b/src/ElectronNET.API/Runtime/Services/ElectronProcess/ElectronProcessActive.cs index 61cae062..b2d32a9e 100644 --- a/src/ElectronNET.API/Runtime/Services/ElectronProcess/ElectronProcessActive.cs +++ b/src/ElectronNET.API/Runtime/Services/ElectronProcess/ElectronProcessActive.cs @@ -1,12 +1,13 @@ namespace ElectronNET.Runtime.Services.ElectronProcess { - using ElectronNET.Common; - using ElectronNET.Runtime.Data; 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,14 +34,42 @@ 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; if (this.isUnpackaged) { + this.CheckRuntimeIdentifier(); + 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,17 +82,71 @@ 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; } - // 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() diff --git a/src/ElectronNET/build/ElectronNET.LateImport.targets b/src/ElectronNET/build/ElectronNET.LateImport.targets index d82dcbd8..f5e655fc 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)' @@ -335,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" /> + + + + + + + @@ -367,7 +429,7 @@ <_ElectronPublishAppAfterTarget Condition="'$(UsingMicrosoftNETSdkWeb)' != 'true'">Publish - + $(_OriginalPublishDir) @@ -376,21 +438,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" />