Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
819e643
Bump socket.io-parser in /src/ElectronNET.Host/ElectronHostHook
dependabot[bot] Aug 5, 2026
e5ccf75
Merge pull request #1094 from ElectronNET/dependabot/npm_and_yarn/src…
FlorianRappl Aug 5, 2026
1ec1fde
chore(build): fix #1096 by depends on not resolve related target
epsnm Aug 7, 2026
d9e9b3d
fix(packaging): Architecture must be defined in electron-builder comp…
epsnm Aug 10, 2026
3b57de9
Merge pull request #1098 from epsitec-sa/bug/#1097
FlorianRappl Aug 10, 2026
26b9d86
chore(build): target frameworks customization
epsnm Aug 10, 2026
4011f3d
Bump js-yaml in /src/ElectronNET.WebApp/ElectronHostHook
dependabot[bot] Aug 10, 2026
def289a
Bump brace-expansion in /src/ElectronNET.WebApp/ElectronHostHook
dependabot[bot] Aug 10, 2026
18f08f9
Bump electron from 30.5.1 to 39.8.10 in /src/ElectronNET.Host
dependabot[bot] Aug 10, 2026
382d544
Merge pull request #1101 from ElectronNET/dependabot/npm_and_yarn/src…
FlorianRappl Aug 11, 2026
f577a53
Merge pull request #1102 from ElectronNET/dependabot/npm_and_yarn/src…
FlorianRappl Aug 11, 2026
195a290
Merge pull request #1100 from ElectronNET/dependabot/npm_and_yarn/src…
FlorianRappl Aug 11, 2026
376a791
Merge pull request #1099 from epsitec-sa/bug/#1096
FlorianRappl Aug 11, 2026
8697c4d
chore(build): passthrough props barriere
epsnm Aug 14, 2026
b27f705
chore(build): Change import barriere
epsnm Aug 14, 2026
20ab82b
chore(build): fix error when props file is missing
epsnm Aug 14, 2026
76ff44f
Merge pull request #1104 from epsitec-sa/feat/#1095
FlorianRappl Aug 14, 2026
76dc687
Merged
FlorianRappl Sep 3, 2026
7e8f45b
Updated changelog
FlorianRappl Sep 3, 2026
9cb2100
Fixed #1105
FlorianRappl Sep 3, 2026
da0e1f1
Fixes #1097
FlorianRappl Sep 3, 2026
7af2e95
Fixed 1040
FlorianRappl Sep 4, 2026
0140749
Fixed #1103
FlorianRappl Sep 4, 2026
042d8e6
Infra enhancements
FlorianRappl Sep 4, 2026
7cd552a
Finished #1106
FlorianRappl Sep 4, 2026
672ff6c
Implemented #1003
FlorianRappl Sep 4, 2026
d5da1db
Fixed #1029
FlorianRappl Sep 4, 2026
248d4bd
Updated and improved migration checks #946
FlorianRappl Sep 4, 2026
703cf8f
Updated to use nsis on Windows
FlorianRappl Sep 4, 2026
98c72af
Updated zoom level
FlorianRappl Sep 4, 2026
fffd7df
Added more missing APIs
FlorianRappl Sep 4, 2026
a04ca0b
Completed APIs from #956
FlorianRappl Sep 4, 2026
deca816
Added template #414
FlorianRappl Sep 4, 2026
730eacb
Improved templates for preview version
FlorianRappl Sep 4, 2026
521e7c9
Removed references to electronize
FlorianRappl Sep 7, 2026
6d94cf9
Improved template
FlorianRappl Sep 7, 2026
a0c0523
Change default framework version to net10.0
FlorianRappl Sep 7, 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
29 changes: 29 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,32 @@
# 0.6.0

## ElectronNET.Core

