Merge pull request #968 from adityashirsatrao007/feat/host-hook-sample

feat: Add ElectronHostHook sample application (#967)
This commit is contained in:
Florian Rappl
2025-12-09 10:21:36 +01:00
committed by GitHub
11 changed files with 197 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
using ElectronNET.API;
using Microsoft.AspNetCore.Mvc;
namespace ElectronNET.Samples.ElectronHostHook.Controllers
{
public class HomeController : Controller
{
public async Task<IActionResult> Index()
{
string message = "Electron not active";
if (HybridSupport.IsElectronActive)
{
// Call the HostHook defined in ElectronHostHook/index.ts
var result = await Electron.HostHook.CallAsync<string>("ping", "Hello from C#");
message = $"Sent 'Hello from C#', Received: '{result}'";
}
return View("Index", message);
}
}
}

View File

@@ -0,0 +1,3 @@
node_modules
*.js
*.js.map

View File

@@ -0,0 +1,21 @@
import { Socket } from "socket.io";
export class Connector {
constructor(private socket: Socket, public app: any) {
}
on(key: string, javaScriptCode: Function): void {
this.socket.on(key, (...args: any[]) => {
const id: string = args.pop();
try {
javaScriptCode(...args, (data) => {
if (data) {
this.socket.emit(`${key}Complete${id}`, data);
}
});
} catch (error) {
this.socket.emit(`${key}Error${id}`, `Host Hook Exception`, error);
}
});
}
}

View File

@@ -0,0 +1,16 @@
import { Connector } from "./connector";
import { Socket } from "socket.io";
export class HookService extends Connector {
constructor(socket: Socket, public app: any) {
super(socket, app);
}
onHostReady(): void {
// execute your own JavaScript Host logic here
this.on("ping", (msg, done) => {
console.log("Received ping from C#:", msg);
done("pong: " + msg);
});
}
}

View File

@@ -0,0 +1,12 @@
{
"name": "electron-host-hook",
"version": "1.0.0",
"description": "Connector for Electron.NET projects.",
"main": "index.js",
"dependencies": {
"socket.io": "^4.8.1"
},
"devDependencies": {
"typescript": "^5.9.3"
}
}

View File

@@ -0,0 +1,9 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "ES2019",
"sourceMap": true,
"skipLibCheck": true
},
"exclude": ["node_modules"]
}

View File

@@ -0,0 +1,36 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<ElectronNetDevMode>true</ElectronNetDevMode>
</PropertyGroup>
<Import Project="..\ElectronNET\build\ElectronNET.Core.props" Condition="$(ElectronNetDevMode)" />
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AspNetCoreHostingModel>OutOfProcess</AspNetCoreHostingModel>
<AspNetCoreModuleName>AspNetCoreModule</AspNetCoreModuleName>
<IsPackable>false</IsPackable>
<TypeScriptModuleKind>commonjs</TypeScriptModuleKind>
<TypeScriptUseNodeJS>true</TypeScriptUseNodeJS>
<TypeScriptTSConfig>ElectronHostHook/tsconfig.json</TypeScriptTSConfig>
<TypeScriptCompileOnSaveEnabled>true</TypeScriptCompileOnSaveEnabled>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
</PropertyGroup>
<ItemGroup>
<TypeScriptCompile Remove="**\node_modules\**" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ElectronNET.API\ElectronNET.API.csproj" Condition="$(ElectronNetDevMode)" />
<ProjectReference Include="..\ElectronNET.AspNet\ElectronNET.AspNet.csproj" Condition="$(ElectronNetDevMode)" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="ElectronNET.Core" Version="0.2.0" Condition="'$(ElectronNetDevMode)' != 'true'" />
<PackageReference Include="ElectronNET.Core.AspNet" Version="0.2.0" Condition="'$(ElectronNetDevMode)' != 'true'" />
<PackageReference Include="Microsoft.TypeScript.MSBuild" Version="5.9.3" />
</ItemGroup>
<Import Project="..\ElectronNET\build\ElectronNET.Core.targets" Condition="$(ElectronNetDevMode)" />
</Project>

View File

@@ -0,0 +1,31 @@
using ElectronNET.API;
namespace ElectronNET.Samples.ElectronHostHook
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseElectron(args, async () =>
{
var window = await Electron.WindowManager.CreateWindowAsync();
});
builder.Services.AddElectron();
builder.Services.AddControllersWithViews();
var app = builder.Build();
app.UseStaticFiles();
app.UseRouting();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
}
}
}

View File

@@ -0,0 +1,12 @@
{
"profiles": {
"ElectronNET.Samples.ElectronHostHook": {
"commandName": "Project",
"launchBrowser": false,
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@@ -0,0 +1,25 @@
@model string
@{
Layout = null;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width" />
<title>ElectronHostHook Sample</title>
<style>
body { font-family: sans-serif; padding: 20px; }
.result { padding: 10px; background-color: #f0f0f0; border: 1px solid #ccc; margin-top: 10px; }
</style>
</head>
<body>
<h1>ElectronHostHook Sample</h1>
<p>This sample demonstrates bidirectional communication between C# and the Electron Host process.</p>
<div class="result">
<strong>Result:</strong> @Model
</div>
</body>
</html>

View File

@@ -62,6 +62,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ElectronNET.IntegrationTest
EndProject
Project("{54A90642-561A-4BB1-A94E-469ADEE60C69}") = "ElectronNET.Host", "ElectronNET.Host\ElectronNET.Host.esproj", "{1C5FD66E-A1C6-C436-DF7C-3ECE4FEDDFE6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ElectronNET.Samples.ElectronHostHook", "ElectronNET.Samples.ElectronHostHook\ElectronNET.Samples.ElectronHostHook.csproj", "{B8D65F3A-7E54-4632-9F1C-46679237B312}"
ProjectSection(ProjectDependencies) = postProject
{1C5FD66E-A1C6-C436-DF7C-3ECE4FEDDFE6} = {1C5FD66E-A1C6-C436-DF7C-3ECE4FEDDFE6}
{8860606D-6847-F22A-5AED-DF4E0984DD24} = {8860606D-6847-F22A-5AED-DF4E0984DD24}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -105,6 +111,10 @@ Global
{1C5FD66E-A1C6-C436-DF7C-3ECE4FEDDFE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1C5FD66E-A1C6-C436-DF7C-3ECE4FEDDFE6}.Release|Any CPU.Build.0 = Release|Any CPU
{1C5FD66E-A1C6-C436-DF7C-3ECE4FEDDFE6}.Release|Any CPU.Deploy.0 = Release|Any CPU
{B8D65F3A-7E54-4632-9F1C-46679237B312}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B8D65F3A-7E54-4632-9F1C-46679237B312}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B8D65F3A-7E54-4632-9F1C-46679237B312}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B8D65F3A-7E54-4632-9F1C-46679237B312}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -120,6 +130,7 @@ Global
{06CAADC7-DE5B-47B4-AB2A-E9501459A2D1} = {D36CDFFD-3438-42E4-A7FF-88BA19AC4964}
{AE877E48-6B44-63C2-8EA0-DB58D096B553} = {75129C45-FC6F-41B0-A485-07F4A7E031ED}
{1C5FD66E-A1C6-C436-DF7C-3ECE4FEDDFE6} = {1BB6F634-2831-4496-83A6-BC6761DCEC8D}
{B8D65F3A-7E54-4632-9F1C-46679237B312} = {EDCBFC49-2AEE-4BAF-9368-4409298C52FC}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {81A62E71-9E04-4EFE-AD5C-23165375F8EF}