Skip to content

Commit 9a615ca

Browse files
authored
Merge pull request #881 from hillin/reintroduce-#648
Reintroduce #648
2 parents 21c17dc + f9601a6 commit 9a615ca

File tree

11 files changed

+445
-2
lines changed

11 files changed

+445
-2
lines changed

src/ElectronNET.API/BridgeConnector.cs

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
namespace ElectronNET.API
1+
using System;
2+
using Newtonsoft.Json.Linq;
3+
using System.Threading;
4+
using System.Threading.Tasks;
5+
6+
namespace ElectronNET.API
27
{
38
internal static class BridgeConnector
49
{
@@ -28,6 +33,82 @@ public static SocketIoFacade Socket
2833

2934
return _socket;
3035
}
36+
}
37+
38+
public static async Task<T> GetValueOverSocketAsync<T>(string eventString, string eventCompletedString)
39+
{
40+
CancellationToken cancellationToken = new();
41+
cancellationToken.ThrowIfCancellationRequested();
42+
43+
var taskCompletionSource = new TaskCompletionSource<T>();
44+
using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled()))
45+
{
46+
BridgeConnector.Socket.On(eventCompletedString, (value) =>
47+
{
48+
BridgeConnector.Socket.Off(eventCompletedString);
49+
50+
if (value == null)
51+
{
52+
Console.WriteLine($"ERROR: BridgeConnector (event: '{eventString}') returned null. Socket loop hang.");
53+
taskCompletionSource.SetCanceled();
54+
return;
55+
}
56+
57+
try
58+
{
59+
taskCompletionSource.SetResult( new JValue(value).ToObject<T>() );
60+
}
61+
catch (Exception e)
62+
{
63+
Console.WriteLine($"ERROR: BridgeConnector (event: '{eventString}') exception: {e.Message}. Socket loop hung.");
64+
}
65+
});
66+
67+
BridgeConnector.Socket.Emit(eventString);
68+
69+
return await taskCompletionSource.Task.ConfigureAwait(false);
70+
}
71+
}
72+
73+
public static async Task<T> GetObjectOverSocketAsync<T>(string eventString, string eventCompletedString)
74+
{
75+
CancellationToken cancellationToken = new();
76+
cancellationToken.ThrowIfCancellationRequested();
77+
78+
var taskCompletionSource = new TaskCompletionSource<T>();
79+
using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled()))
80+
{
81+
BridgeConnector.Socket.On(eventCompletedString, (value) =>
82+
{
83+
BridgeConnector.Socket.Off(eventCompletedString);
84+
taskCompletionSource.SetResult( ((JObject)value).ToObject<T>() );
85+
});
86+
87+
BridgeConnector.Socket.Emit(eventString);
88+
89+
return await taskCompletionSource.Task.ConfigureAwait(false);
90+
}
91+
}
92+
93+
public static async Task<T> GetArrayOverSocketAsync<T>(string eventString, string eventCompletedString)
94+
{
95+
CancellationToken cancellationToken = new();
96+
cancellationToken.ThrowIfCancellationRequested();
97+
98+
var taskCompletionSource = new TaskCompletionSource<T>();
99+
using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled()))
100+
{
101+
BridgeConnector.Socket.On(eventCompletedString, (value) =>
102+
{
103+
BridgeConnector.Socket.Off(eventCompletedString);
104+
taskCompletionSource.SetResult( ((JArray)value).ToObject<T>() );
105+
});
106+
107+
BridgeConnector.Socket.Emit(eventString);
108+
109+
return await taskCompletionSource.Task.ConfigureAwait(false);
110+
}
31111
}
112+
32113
}
33114
}

