Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
04c1415
Bump lodash from 4.17.21 to 4.17.23 in /src/ElectronNET.Host
dependabot[bot] Jan 21, 2026
f4da958
Bump lodash in /src/ElectronNET.WebApp/ElectronHostHook
dependabot[bot] Jan 21, 2026
c1bf6d9
Updated version
FlorianRappl Mar 5, 2026
b8151a2
Changed facade to socket connection
FlorianRappl Mar 5, 2026
2010461
Merge pull request #1037 from ElectronNET/feature/socket-interface
FlorianRappl Mar 5, 2026
7930831
Added sample for auth
FlorianRappl Mar 18, 2026
8fc197b
Proposed fix for releaseNotes serialization #1039
FlorianRappl Mar 18, 2026
c9945a8
Bump flatted from 3.3.3 to 3.4.2 in /src/ElectronNET.Host
dependabot[bot] Mar 21, 2026
4c48588
Fix HasShadow not being true by default
AeonSake Mar 25, 2026
1d1b953
Merge pull request #1016 from ElectronNET/dependabot/npm_and_yarn/src…
FlorianRappl Mar 25, 2026
ce271fd
Merge pull request #1046 from ElectronNET/dependabot/npm_and_yarn/src…
FlorianRappl Mar 25, 2026
3f14f9a
Merge branch 'develop' into dependabot/npm_and_yarn/src/ElectronNET.W…
FlorianRappl Mar 25, 2026
005fedd
Merge pull request #1049 from AeonSake/1048-hasshadow-true-by-default
FlorianRappl Mar 25, 2026
2a14840
Merge pull request #1017 from ElectronNET/dependabot/npm_and_yarn/src…
FlorianRappl Mar 26, 2026
1e8b026
Merge pull request #1041 from ElectronNET/hotfix/autoupdater-checkfor…
FlorianRappl Mar 26, 2026
11f71fe
Automatic Port Selection and Secured Communication (#1038)
FlorianRappl May 9, 2026
833d288
Bump lodash from 4.17.23 to 4.18.1 in /src/ElectronNET.Host (#1059)
dependabot[bot] May 9, 2026
89f721d
Bump brace-expansion from 1.1.12 to 1.1.14 in /src/ElectronNET.WebApp…
dependabot[bot] May 9, 2026
e9b3ba0
Bump socket.io-parser in /src/ElectronNET.WebApp/ElectronHostHook (#1…
dependabot[bot] May 9, 2026
30b7b1d
Bump socket.io-parser in /src/ElectronNET.Host/ElectronHostHook (#1043)
dependabot[bot] May 9, 2026
d7e1a09
fix: correct ReleaseNotes deserialization for AutoUpdater (fixes #103…
GregorBiswanger May 9, 2026
50c9076
fix: replace ReadAllLines with ReadAllText in MigrationChecks.targets…
GregorBiswanger May 9, 2026
fe939e0
ci: stop hanging PR workflows and remove duplicate runs (#1063)
GregorBiswanger May 9, 2026
07be82c
WIP
FlorianRappl May 10, 2026
979b25f
Exclude file-system based transfer from #1038 (#1064)
FlorianRappl May 10, 2026
fee3806
Removed flag
FlorianRappl May 25, 2026
af5e70c
Fixed missing namespace reference
FlorianRappl May 25, 2026
c425195
Updated changelog
FlorianRappl May 25, 2026
558e582
Updated available lists
FlorianRappl May 25, 2026
fdab81a
Merge branch 'develop' of https://github.com/ElectronNET/Electron.NET…
FlorianRappl May 25, 2026
279a823
Improved demo and updated docs
FlorianRappl May 25, 2026
c76ce97
Merge pull request #1066 from ElectronNET/feature/auth-sample-docs
FlorianRappl May 25, 2026
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
14 changes: 13 additions & 1 deletion .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,16 @@ TL;DR: Unless there is a technical reason (e.g., a crucial new API not being ava

We pretty much release whenever we have something new (i.e., do fixes such as a 0.1.1, or add new features, such as a 0.2.0) quite quickly.

We will go for a 1.0.0 release of this as early as ~mid of January 2026 (unless we find some critical things or want to extend the beta phase for ElectronNET.Core). This should be sufficient time to get some user input and have enough experience to call it stable.
We will go for a 1.0.0 release of this as early as ~mid of June 2026 (unless we find some critical things or want to extend the beta phase for ElectronNET.Core). This should be sufficient time to get some user input and have enough experience to call it stable.

## Updating Electron Versions

The releases of Electron are found on the [releases.electronjs.org](https://releases.electronjs.org/release?page=1) website.

You can update the `src\ElectronNET\build\ElectronNETRules.Project.xaml` file with new entries using the following script (run it in the browser's console when being on the Electron Releases website):

```js
[...new Set([...document.querySelectorAll('tbody tr a[href^="/release/v"]')].map(m => m.getAttribute('href').replace('/release/v', '')))].map(m => `<EnumValue Name="${m}" DisplayName="${m}" />`).sort().join('\n')
```

Alternatively, use the website's information to feed into an AI agent of your choice.
4 changes: 3 additions & 1 deletion .github/workflows/Build and Publish.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
name: Build and Publish

on: [push]
on:
push:
branches: [main, develop]

env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
19 changes: 9 additions & 10 deletions .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ on:
workflow_call:

concurrency:
group: integration-tests-${{ github.ref }}
group: integration-tests-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
tests:
name: ${{ matrix.os }} API-${{ matrix.electronVersion }}
runs-on: ${{ matrix.os }}
timeout-minutes: 25
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -42,13 +43,6 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: Random delay (0-20 seconds)
shell: bash
run: |
DELAY=$((RANDOM % 21))
echo "Waiting for $DELAY seconds..."
sleep $DELAY

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
Expand Down Expand Up @@ -79,27 +73,31 @@ jobs:
- name: Run tests (Linux)
if: runner.os == 'Linux'
continue-on-error: true
timeout-minutes: 15
run: |
mkdir -p test-results
xvfb-run -a dotnet test src/ElectronNET.IntegrationTests/ElectronNET.IntegrationTests.csproj \
-c Release --no-build -r ${{ matrix.rid }} -p:RuntimeIdentifier=${{ matrix.rid }} -p:ElectronVersion=${{ matrix.electronVersion }} \
--logger "trx;LogFileName=${{ matrix.os }}-electron-${{ matrix.electronVersion }}.trx" \
--logger "console;verbosity=detailed" \
--blame-hang --blame-hang-timeout 5min \
--results-directory test-results

- name: Run tests (Windows)
if: runner.os == 'Windows'
continue-on-error: true
timeout-minutes: 15
run: |
New-Item -ItemType Directory -Force -Path test-results | Out-Null
dotnet test src/ElectronNET.IntegrationTests/ElectronNET.IntegrationTests.csproj -c Release --no-build -r ${{ matrix.rid }} -p:RuntimeIdentifier=${{ matrix.rid }} -p:ElectronVersion=${{ matrix.electronVersion }} --logger "trx;LogFileName=${{ matrix.os }}-electron-${{ matrix.electronVersion }}.trx" --logger "console;verbosity=detailed" --results-directory test-results
dotnet test src/ElectronNET.IntegrationTests/ElectronNET.IntegrationTests.csproj -c Release --no-build -r ${{ matrix.rid }} -p:RuntimeIdentifier=${{ matrix.rid }} -p:ElectronVersion=${{ matrix.electronVersion }} --logger "trx;LogFileName=${{ matrix.os }}-electron-${{ matrix.electronVersion }}.trx" --logger "console;verbosity=detailed" --blame-hang --blame-hang-timeout 5min --results-directory test-results

- name: Run tests (macOS)
if: runner.os == 'macOS'
continue-on-error: true
timeout-minutes: 15
run: |
mkdir -p test-results
dotnet test src/ElectronNET.IntegrationTests/ElectronNET.IntegrationTests.csproj -c Release --no-build -r ${{ matrix.rid }} -p:RuntimeIdentifier=${{ matrix.rid }} -p:ElectronVersion=${{ matrix.electronVersion }} --logger "trx;LogFileName=${{ matrix.os }}-electron-${{ matrix.electronVersion }}.trx" --logger "console;verbosity=detailed" --results-directory test-results
dotnet test src/ElectronNET.IntegrationTests/ElectronNET.IntegrationTests.csproj -c Release --no-build -r ${{ matrix.rid }} -p:RuntimeIdentifier=${{ matrix.rid }} -p:ElectronVersion=${{ matrix.electronVersion }} --logger "trx;LogFileName=${{ matrix.os }}-electron-${{ matrix.electronVersion }}.trx" --logger "console;verbosity=detailed" --blame-hang --blame-hang-timeout 5min --results-directory test-results

- name: Upload raw test results
if: always()
Expand All @@ -114,6 +112,7 @@ jobs:
runs-on: ubuntu-24.04
if: always()
needs: [tests]
timeout-minutes: 10

permissions:
actions: read
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/retry-test-jobs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
run: |
echo "Inspecting jobs of workflow run $RUN_ID in $REPO"

jobs_json="$(gh api -R $REPO repos/$REPO/actions/runs/$RUN_ID/jobs)"
jobs_json="$(gh api repos/$REPO/actions/runs/$RUN_ID/jobs)"

echo "Jobs and conclusions:"
echo "$jobs_json" | jq '.jobs[] | {name: .name, conclusion: .conclusion}'
Expand Down
10 changes: 10 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
## 0.5.0

## ElectronNET.Core

- Updated internal facade from `SocketIoFacade` to `ISocketConnection` (#1037)
- Fixed `HasShadow` is not `true` by default (#1049) @AeonSake
- Fixed missing `ReadAllLines` in MSBuild execution (#1035)
- Fixed serialization of release notes for the updater (#1041)
- Added automatic port selection and secured IPC communication (#1038)

# 0.4.1

## ElectronNET.Core
Expand Down
2 changes: 1 addition & 1 deletion docs/GettingStarted/Console-App.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Add the Electron.NET configuration to your `.csproj` file:
</PropertyGroup>

<ItemGroup>
<PackageReference Include="ElectronNET.Core" Version="0.4.1" />
<PackageReference Include="ElectronNET.Core" Version="0.5.0" />
</ItemGroup>
```

Expand Down
32 changes: 32 additions & 0 deletions docs/Using/Secure-Communication.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Secure Communication

By default, the IPC communication between .NET and Node.js is secured on startup. Consequently, multiple instances running on different user accounts (but shared on the same machine) can safely co-exist. However, this protection is not enough to secure the web application behind - or make any security statement w.r.t. a malicious root user.

## Securing the Web Application

You can opt-in to also guard your ASP.NET Core application using the same mechanism that is already used to protected the IPC broker that deals with the .NET to Node.js communication.

The key to opt-in is to provide another service *before* calling `AddElectron` on the service collection.

The following two namespaces are used in the next instructions:

```cs
using ElectronNET.AspNet.Middleware;
using ElectronNET.AspNet.Services;
```

You'll need the following line:

```cs
builder.Services.AddSingleton<IElectronAuthenticationService, ElectronAuthenticationService>();
```

This way, Electron.NET is notified that you want to store and re-use the authentication token that has been negotiated between the .NET and Node.js processes at startup.

With this being set up you can register a middleware to actually deny requests that have originated outside of your Electron.NET application:

```cs
app.UseMiddleware<ElectronAuthenticationMiddleware>();
```

This must be placed above any routing (e.g., before calling `UseRouting` on the web application) in order to properly take effect.
1 change: 1 addition & 0 deletions docs/_Sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
- [Startup-Methods](Using/Startup-Methods.md)
- [Debugging](Using/Debugging.md)
- [Package Building](Using/Package-Building.md)
- [Secure Communication](Using/Secure-Communication.md)
- [Adding a `custom_main.js`](Using/Custom_main.md)

# API Reference
Expand Down
3 changes: 2 additions & 1 deletion src/ElectronNET.API/API/Entities/BrowserWindowOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,8 @@ public class BrowserWindowOptions
/// <summary>
/// Whether window should have a shadow. Default is true.
/// </summary>
public bool HasShadow { get; set; }
[DefaultValue(true)]
public bool HasShadow { get; set; } = true;

/// <summary>
/// Forces using dark theme for the window, only works on some GTK+3 desktop environments. Default is false.
Expand Down
9 changes: 7 additions & 2 deletions src/ElectronNET.API/API/Entities/UpdateInfo.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
namespace ElectronNET.API.Entities
using System;
using System.Text.Json.Serialization;
using ElectronNET.API.Converter;

namespace ElectronNET.API.Entities
{
/// <summary>
///
Expand All @@ -24,7 +28,8 @@ public class UpdateInfo
/// <summary>
/// Gets or sets the release notes.
/// </summary>
public ReleaseNoteInfo[] ReleaseNotes { get; set; } = new ReleaseNoteInfo[0];
[JsonConverter(typeof(ReleaseNotesConverter))]
public ReleaseNoteInfo[] ReleaseNotes { get; set; } = Array.Empty<ReleaseNoteInfo>();

/// <summary>
/// Gets or sets the release date.
Expand Down
2 changes: 1 addition & 1 deletion src/ElectronNET.API/Bridge/BridgeConnector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace ElectronNET.API
{
internal static class BridgeConnector
{
public static SocketIoFacade Socket
public static ISocketConnection Socket
{
get
{
Expand Down
56 changes: 56 additions & 0 deletions src/ElectronNET.API/Bridge/ISocketConnection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
namespace ElectronNET.API;

using System;
using System.Threading.Tasks;

/// <summary>
/// Common interface for communication facades.
/// Provides methods for bidirectional communication between .NET and Electron.
/// </summary>
internal interface ISocketConnection : IDisposable
{
/// <summary>
/// Raised when the bridge connection is established.
/// </summary>
event EventHandler BridgeConnected;

/// <summary>
/// Raised when the bridge connection is lost.
/// </summary>
event EventHandler BridgeDisconnected;

/// <summary>
/// Establishes the connection to Electron.
/// </summary>
void Connect();

/// <summary>
/// Registers a persistent event handler.
/// </summary>
void On(string eventName, Action action);

/// <summary>
/// Registers a persistent event handler with a typed parameter.
/// </summary>
void On<T>(string eventName, Action<T> action);

/// <summary>
/// Registers a one-time event handler.
/// </summary>
void Once(string eventName, Action action);

/// <summary>
/// Registers a one-time event handler with a typed parameter.
/// </summary>
void Once<T>(string eventName, Action<T> action);

/// <summary>
/// Removes an event handler.
/// </summary>
void Off(string eventName);

/// <summary>
/// Sends a message to Electron.
/// </summary>
Task Emit(string eventName, params object[] args);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,29 @@
namespace ElectronNET.API;

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using ElectronNET.API.Serialization;
using SocketIO.Serializer.SystemTextJson;
using SocketIO = SocketIOClient.SocketIO;
using SocketIOOptions = SocketIOClient.SocketIOOptions;

internal class SocketIoFacade : IDisposable
internal class SocketIOConnection : ISocketConnection
{
private readonly SocketIO _socket;
private readonly object _lockObj = new object();
private bool _isDisposed;

public SocketIoFacade(string uri)
public SocketIOConnection(string uri, string authorization)
{
_socket = new SocketIO(uri);
var opts = string.IsNullOrEmpty(authorization) ? new SocketIOOptions() : new SocketIOOptions
{
ExtraHeaders = new Dictionary<string, string>
{
["authorization"] = authorization
},
};
_socket = new SocketIO(uri, opts);
_socket.Serializer = new SystemTextJsonSerializer(ElectronJson.Options);
// Use default System.Text.Json serializer from SocketIOClient.
// Outgoing args are normalized to camelCase via SerializeArg in Emit.
Expand Down Expand Up @@ -140,7 +149,7 @@ private void CheckDisposed()
{
if (this._isDisposed)
{
throw new ObjectDisposedException(nameof(SocketIoFacade));
throw new ObjectDisposedException(nameof(SocketIOConnection));
}
}
}
3 changes: 3 additions & 0 deletions src/ElectronNET.API/Common/ProcessRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public class ProcessRunner : IDisposable
private readonly StringBuilder stdOut = new StringBuilder(4 * 1024);
private readonly StringBuilder stdErr = new StringBuilder(4 * 1024);

public event EventHandler<string> LineReceived;

private volatile ManualResetEvent stdOutEvent;
private volatile ManualResetEvent stdErrEvent;
private volatile Stopwatch stopwatch;
Expand Down Expand Up @@ -571,6 +573,7 @@ private void Process_OutputDataReceived(object sender, DataReceivedEventArgs e)
if (e.Data != null)
{
Console.WriteLine("|| " + e.Data);
LineReceived?.Invoke(this, e.Data);
}
else
{
Expand Down
Loading
Loading