From 248c64d6dd7c26ec8ef28e8b5dcc008dd252e97f Mon Sep 17 00:00:00 2001 From: Florian Rappl Date: Mon, 2 Mar 2026 21:21:19 +0100 Subject: [PATCH] Auto-determine used port --- src/ElectronNET.API/Common/ProcessRunner.cs | 3 +++ .../RuntimeControllerDotNetFirst.cs | 14 ++++--------- .../ElectronProcess/ElectronProcessActive.cs | 21 +++++++++++++++++++ .../RuntimeControllerAspNetDotnetFirst.cs | 16 +++++--------- src/ElectronNET.Host/main.js | 19 ++++------------- 5 files changed, 37 insertions(+), 36 deletions(-) diff --git a/src/ElectronNET.API/Common/ProcessRunner.cs b/src/ElectronNET.API/Common/ProcessRunner.cs index 5ac7612..d561020 100644 --- a/src/ElectronNET.API/Common/ProcessRunner.cs +++ b/src/ElectronNET.API/Common/ProcessRunner.cs @@ -26,6 +26,8 @@ private readonly StringBuilder stdOut = new StringBuilder(4 * 1024); private readonly StringBuilder stdErr = new StringBuilder(4 * 1024); + public event EventHandler LineReceived; + private volatile ManualResetEvent stdOutEvent; private volatile ManualResetEvent stdErrEvent; private volatile Stopwatch stopwatch; @@ -571,6 +573,7 @@ if (e.Data != null) { Console.WriteLine("|| " + e.Data); + LineReceived?.Invoke(this, e.Data); } else { diff --git a/src/ElectronNET.API/Runtime/Controllers/RuntimeControllerDotNetFirst.cs b/src/ElectronNET.API/Runtime/Controllers/RuntimeControllerDotNetFirst.cs index 221fffc..6483bf9 100644 --- a/src/ElectronNET.API/Runtime/Controllers/RuntimeControllerDotNetFirst.cs +++ b/src/ElectronNET.API/Runtime/Controllers/RuntimeControllerDotNetFirst.cs @@ -14,7 +14,6 @@ { private ElectronProcessBase electronProcess; private SocketBridgeService socketBridge; - private int? port; public RuntimeControllerDotNetFirst() { @@ -42,19 +41,13 @@ var isUnPacked = ElectronNetRuntime.StartupMethod.IsUnpackaged(); var electronBinaryName = ElectronNetRuntime.ElectronExecutable; var args = string.Format("{0} {1}", ElectronNetRuntime.ElectronExtraArguments, Environment.CommandLine).Trim(); - this.port = ElectronNetRuntime.ElectronSocketPort; - - if (!this.port.HasValue) - { - this.port = PortHelper.GetFreePort(ElectronNetRuntime.DefaultSocketPort); - ElectronNetRuntime.ElectronSocketPort = this.port; - } + var port = ElectronNetRuntime.ElectronSocketPort ?? 0; Console.Error.WriteLine("[StartCore]: isUnPacked: {0}", isUnPacked); Console.Error.WriteLine("[StartCore]: electronBinaryName: {0}", electronBinaryName); Console.Error.WriteLine("[StartCore]: args: {0}", args); - this.electronProcess = new ElectronProcessActive(isUnPacked, electronBinaryName, args, this.port.Value); + this.electronProcess = new ElectronProcessActive(isUnPacked, electronBinaryName, args, port); this.electronProcess.Ready += this.ElectronProcess_Ready; this.electronProcess.Stopped += this.ElectronProcess_Stopped; @@ -64,8 +57,9 @@ private void ElectronProcess_Ready(object sender, EventArgs e) { + var port = ElectronNetRuntime.ElectronSocketPort.Value; this.TransitionState(LifetimeState.Started); - this.socketBridge = new SocketBridgeService(this.port!.Value, ""); + this.socketBridge = new SocketBridgeService(port, ""); this.socketBridge.Ready += this.SocketBridge_Ready; this.socketBridge.Stopped += this.SocketBridge_Stopped; this.socketBridge.Start(); diff --git a/src/ElectronNET.API/Runtime/Services/ElectronProcess/ElectronProcessActive.cs b/src/ElectronNET.API/Runtime/Services/ElectronProcess/ElectronProcessActive.cs index b2d32a9..8fc81c0 100644 --- a/src/ElectronNET.API/Runtime/Services/ElectronProcess/ElectronProcessActive.cs +++ b/src/ElectronNET.API/Runtime/Services/ElectronProcess/ElectronProcessActive.cs @@ -155,6 +155,26 @@ return Task.CompletedTask; } + private void Read_SocketIO_Port(object sender, string line) + { + // Look for "Electron Socket: listening on port %s at" + var prefix = "Electron Socket: listening on port "; + + if (line.StartsWith(prefix)) + { + var start = prefix.Length; + var end = line.IndexOf(' ', start + 1); + var port = line[start..end]; + + if (int.TryParse(port, out var p)) + { + // We got the port, so no more need for reading this + this.process.LineReceived -= this.Read_SocketIO_Port; + ElectronNetRuntime.ElectronSocketPort = p; + } + } + } + private async Task StartInternal(string startCmd, string args, string directoriy) { try @@ -166,6 +186,7 @@ this.process = new ProcessRunner("ElectronRunner"); this.process.ProcessExited += this.Process_Exited; + this.process.LineReceived += this.Read_SocketIO_Port; this.process.Run(startCmd, args, directoriy); await Task.Delay(500.ms()).ConfigureAwait(false); diff --git a/src/ElectronNET.AspNet/Runtime/Controllers/RuntimeControllerAspNetDotnetFirst.cs b/src/ElectronNET.AspNet/Runtime/Controllers/RuntimeControllerAspNetDotnetFirst.cs index 03b26fd..5a73ee0 100644 --- a/src/ElectronNET.AspNet/Runtime/Controllers/RuntimeControllerAspNetDotnetFirst.cs +++ b/src/ElectronNET.AspNet/Runtime/Controllers/RuntimeControllerAspNetDotnetFirst.cs @@ -11,7 +11,6 @@ internal class RuntimeControllerAspNetDotnetFirst : RuntimeControllerAspNetBase { private ElectronProcessBase electronProcess; - private int? port; private readonly string authorization; public RuntimeControllerAspNetDotnetFirst(AspNetLifetimeAdapter aspNetLifetimeAdapter, IElectronAuthenticationService authenticationService = null) : base(aspNetLifetimeAdapter) @@ -29,16 +28,10 @@ var isUnPacked = ElectronNetRuntime.StartupMethod.IsUnpackaged(); var electronBinaryName = ElectronNetRuntime.ElectronExecutable; var authToken = this.authorization; - this.port = ElectronNetRuntime.ElectronSocketPort; - - if (!this.port.HasValue) - { - this.port = PortHelper.GetFreePort(ElectronNetRuntime.DefaultSocketPort); - ElectronNetRuntime.ElectronSocketPort = this.port; - } - + var port = ElectronNetRuntime.ElectronSocketPort ?? 0; var args = $"{Environment.CommandLine} --authtoken={authToken}"; - this.electronProcess = new ElectronProcessActive(isUnPacked, electronBinaryName, args, this.port.Value); + + this.electronProcess = new ElectronProcessActive(isUnPacked, electronBinaryName, args, port); this.electronProcess.Ready += this.ElectronProcess_Ready; this.electronProcess.Stopped += this.ElectronProcess_Stopped; @@ -53,8 +46,9 @@ private void ElectronProcess_Ready(object sender, EventArgs e) { + var port = ElectronNetRuntime.ElectronSocketPort.Value; this.TransitionState(LifetimeState.Started); - this.CreateSocketBridge(this.port!.Value, this.authorization); + this.CreateSocketBridge(port, this.authorization); } private void ElectronProcess_Stopped(object sender, EventArgs e) diff --git a/src/ElectronNET.Host/main.js b/src/ElectronNET.Host/main.js index e8dd31f..6f22906 100644 --- a/src/ElectronNET.Host/main.js +++ b/src/ElectronNET.Host/main.js @@ -16,12 +16,8 @@ let processInfo; let splashScreen; let nativeTheme; let dock; -let desktopCapturer; -let electronHostHook; -let touchBar; let launchFile; let launchUrl; -let processApi; let manifestJsonFileName = 'package.json'; let unpackedelectron = false; @@ -45,7 +41,7 @@ else if (app.commandLine.hasSwitch('dotnetpacked')) { } if (app.commandLine.hasSwitch('electronforcedport')) { - electronforcedport = app.commandLine.getSwitchValue('electronforcedport'); + electronforcedport = +app.commandLine.getSwitchValue('electronforcedport'); } let authToken; @@ -172,17 +168,10 @@ app.on('ready', async () => { if (electronforcedport) { console.info('Electron Socket IO (forced) Port: ' + electronforcedport); startSocketApiBridge(electronforcedport); - return; + } else { + console.info('Electron Socket dynamic IO Port'); + startSocketApiBridge(0); } - - // Added default port as configurable for port restricted environments. - let defaultElectronPort = 8000; - if (manifestJsonFile.electronPort) { - defaultElectronPort = manifestJsonFile.electronPort; - } - - console.info('Electron Socket dynamic IO Port'); - startSocketApiBridge(0); }); app.on('quit', async (event, exitCode) => {