src/ElectronNET.API/Electron.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,5 +88,10 @@ public static class Electron
8888
/// Control your app in the macOS dock.
8989
/// </summary>
9090
public static Dock Dock { get { return Dock.Instance; } }
91+
92+
/// <summary>
93+
/// Electeon extensions to the Nodejs process object.
94+
/// </summary>
95+
public static Process Process { get { return Process.Instance; } }
9196
}
9297
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace ElectronNET.API
2+
{
3+
/// <summary>
4+
/// An object listing the version strings specific to Electron
5+
/// </summary>
6+
/// <param name="Chrome">Value representing Chrome's version string</param>
7+
/// <param name="Electron">Value representing Electron's version string</param>
8+
/// <returns></returns>
9+
public record ProcessVersions(string Chrome, string Electron);
10+
}

src/ElectronNET.API/Process.cs

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
using System.Threading;
2+
using System.Threading.Tasks;
3+
using Newtonsoft.Json;
4+
using Newtonsoft.Json.Linq;
5+
6+
namespace ElectronNET.API
7+
{
8+
/// <summary>
9+
/// Electron's process object is extended from the Node.js process object. It adds the
10+
/// events, properties, and methods.
11+
/// </summary>
12+
public sealed class Process
13+
{
14+
internal Process() { }
15+
16+
internal static Process Instance
17+
{
18+
get
19+
{
20+
if (_process == null)
21+
{
22+
lock (_syncRoot)
23+
{
24+
if (_process == null)
25+
{
26+
_process = new Process();
27+
}
28+
}
29+
}
30+
31+
return _process;
32+
}
33+
}
34+
35+
private static Process _process;
36+
37+
private static readonly object _syncRoot = new();
38+
39+
/// <summary>
40+
/// The process.execPath property returns the absolute pathname of the executable that
41+
/// started the Node.js process. Symbolic links, if any, are resolved.
42+
/// </summary>
43+
public Task<string> ExecPathAsync
44+
{
45+
get
46+
{
47+
return BridgeConnector.GetValueOverSocketAsync<string>(
48+
"process-execPath", "process-execPath-Completed");
49+
}
50+
}
51+
52+
/// <summary>
53+
/// The process.argv property returns an array containing the command-line arguments passed
54+
/// when the Node.js process was launched. The first element will be process.execPath. See
55+
/// process.argv0 if access to the original value of argv[0] is needed. The second element
56+
/// will be the path to the JavaScript file being executed. The remaining elements will be
57+
/// any additional command-line arguments
58+
/// </summary>
59+
public Task<string[]> ArgvAsync
60+
{
61+
get
62+
{
63+
return BridgeConnector.GetArrayOverSocketAsync<string[]>(
64+
"process-argv", "process-argv-Completed");
65+
}
66+
}
67+
68+
/// <summary>
69+
/// The process.execPath property returns the absolute pathname of the executable that
70+
/// started the Node.js process. Symbolic links, if any, are resolved.
71+
/// </summary>
72+
public Task<string> TypeAsync
73+
{
74+
get
75+
{
76+
return BridgeConnector.GetValueOverSocketAsync<string>(
77+
"process-type", "process-type-Completed");
78+
}
79+
}
80+
81+
82+
/// <summary>
83+
/// The process.versions property returns an object listing the version strings of
84+
/// chrome and electron.
85+
/// </summary>
86+
public Task<ProcessVersions> VersionsAsync
87+
{
88+
get
89+
{
90+
return BridgeConnector.GetValueOverSocketAsync<ProcessVersions>(
91+
"process-versions", "process-versions-Completed");
92+
}
93+
}
94+
95+
96+
/// <summary>
97+
/// A Boolean. When app is started by being passed as parameter to the default app, this
98+
/// property is true in the main process, otherwise it is false.
99+
/// </summary>
100+
public Task<bool> DefaultAppAsync
101+
{
102+
get
103+
{
104+
return BridgeConnector.GetValueOverSocketAsync<bool>(
105+
"process-defaultApp", "process-defaultApp-Completed");
106+
}
107+
}
108+
109+
/// <summary>
110+
/// A Boolean, true when the current renderer context is the "main" renderer frame. If you
111+
/// want the ID of the current frame you should use webFrame.routingId
112+
/// </summary>
113+
public Task<bool> IsMainFrameAsync
114+
{
115+
get
116+
{
117+
return BridgeConnector.GetValueOverSocketAsync<bool>(
118+
"process-isMainFrame", "process-isMainFrame-Completed");
119+
}
120+
}
121+
122+
/// <summary>
123+
/// A String representing the path to the resources directory.
124+
/// </summary>
125+
public Task<string> ResourcesPathAsync
126+
{
127+
get
128+
{
129+
return BridgeConnector.GetValueOverSocketAsync<string>(
130+
"process-resourcesPath", "process-resourcesPath-Completed");
131+
}
132+
}
133+
134+
/// <summary>
135+
/// The number of seconds the current Node.js process has been running. The return value
136+
/// includes fractions of a second. Use Math.floor() to get whole seconds.
137+
/// </summary>
138+
public Task<double> UpTimeAsync
139+
{
140+
get
141+
{
142+
return BridgeConnector.GetValueOverSocketAsync<double>(
143+
"process-uptime", "process-uptime-Completed");
144+
}
145+
}
146+
147+
/// <summary>
148+
/// The PID of the electron process
149+
/// </summary>
150+
public Task<int> PidAsync
151+
{
152+
get
153+
{
154+
return BridgeConnector.GetValueOverSocketAsync<int>(
155+
"process-pid", "process-pid-Completed");
156+
}
157+
}
158+
159+
160+
/// <summary>
161+
/// The operating system CPU architecture for which the Node.js binary was compiled
162+
/// </summary>
163+
public Task<string> ArchAsync
164+
{
165+
get
166+
{
167+
return BridgeConnector.GetValueOverSocketAsync<string>(
168+
"process-arch", "process-arch-Completed");
169+
}
170+
}
171+
172+
/// <summary>
173+
/// A string identifying the operating system platform on which the Node.js process is running
174+
/// </summary>
175+
public Task<string> PlatformAsync
176+
{
177+
get
178+
{
179+
return BridgeConnector.GetValueOverSocketAsync<string>(
180+
"process-platform", "process-platform-Completed");
181+
}
182+
}
183+
184+
}
185+
}

