Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/GettingStarted/ASP.Net.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,11 @@ public class Program

#### ASP.NET Port

If you want to launch a specific URL, you can retrieve the actual ASP.NET port from the new `ElectronNetRuntime` static class, for example:
If you want to launch a specific URL, you can retrieve the actual ASP.NET port from `ElectronHostEnvironment.Current`, for example:

```csharp
await browserWindow.WebContents
.LoadURLAsync($"http://localhost:{ElectronNetRuntime.AspNetWebPort}/mypage.html");
.LoadURLAsync($"http://localhost:{ElectronNET.Runtime.ElectronHostEnvironment.Current.AspNetWebPort}/mypage.html");
```

### 4. Alternative: IWebHostBuilder Setup
Expand Down
3 changes: 2 additions & 1 deletion docs/GettingStarted/Console-App.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,15 @@ Here's a complete console application example:
using System;
using System.Threading.Tasks;
using ElectronNET.API.Entities;
using ElectronNET.Runtime;

namespace MyElectronApp

public class Program
{
public static async Task Main(string[] args)
{
var runtimeController = ElectronNetRuntime.RuntimeController;
var runtimeController = ElectronHostEnvironment.Current.RuntimeController;

try
{
Expand Down
4 changes: 2 additions & 2 deletions docs/Using/Startup-Methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ app.Run();
// Program.cs
public static async Task Main(string[] args)
{
var runtimeController = ElectronNetRuntime.RuntimeController;
var runtimeController = ElectronNET.Runtime.ElectronHostEnvironment.Current.RuntimeController;

await runtimeController.Start();
await runtimeController.WaitReadyTask;
Expand Down Expand Up @@ -189,7 +189,7 @@ ElectronNET.Core automatically manages process lifecycle:
Access runtime controller for advanced scenarios:

```csharp
var runtime = ElectronNetRuntime.RuntimeController;
var runtime = ElectronNET.Runtime.ElectronHostEnvironment.Current.RuntimeController;

// Wait for Electron to be ready
await runtime.WaitReadyTask;
Expand Down
10 changes: 6 additions & 4 deletions src/ElectronNET.API/API/HybridSupport.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
namespace ElectronNET.API
namespace ElectronNET.API
{
using ElectronNET.Runtime;

/// <summary>
///
///
/// </summary>
public static class HybridSupport
{
Expand All @@ -15,8 +17,8 @@ public static bool IsElectronActive
{
get
{
return ElectronNetRuntime.RuntimeController != null;
return ElectronHostEnvironment.Current.RuntimeController != null;
}
}
}
}
}
6 changes: 4 additions & 2 deletions src/ElectronNET.API/API/WindowManager.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using ElectronNET.API.Entities;
using ElectronNET.API.Serialization;
using ElectronNET.Runtime;
using System;
using System.Collections.Generic;
using System.Linq;
Expand Down Expand Up @@ -117,9 +118,10 @@ public async Task<BrowserWindow> CreateWindowAsync(BrowserWindowOptions options,
}
});

if (loadUrl.Equals("http://localhost", StringComparison.OrdinalIgnoreCase) && ElectronNetRuntime.AspNetWebPort.HasValue)
var host = ElectronHostEnvironment.Current;
if (loadUrl.Equals("http://localhost", StringComparison.OrdinalIgnoreCase) && host.AspNetWebPort.HasValue)
{
loadUrl = $"{loadUrl}:{ElectronNetRuntime.AspNetWebPort}";
loadUrl = $"{loadUrl}:{host.AspNetWebPort}";
}

// Workaround Windows 10 / Electron Bug
Expand Down
4 changes: 3 additions & 1 deletion src/ElectronNET.API/Bridge/BridgeConnector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
// ReSharper disable once CheckNamespace
namespace ElectronNET.API
{
using ElectronNET.Runtime;

internal static class BridgeConnector
{
public static SocketIoFacade Socket
{
get
{
return ElectronNetRuntime.GetSocket();
return ElectronHostEnvironment.Current.GetSocket();
}
}
}
Expand Down
43 changes: 43 additions & 0 deletions src/ElectronNET.API/ElectronAppLifetimeEvents.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
namespace ElectronNET
{
using System;
using System.Threading.Tasks;

/// <summary>
/// Represents callbacks that are invoked during different phases of the Electron application
/// lifetime. These callbacks allow consumers to hook into the startup sequence more
/// granularly than the existing single callback. Callbacks return <see cref="Task"/>
/// enabling asynchronous work to be awaited before the next phase of the Electron runtime
/// commences.
/// </summary>
public class ElectronAppLifetimeEvents
{
/// <summary>
/// Gets or sets the callback that is invoked once the Electron process and socket bridge
/// have been established but before the Electron <c>ready</c> event has been
/// acknowledged. Use this hook to register custom protocols or perform other
/// initialization that must occur prior to the <c>ready</c> event.
/// </summary>
public Func<Task> OnBeforeReady { get; set; } = () => Task.CompletedTask;

/// <summary>
/// Gets or sets the callback that is invoked when the Electron <c>ready</c> event is
/// fired. Use this hook to create browser windows or perform post-ready initialization.
/// </summary>
public Func<Task> OnReady { get; set; } = () => Task.CompletedTask;

/// <summary>
/// Gets or sets the callback that is invoked when the Electron process is about to quit.
/// This maps to the <c>will-quit</c> event in Electron and can be used to perform
/// graceful shutdown logic. The default implementation does nothing.
/// </summary>
public Func<Task> OnWillQuit { get; set; } = () => Task.CompletedTask;

/// <summary>
/// Gets or sets the callback that is invoked when the Electron process has fully
/// terminated. This can be used for cleanup tasks. The default implementation does
/// nothing.
/// </summary>
public Func<Task> OnQuit { get; set; } = () => Task.CompletedTask;
}
}
20 changes: 20 additions & 0 deletions src/ElectronNET.API/ElectronNetOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace ElectronNET
{
/// <summary>
/// Provides configuration options for Electron.NET. Consumers can assign
/// an instance of <see cref="ElectronAppLifetimeEvents"/> to the <see cref="Events"/>
/// property to hook into the Electron application lifecycle. Additional
/// configuration properties can be added to this class in future versions without
/// breaking existing consumers.
/// </summary>
public class ElectronNetOptions
{
/// <summary>
/// Gets or sets the collection of lifecycle callbacks. The default value is
/// an instance of <see cref="ElectronAppLifetimeEvents"/> with no-op
/// implementations. Assigning a new instance or modifying individual
/// callbacks allows consumers to customize the startup sequence.
/// </summary>
public ElectronAppLifetimeEvents Events { get; set; } = new ElectronAppLifetimeEvents();
}
}
57 changes: 0 additions & 57 deletions src/ElectronNET.API/ElectronNetRuntime.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,16 @@ internal override SocketIoFacade Socket

protected override Task StartCore()
{
var isUnPacked = ElectronNetRuntime.StartupMethod.IsUnpackaged();
var electronBinaryName = ElectronNetRuntime.ElectronExecutable;
var args = string.Format("{0} {1}", ElectronNetRuntime.ElectronExtraArguments, Environment.CommandLine).Trim();
this.port = ElectronNetRuntime.ElectronSocketPort;
var host = ElectronHostEnvironment.InternalHost;
var isUnPacked = host.StartupMethod.IsUnpackaged();
var electronBinaryName = host.ElectronExecutable;
var args = string.Format("{0} {1}", host.ElectronExtraArguments, Environment.CommandLine).Trim();
this.port = host.ElectronSocketPort;

if (!this.port.HasValue)
{
this.port = PortHelper.GetFreePort(ElectronNetRuntime.DefaultSocketPort);
ElectronNetRuntime.ElectronSocketPort = this.port;
this.port = PortHelper.GetFreePort(ElectronHostDefaults.DefaultSocketPort);
host.ElectronSocketPort = this.port;
}

Console.Error.WriteLine("[StartCore]: isUnPacked: {0}", isUnPacked);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,15 @@ internal override SocketIoFacade Socket

protected override Task StartCore()
{
this.port = ElectronNetRuntime.ElectronSocketPort;
var host = ElectronHostEnvironment.InternalHost;
this.port = host.ElectronSocketPort;

if (!this.port.HasValue)
{
throw new Exception("No port has been specified by Electron!");
}

if (!ElectronNetRuntime.ElectronProcessId.HasValue)
if (!host.ElectronProcessId.HasValue)
{
throw new Exception("No electronPID has been specified by Electron!");
}
Expand All @@ -54,7 +55,7 @@ protected override Task StartCore()
this.socketBridge.Stopped += this.SocketBridge_Stopped;
this.socketBridge.Start();

this.electronProcess = new ElectronProcessPassive(ElectronNetRuntime.ElectronProcessId.Value);
this.electronProcess = new ElectronProcessPassive(host.ElectronProcessId.Value);
this.electronProcess.Ready += this.ElectronProcess_Ready;
this.electronProcess.Stopped += this.ElectronProcess_Stopped;

Expand Down
57 changes: 57 additions & 0 deletions src/ElectronNET.API/Runtime/ElectronHost.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
namespace ElectronNET.Runtime
{
using System.Collections.Immutable;
using ElectronNET.Runtime.Controllers;
using ElectronNET.Runtime.Data;

/// <summary>
/// Default implementation of <see cref="IElectronHost"/> that keeps track of the
/// runtime state shared between the Electron.NET CLI bootstrapper and ASP.NET
/// applications.
/// </summary>
public sealed class ElectronHost : IElectronHost
{
private readonly StartupManager startupManager;

public ElectronHost()
{
this.Options = new ElectronNetOptions();
this.startupManager = new StartupManager(this);
this.startupManager.Initialize();
}

public string ElectronExtraArguments { get; set; }

public int? ElectronSocketPort { get; set; }

public int? AspNetWebPort { get; set; }

public StartupMethod StartupMethod { get; set; }

public DotnetAppType DotnetAppType { get; set; }

public string ElectronExecutable { get; set; }

public ImmutableList<string> ProcessArguments { get; set; }

public BuildInfo BuildInfo { get; set; }

public IElectronNetRuntimeController RuntimeController => this.RuntimeControllerCore;

public int? ElectronProcessId { get; set; }

public ElectronNetOptions Options { get; private set; }

internal RuntimeControllerBase RuntimeControllerCore { get; set; }

public SocketIoFacade GetSocket()

Check failure on line 47 in src/ElectronNET.API/Runtime/ElectronHost.cs

View workflow job for this annotation

GitHub Actions / Integration Tests (ubuntu-24.04)

The type or namespace name 'SocketIoFacade' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 47 in src/ElectronNET.API/Runtime/ElectronHost.cs

View workflow job for this annotation

GitHub Actions / Integration Tests (ubuntu-24.04)

The type or namespace name 'SocketIoFacade' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 47 in src/ElectronNET.API/Runtime/ElectronHost.cs

View workflow job for this annotation

GitHub Actions / Integration Tests (macos-14)

The type or namespace name 'SocketIoFacade' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 47 in src/ElectronNET.API/Runtime/ElectronHost.cs

View workflow job for this annotation

GitHub Actions / Integration Tests (macos-14)

The type or namespace name 'SocketIoFacade' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 47 in src/ElectronNET.API/Runtime/ElectronHost.cs

View workflow job for this annotation

GitHub Actions / Integration Tests (windows-2022)

The type or namespace name 'SocketIoFacade' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 47 in src/ElectronNET.API/Runtime/ElectronHost.cs

View workflow job for this annotation

GitHub Actions / Integration Tests (windows-2022)

The type or namespace name 'SocketIoFacade' could not be found (are you missing a using directive or an assembly reference?)
{
return this.RuntimeControllerCore?.Socket;
}

public void ApplyOptions(ElectronNetOptions options)
{
this.Options = options ?? new ElectronNetOptions();
}
}
}
13 changes: 13 additions & 0 deletions src/ElectronNET.API/Runtime/ElectronHostDefaults.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace ElectronNET.Runtime
{
/// <summary>
/// Provides shared default values for the Electron.NET runtime host.
/// </summary>
public static class ElectronHostDefaults
{
public const int DefaultSocketPort = 8000;
public const int DefaultWebPort = 8001;
public const string ElectronPortArgumentName = "electronPort";
public const string ElectronPidArgumentName = "electronPID";
}
}
18 changes: 18 additions & 0 deletions src/ElectronNET.API/Runtime/ElectronHostEnvironment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace ElectronNET.Runtime
{
using System;

/// <summary>
/// Provides access to the singleton <see cref="IElectronHost"/> instance that is
/// used across the application. Consumers can resolve the same instance from
/// dependency injection via <c>services.AddSingleton(ElectronHostEnvironment.Current)</c>.
/// </summary>
public static class ElectronHostEnvironment
{
private static readonly Lazy<ElectronHost> LazyHost = new(() => new ElectronHost());

public static IElectronHost Current => LazyHost.Value;

internal static ElectronHost InternalHost => LazyHost.Value;
}
}
6 changes: 4 additions & 2 deletions src/ElectronNET.API/Runtime/Helpers/LaunchOrderDetector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ public static bool CheckIsLaunchedByDotNet()

private static bool? CheckIsDotNetStartup1()
{
var hasPortArg = ElectronNetRuntime.ProcessArguments.Any(e => e.Contains(ElectronNetRuntime.ElectronPortArgumentName, StringComparison.OrdinalIgnoreCase));
var host = ElectronHostEnvironment.InternalHost;
var hasPortArg = host.ProcessArguments.Any(e => e.Contains(ElectronHostDefaults.ElectronPortArgumentName, StringComparison.OrdinalIgnoreCase));
if (hasPortArg)
{
return false;
Expand All @@ -50,7 +51,8 @@ public static bool CheckIsLaunchedByDotNet()

private static bool? CheckIsDotNetStartup2()
{
var hasPidArg = ElectronNetRuntime.ProcessArguments.Any(e => e.Contains(ElectronNetRuntime.ElectronPidArgumentName, StringComparison.OrdinalIgnoreCase));
var host = ElectronHostEnvironment.InternalHost;
var hasPidArg = host.ProcessArguments.Any(e => e.Contains(ElectronHostDefaults.ElectronPidArgumentName, StringComparison.OrdinalIgnoreCase));
if (hasPidArg)
{
return false;
Expand Down
Loading
Loading