From 882338f9cdab6b6ec76bc9d66478d5bc77f67046 Mon Sep 17 00:00:00 2001
From: DYH1319 <1245687900@qq.com>
Date: Mon, 24 Aug 2026 09:01:05 +0000
Subject: [PATCH] Add DotNet-First packaging layout support and build
extensibility
- Detect and launch the Electron host from an electron/ subdirectory
when using a DotNet-First packaged app layout.
- Make ElectronPackageId and Title overridable from MSBuild properties.
- Allow overriding the intermediate PublishDir via ElectronPublishDir.
- Add ElectronSkipExecCommands to suppress npm/npx build steps.
Co-Authored-By: Mark Deng <1245687900@qq.com>
---
.../Runtime/Helpers/UnpackagedDetector.cs | 11 +++++++++-
.../ElectronProcess/ElectronProcessActive.cs | 22 +++++++++++++++----
src/ElectronNET/build/ElectronNET.Core.props | 4 ++--
.../build/ElectronNET.LateImport.targets | 19 +++++++++++-----
4 files changed, 43 insertions(+), 13 deletions(-)
diff --git a/src/ElectronNET.API/Runtime/Helpers/UnpackagedDetector.cs b/src/ElectronNET.API/Runtime/Helpers/UnpackagedDetector.cs
index f5c5f549..44884962 100644
--- a/src/ElectronNET.API/Runtime/Helpers/UnpackagedDetector.cs
+++ b/src/ElectronNET.API/Runtime/Helpers/UnpackagedDetector.cs
@@ -64,11 +64,20 @@ public static bool CheckIsUnpackaged()
private static bool? CheckUnpackaged2()
{
var dir = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);
+
+ // Electron-First packaging mode: the .NET binary is in resources/bin.
if (dir.Name == "bin" && dir.Parent?.Name == "resources")
{
return false;
}
+ // DotNet-First packaging mode: the Electron host is in the electron subdirectory.
+ if (dir.GetDirectories().Any(e => e.Name == "electron"))
+ {
+ return false;
+ }
+
+ // Development mode: the .electron subdirectory exists.
if (dir.GetDirectories().Any(e => e.Name == ".electron"))
{
return true;
@@ -106,4 +115,4 @@ public static bool CheckIsUnpackaged()
return null;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ElectronNET.API/Runtime/Services/ElectronProcess/ElectronProcessActive.cs b/src/ElectronNET.API/Runtime/Services/ElectronProcess/ElectronProcessActive.cs
index b7c65ed4..dfc0b513 100644
--- a/src/ElectronNET.API/Runtime/Services/ElectronProcess/ElectronProcessActive.cs
+++ b/src/ElectronNET.API/Runtime/Services/ElectronProcess/ElectronProcessActive.cs
@@ -87,10 +87,24 @@ protected override async Task StartCore()
}
else
{
- dir = dir.Parent!.Parent!;
- startCmd = Path.Combine(dir.FullName, this.electronBinaryName);
+ // DotNet-First packaging mode: the Electron host is in the electron subdirectory.
+ var electronDir = Path.Combine(dir.FullName, "electron");
+
+ if (Directory.Exists(electronDir))
+ {
+ // New DotNet-First directory layout.
+ startCmd = Path.Combine(electronDir, this.electronBinaryName);
+ workingDir = electronDir;
+ }
+ else
+ {
+ // Fallback to the legacy Electron-First directory layout.
+ dir = dir.Parent!.Parent!;
+ startCmd = Path.Combine(dir.FullName, this.electronBinaryName);
+ workingDir = dir.FullName;
+ }
+
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"
@@ -241,4 +255,4 @@ private void Process_Exited(object sender, EventArgs e)
this.TransitionState(LifetimeState.Stopped);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ElectronNET/build/ElectronNET.Core.props b/src/ElectronNET/build/ElectronNET.Core.props
index 13578cae..af3bd840 100644
--- a/src/ElectronNET/build/ElectronNET.Core.props
+++ b/src/ElectronNET/build/ElectronNET.Core.props
@@ -14,9 +14,9 @@