src/ElectronNET.API/ServiceCollectionExtensions.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public static IServiceCollection AddElectron(this IServiceCollection services)
2828
.AddSingleton(provider => HostHook.Instance)
2929
.AddSingleton(provider => PowerMonitor.Instance)
3030
.AddSingleton(provider => NativeTheme.Instance)
31-
.AddSingleton(provider => Dock.Instance);
31+
.AddSingleton(provider => Dock.Instance)
32+
.AddSingleton(provider => Process.Instance);
3233
}
3334
}

src/ElectronNET.CLI/Commands/Actions/DeployEmbeddedElectronFiles.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public static void Do(string tempPath)
4242
EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "browserView.js", "api.");
4343
EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "powerMonitor.js", "api.");
4444
EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "nativeTheme.js", "api.");
45+
EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "process.js", "api.");
4546

4647
string splashscreenFolder = Path.Combine(tempPath, "splashscreen");
4748
if (Directory.Exists(splashscreenFolder) == false)

src/ElectronNET.CLI/ElectronNET.CLI.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
<EmbeddedResource Include="..\ElectronNET.Host\api\browserView.js" Link="ElectronHost\api\browserView.js" />
6969
<EmbeddedResource Include="..\ElectronNET.Host\api\powerMonitor.js" Link="ElectronHost\api\powerMonitor.js" />
7070
<EmbeddedResource Include="..\ElectronNET.Host\api\nativeTheme.js" Link="ElectronHost\api\nativeTheme.js" />
71+
<EmbeddedResource Include="..\ElectronNET.Host\api\process.js" Link="ElectronHost\api\process.js" />
7172
<EmbeddedResource Include="..\ElectronNET.Host\.vscode\launch.json" Link="ElectronHost\.vscode\launch.json" />
7273
<EmbeddedResource Include="..\ElectronNET.Host\.vscode\tasks.json" Link="ElectronHost\.vscode\tasks.json" />
7374
</ItemGroup>

src/ElectronNET.Host/api/process.js

Lines changed: 62 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/ElectronNET.Host/api/process.js.map

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)