- Updated dependencies
- Updated `WebContents` zoom level APIs to use `double` instead of `int` (#956)
- Improved migration checks to honor custom output paths and to detect `ProjectGuid` in publish profiles (#946)
- Fixed single instance handling on macOS (#1040)
- Fixed slow socket bridge startup by binding to an explicit loopback address (#1103)
- Fixed socket bridge connection when a system proxy is configured (#1105)
- Fixed electron-builder using the host RID instead of the target RID (#1097)
- Fixed cross-compilation behavior on same platform (#1098) @epsnm
- Fixed resolution of unrelated target (#1099) @epsnm
- Fixed false alarm for `ELECTRON001` on a root `package-lock.json` (#946)
- Added `ElectronNET.Core.Templates` package with a `dotnet new electron-blazor` template (#414)
- Added `WebContents.OnZoomChanged` event (#956)
- Added `WebContents` page loading APIs `LoadFileAsync`, `IsLoadingAsync`, `IsLoadingMainFrameAsync`, `IsWaitingForResponseAsync`, `Reload`, `ReloadIgnoringCache` and `Stop` (#956)
- Added `WebContents.InsertCSSAsync` and `WebContents.RemoveInsertedCSSAsync` for dynamic CSS (#956)
- Added `WebContents` editing and selection APIs (undo, redo, cut, copy, paste, insert text, select, ...) (#956)
- Added `WebContents.FindInPageAsync`, `WebContents.StopFindInPage` and the `OnFoundInPage` event (#956)
- Added `WebContents` audio events `OnAudioStateChanged`, `OnMediaStartedPlaying` and `OnMediaPaused` (#956)
- Added `WebContents.ScrollToTop` and `WebContents.ScrollToBottom` (#956)
- Added target framework customization (#1095) @epsnm
- Added configurable Electron root directory for custom packaging layouts (#1106) @DYH1319
- Added ability for `custom_main.js` to modify command line switches (#1029) @AeonSake
- Added migration checks for incomplete `ElectronHostHook` folders (`ELECTRON010`, `ELECTRON011`) (#946)
- Added `ElectronExecutableName` to separate the product name from the executable name (#1003) @AeonSake
- Added build extensibility properties `ElectronSkipExecCommands` and `ElectronIntermediatePublishDir` (#1106) @DYH1319

# 0.5.2

## ElectronNET.Core
Expand Down
7 changes: 7 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,11 @@
<!-- Uncomment to include parent Directory.Build.props file -->
<!--<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />-->

<PropertyGroup>
<ElectronNetBuildProps>$([MSBuild]::GetPathOfFileAbove('ElectronNet.Build.props', '$(MSBuildThisFileDirectory)../'))</ElectronNetBuildProps>
</PropertyGroup>

<!-- Only import specific project related MSBuild file -->
<Import Project="$(ElectronNetBuildProps)" Condition=" '$(ElectronNetBuildProps)' != '' " />

</Project>
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ While the classic Electron.NET setup (using an ASP.NET host run by the Electron
* ElectronNET.Core: [![NuGet](https://img.shields.io/nuget/v/ElectronNET.Core.svg?style=flat-square)](https://www.nuget.org/packages/ElectronNET.Core.API/)
* ElectronNET.Core.API: [![NuGet](https://img.shields.io/nuget/v/ElectronNET.Core.API.svg?style=flat-square)](https://www.nuget.org/packages/ElectronNET.Core.API/)
* ElectronNET.Core.AspNet: [![NuGet](https://img.shields.io/nuget/v/ElectronNET.Core.AspNet.svg?style=flat-square)](https://www.nuget.org/packages/ElectronNET.Core.AspNet/)
* ElectronNET.Core.Templates: [![NuGet](https://img.shields.io/nuget/v/ElectronNET.Core.Templates.svg?style=flat-square)](https://www.nuget.org/packages/ElectronNET.Core.Templates/)

## 🛠 Requirements to Run

You should have installed:

* .NET 6/8 or later.
* The minimum base OS is the same as [.NET 6](https://github.com/dotnet/core/blob/main/release-notes/6.0/supported-os.md) / [.NET 8](https://github.com/dotnet/core/blob/main/release-notes/8.0/supported-os.md).
* .NET 8/10 or later.
* The minimum base OS is the same as [.NET 8](https://github.com/dotnet/core/blob/main/release-notes/8.0/supported-os.md) / [.NET 10](https://github.com/dotnet/core/blob/main/release-notes/10.0/supported-os.md).
* Node.JS using at least [Version 22.x](https://nodejs.org).

## 👩‍🏫 Usage with ASP.NET
Expand Down Expand Up @@ -202,6 +203,8 @@ Alternatively, consider using a GitHub sponsorship for the core maintainers:
- [Gregor Biswanger](https://github.com/sponsors/GregorBiswanger)
- [Florian Rappl](https://github.com/sponsors/FlorianRappl)

Or just [buy Florian a coffee](https://buymeacoffee.com/florianrappl) :coffee:.

Any support appreciated! 🍻

## 🎉 License
Expand Down
208 changes: 208 additions & 0 deletions docs/API/WebContents.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,23 @@ Works for both BrowserWindows and BrowserViews.
- `isBrowserWindow` - Whether the webContents belong to a BrowserWindow or not (the other option is a BrowserView)
- `path` - Absolute path to the CSS file location

#### 🧊 `Task<string> InsertCSSAsync(string css, string cssOrigin = null)`
Injects CSS into the current web page and returns a unique key for the inserted style sheet.

**Parameters:**
- `css` - The style sheet to inject
- `cssOrigin` - Can be either `user` or `author`, defaults to `author`

**Returns:**

The key of the inserted style sheet, to be used with `RemoveInsertedCSSAsync`.

#### 🧊 `Task RemoveInsertedCSSAsync(string key)`
Removes a previously inserted style sheet from the current web page.

**Parameters:**
- `key` - The key returned by `InsertCSSAsync`

#### 🧊 `Task LoadURLAsync(string url)`
Loads the url in the window. The url must contain the protocol prefix.

Expand Down Expand Up @@ -113,6 +130,106 @@ Prints window's web page as PDF with Chromium's preview printing custom settings

Whether the PDF generation succeeded.

#### 🧊 `Task<double> GetZoomFactorAsync()`
Returns the current zoom factor. A factor of `1.0` means 100%.

#### 🧊 `void SetZoomFactor(double factor)`
Changes the zoom factor to the specified factor. The zoom factor is the zoom percent divided by 100, so 300% = `3.0`. The factor must be greater than `0.0`.

**Parameters:**
- `factor` - The zoom factor

#### 🧊 `Task<double> GetZoomLevelAsync()`
Returns the current zoom level.

#### 🧊 `void SetZoomLevel(double level)`
Changes the zoom level to the specified level. The original size is `0` and each increment above or below represents zooming 20% larger or smaller to default limits of 300% and 50% of the original size, respectively.

**Parameters:**
- `level` - The zoom level

#### 🧊 `Task SetVisualZoomLevelLimitsAsync(double minimumLevel, double maximumLevel)`
Sets the maximum and minimum pinch-to-zoom level.

**Parameters:**
- `minimumLevel` - The minimum pinch-to-zoom level
- `maximumLevel` - The maximum pinch-to-zoom level

#### 🧊 `Task LoadFileAsync(string filePath, LoadFileOptions options = null)`
Loads the given HTML file, relative to the root of the application.

**Parameters:**
- `filePath` - Path to the HTML file
- `options` - Optional `Query`, `Search` and `Hash` parts of the resulting URL

#### 🧊 `void SetAudioMuted(bool muted)`
Mutes or unmutes the audio on the current web page.

#### 🧊 `Task<bool> IsAudioMutedAsync()`
Whether this page has been muted.

#### 🧊 `Task<bool> IsCurrentlyAudibleAsync()`
Whether audio is currently playing.

#### 🧊 `Task<string> GetUserAgentAsync()` / `void SetUserAgent(string userAgent)`
Gets or overrides the user agent for this web page.

#### 🧊 `Task<bool> IsLoadingAsync()`
Whether the web page is still loading resources.

#### 🧊 `Task<bool> IsLoadingMainFrameAsync()`
Whether the main frame (and not just iframes or frames within it) is still loading.

#### 🧊 `Task<bool> IsWaitingForResponseAsync()`
Whether the web page is waiting for a first response from the main resource of the page.

#### 🧊 `void Reload()`
Reloads the current web page.

#### 🧊 `void ReloadIgnoringCache()`
Reloads the current web page and ignores the cache.

#### 🧊 `void Stop()`
Stops any pending navigation.

#### 🧊 `void Undo()` / `void Redo()`
Executes the `undo` / `redo` editing command in the web page.

#### 🧊 `void Cut()` / `void Copy()` / `void Paste()` / `void PasteAndMatchStyle()` / `void Delete()`
Executes the corresponding editing command in the web page.

#### 🧊 `void CopyImageAt(int x, int y)`
Copies the image at the given position to the clipboard.

#### 🧊 `void SelectAll()` / `void Unselect()` / `void CenterSelection()`
Selects all content, clears the selection, or scrolls to the current selection.

#### 🧊 `void ScrollToTop()` / `void ScrollToBottom()`
Scrolls to the top or the bottom of the current web page.

#### 🧊 `void AdjustSelection(AdjustSelectionOptions options)`
Adjusts the start and end points of the current text selection by the given amounts. Negative amounts move towards the beginning of the document.

#### 🧊 `Task InsertTextAsync(string text)`
Inserts text into the focused element.

#### 🧊 `void Replace(string text)` / `void ReplaceMisspelling(string text)`
Replaces the current selection, or the currently misspelled word, with the given text.

#### 🧊 `Task<int> FindInPageAsync(string text, FindInPageOptions options = null)`
Starts a request to find all matches for the text in the web page. Results are reported via the `OnFoundInPage` event.

**Parameters:**
- `text` - Content to be searched, must not be empty
- `options` - Optional `Forward`, `FindNext` and `MatchCase` flags

**Returns:**

The request id of the find request.

#### 🧊 `void StopFindInPage(StopFindInPageAction action)`
Stops any `FindInPageAsync` request with the given action (`ClearSelection`, `KeepSelection` or `ActivateSelection`).

## Events

#### ⚡ `InputEvent`
Expand Down Expand Up @@ -142,6 +259,21 @@ Emitted when the document in the top-level frame is loaded.
#### ⚡ `OnWillRedirect`
Emitted when a server side redirect occurs during navigation.

#### ⚡ `OnZoomChanged`
Emitted when the user changes the zoom level using the mouse wheel or the keyboard. The handler receives the `ZoomDirection` (`In` or `Out`).

#### ⚡ `OnFoundInPage`
Emitted when a result is available for a `FindInPageAsync` request. The handler receives a `FoundInPageResult`.

#### ⚡ `OnAudioStateChanged`
Emitted when media becomes audible or inaudible. The handler receives `true` if one or more frames or child web contents are emitting audio.

#### ⚡ `OnMediaStartedPlaying`
Emitted when media starts playing.

#### ⚡ `OnMediaPaused`
Emitted when media is paused or done playing.

## Usage Examples

### Page Loading
Expand Down Expand Up @@ -279,6 +411,82 @@ webContents.OnCrashed += (killed) =>
};
```

### Zoom Control

```csharp
// Set the zoom to 150%
webContents.SetZoomFactor(1.5);

var factor = await webContents.GetZoomFactorAsync();
Console.WriteLine($"Current zoom: {factor * 100}%");

// Zoom levels are relative: each step is 20% larger/smaller, 0 is the original size
webContents.SetZoomLevel(2);

// Restrict pinch-to-zoom
await webContents.SetVisualZoomLevelLimitsAsync(1, 3);

// React to zoom changes triggered by the user
webContents.OnZoomChanged += (direction) =>
{
Console.WriteLine($"User zoomed {direction}");
};
```

> **Note:** The zoom factor is shared by all windows using the same session partition. Assign a unique `WebPreferences.Partition` per window if each window should keep its own zoom.

### Dynamic CSS

```csharp
var key = await webContents.InsertCSSAsync("body { background-color: #202020; }");

// ... later
await webContents.RemoveInsertedCSSAsync(key);
```

### Editing and Selection

```csharp
await webContents.InsertTextAsync("Hello from .NET");

webContents.SelectAll();
webContents.Copy();
webContents.Unselect();
```

### Find in Page

```csharp
webContents.OnFoundInPage += (result) =>
{
Console.WriteLine($"{result.ActiveMatchOrdinal}/{result.Matches} matches");

if (result.FinalUpdate)
{
webContents.StopFindInPage(StopFindInPageAction.ClearSelection);
}
};

var requestId = await webContents.FindInPageAsync("electron", new FindInPageOptions { MatchCase = false });
```

### Audio

```csharp
webContents.SetAudioMuted(true);

var muted = await webContents.IsAudioMutedAsync();
var audible = await webContents.IsCurrentlyAudibleAsync();

webContents.OnAudioStateChanged += (isAudible) =>
{
Console.WriteLine(isAudible ? "Page started emitting audio" : "Page went silent");
};

webContents.OnMediaStartedPlaying += () => Console.WriteLine("Media playing");
webContents.OnMediaPaused += () => Console.WriteLine("Media paused");
```

## Related APIs

- [Electron.WindowManager](WindowManager.md) - Windows containing web contents
Expand Down
Loading
Loading