From ca748384cfa341627ee59c704654c650f6df285c Mon Sep 17 00:00:00 2001 From: Todd Schavey Date: Tue, 28 Dec 2021 21:40:53 -0500 Subject: [PATCH 1/6] fix #647 process argv for open-file for win and linux --- src/ElectronNET.Host/main.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/ElectronNET.Host/main.js b/src/ElectronNET.Host/main.js index 622342e0..02c3ff78 100644 --- a/src/ElectronNET.Host/main.js +++ b/src/ElectronNET.Host/main.js @@ -18,6 +18,27 @@ let launchUrl; let manifestJsonFileName = 'electron.manifest.json'; let watchable = false; + +// handle for opening the app with a file for win and linux +if (process && process.argv.length > 1) { + + let firstAppArgument = process.argv[1]; + + // With invoked via electronize, the first argument is the path to the main.js. + // Per issue #337, the /args switch can also be present. If either are present, + // we need to check the subsequent argument. + if (firstAppArgument === '..\\..\\main.js' || firstAppArgument === '../../main.js' || firstAppArgument === '/args') { + if (process.argv.length > 2) { + firstAppArgument = process.argv[2]; + } + } + + // only append the first app arg if it is not already a switch + if (!firstAppArgument.startsWith("--")) { + app.commandLine.appendSwitch("open-file", firstAppArgument); + } +} + if (app.commandLine.hasSwitch('manifest')) { manifestJsonFileName = app.commandLine.getSwitchValue('manifest'); } From f7de17f1ee53663a7eda00f081ff8590ba21561e Mon Sep 17 00:00:00 2001 From: Todd Schavey Date: Sun, 2 Jan 2022 16:46:14 -0500 Subject: [PATCH 2/6] fix #647 add initial Process class to ElectronNET.API --- src/ElectronNET.API/Electron.cs | 5 ++ src/ElectronNET.API/Process.cs | 61 +++++++++++++++++++ .../ServiceCollectionExtensions.cs | 3 +- .../Actions/DeployEmbeddedElectronFiles.cs | 1 + src/ElectronNET.CLI/ElectronNET.CLI.csproj | 1 + src/ElectronNET.Host/api/process.js | 10 +++ src/ElectronNET.Host/api/process.js.map | 1 + src/ElectronNET.Host/api/process.ts | 11 ++++ src/ElectronNET.Host/main.js | 2 + 9 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 src/ElectronNET.API/Process.cs create mode 100644 src/ElectronNET.Host/api/process.js create mode 100644 src/ElectronNET.Host/api/process.js.map create mode 100644 src/ElectronNET.Host/api/process.ts diff --git a/src/ElectronNET.API/Electron.cs b/src/ElectronNET.API/Electron.cs index 23f9902d..5c636164 100644 --- a/src/ElectronNET.API/Electron.cs +++ b/src/ElectronNET.API/Electron.cs @@ -88,5 +88,10 @@ public static class Electron /// Control your app in the macOS dock. /// public static Dock Dock { get { return Dock.Instance; } } + + /// + /// Electeon extensions to the Nodejs process object. + /// + public static Process Process { get { return Process.Instance; } } } } \ No newline at end of file diff --git a/src/ElectronNET.API/Process.cs b/src/ElectronNET.API/Process.cs new file mode 100644 index 00000000..daa692b2 --- /dev/null +++ b/src/ElectronNET.API/Process.cs @@ -0,0 +1,61 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace ElectronNET.API +{ + /// + /// Electron's process object is extended from the Node.js process object. It adds the + /// events, properties, and methods. + /// + public sealed class Process + { + internal Process() { } + + internal static Process Instance + { + get + { + if (_process == null) + { + lock (_syncRoot) + { + if (_process == null) + { + _process = new Process(); + } + } + } + + return _process; + } + } + + private static Process _process; + + private static readonly object _syncRoot = new(); + + /// + /// TBD + /// + /// + public async Task GetExecPathAsync(CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + + var taskCompletionSource = new TaskCompletionSource(); + using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled())) + { + BridgeConnector.Socket.On("process-execPathCompleted", (text) => + { + BridgeConnector.Socket.Off("process-execPathCompleted"); + taskCompletionSource.SetResult((string) text); + }); + + BridgeConnector.Socket.Emit("process-execPath"); + + return await taskCompletionSource.Task + .ConfigureAwait(false); + } + } + } +} diff --git a/src/ElectronNET.API/ServiceCollectionExtensions.cs b/src/ElectronNET.API/ServiceCollectionExtensions.cs index f933731b..a63aacf2 100644 --- a/src/ElectronNET.API/ServiceCollectionExtensions.cs +++ b/src/ElectronNET.API/ServiceCollectionExtensions.cs @@ -28,6 +28,7 @@ public static IServiceCollection AddElectron(this IServiceCollection services) .AddSingleton(provider => HostHook.Instance) .AddSingleton(provider => PowerMonitor.Instance) .AddSingleton(provider => NativeTheme.Instance) - .AddSingleton(provider => Dock.Instance); + .AddSingleton(provider => Dock.Instance) + .AddSingleton(provider => Process.Instance); } } diff --git a/src/ElectronNET.CLI/Commands/Actions/DeployEmbeddedElectronFiles.cs b/src/ElectronNET.CLI/Commands/Actions/DeployEmbeddedElectronFiles.cs index 205ff7b4..c0205b6a 100644 --- a/src/ElectronNET.CLI/Commands/Actions/DeployEmbeddedElectronFiles.cs +++ b/src/ElectronNET.CLI/Commands/Actions/DeployEmbeddedElectronFiles.cs @@ -42,6 +42,7 @@ public static void Do(string tempPath) EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "browserView.js", "api."); EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "powerMonitor.js", "api."); EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "nativeTheme.js", "api."); + EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "process.js", "api."); string splashscreenFolder = Path.Combine(tempPath, "splashscreen"); if (Directory.Exists(splashscreenFolder) == false) diff --git a/src/ElectronNET.CLI/ElectronNET.CLI.csproj b/src/ElectronNET.CLI/ElectronNET.CLI.csproj index fd30a574..074ffd87 100644 --- a/src/ElectronNET.CLI/ElectronNET.CLI.csproj +++ b/src/ElectronNET.CLI/ElectronNET.CLI.csproj @@ -68,6 +68,7 @@ + diff --git a/src/ElectronNET.Host/api/process.js b/src/ElectronNET.Host/api/process.js new file mode 100644 index 00000000..80bdaf79 --- /dev/null +++ b/src/ElectronNET.Host/api/process.js @@ -0,0 +1,10 @@ +"use strict"; +let electronSocket; +module.exports = (socket) => { + electronSocket = socket; + socket.on('process-execPath', () => { + const value = process.execPath; + electronSocket.emit('process-execPathCompleted', value); + }); +}; +//# sourceMappingURL=process.js.map \ No newline at end of file diff --git a/src/ElectronNET.Host/api/process.js.map b/src/ElectronNET.Host/api/process.js.map new file mode 100644 index 00000000..e2e659a4 --- /dev/null +++ b/src/ElectronNET.Host/api/process.js.map @@ -0,0 +1 @@ +{"version":3,"file":"process.js","sourceRoot":"","sources":["process.ts"],"names":[],"mappings":";AACA,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,EAAE;IACxB,cAAc,GAAG,MAAM,CAAC;IAExB,MAAM,CAAC,EAAE,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC;QAC/B,cAAc,CAAC,IAAI,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"} \ No newline at end of file diff --git a/src/ElectronNET.Host/api/process.ts b/src/ElectronNET.Host/api/process.ts new file mode 100644 index 00000000..a5598698 --- /dev/null +++ b/src/ElectronNET.Host/api/process.ts @@ -0,0 +1,11 @@ +import { Socket } from 'net'; +let electronSocket; + +export = (socket: Socket) => { + electronSocket = socket; + + socket.on('process-execPath', () => { + const value = process.execPath; + electronSocket.emit('process-execPathCompleted', value); + }); +}; diff --git a/src/ElectronNET.Host/main.js b/src/ElectronNET.Host/main.js index 02c3ff78..f90c2d5f 100644 --- a/src/ElectronNET.Host/main.js +++ b/src/ElectronNET.Host/main.js @@ -15,6 +15,7 @@ let nativeTheme; let dock; let launchFile; let launchUrl; +let processApi; let manifestJsonFileName = 'electron.manifest.json'; let watchable = false; @@ -250,6 +251,7 @@ function startSocketApiBridge(port) { if (powerMonitor === undefined) powerMonitor = require('./api/powerMonitor')(socket); if (nativeTheme === undefined) nativeTheme = require('./api/nativeTheme')(socket); if (dock === undefined) dock = require('./api/dock')(socket); + if (processApi === undefined) processApi = require('./api/process')(socket); socket.on('register-app-open-file-event', (id) => { global['electronsocket'] = socket; From dc019adb109345f31aa3926655ccacf0244b1acc Mon Sep 17 00:00:00 2001 From: Todd Schavey Date: Sun, 2 Jan 2022 18:28:39 -0500 Subject: [PATCH 3/6] #647 add to ElectronNET.API Process member interfaces for argv and type --- src/ElectronNET.API/Process.cs | 89 ++++++++++++++++++++++--- src/ElectronNET.Host/api/process.js | 8 +++ src/ElectronNET.Host/api/process.js.map | 2 +- src/ElectronNET.Host/api/process.ts | 10 +++ 4 files changed, 97 insertions(+), 12 deletions(-) diff --git a/src/ElectronNET.API/Process.cs b/src/ElectronNET.API/Process.cs index daa692b2..887eda39 100644 --- a/src/ElectronNET.API/Process.cs +++ b/src/ElectronNET.API/Process.cs @@ -1,5 +1,7 @@ using System.Threading; using System.Threading.Tasks; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; namespace ElectronNET.API { @@ -34,27 +36,92 @@ internal static Process Instance private static readonly object _syncRoot = new(); + /// + /// The process.execPath property returns the absolute pathname of the executable that started the Node.js process. Symbolic links, if any, are resolved. + /// + /// + /// + /// var path = await Electron.Process.ExecPathAsync; + /// + /// + public Task ExecPathAsync + { + get + { + CancellationToken cancellationToken = new(); + cancellationToken.ThrowIfCancellationRequested(); + + var taskCompletionSource = new TaskCompletionSource(); + using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled())) + { + BridgeConnector.Socket.On("process-execPathCompleted", (text) => + { + BridgeConnector.Socket.Off("process-execPathCompleted"); + taskCompletionSource.SetResult((string) text); + }); + + BridgeConnector.Socket.Emit("process-execPath"); + + return taskCompletionSource.Task; + } + } + } + /// /// TBD /// /// - public async Task GetExecPathAsync(CancellationToken cancellationToken = default) + public Task ArgvAsync { - cancellationToken.ThrowIfCancellationRequested(); + get + { + CancellationToken cancellationToken = new(); + cancellationToken.ThrowIfCancellationRequested(); - var taskCompletionSource = new TaskCompletionSource(); - using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled())) + var taskCompletionSource = new TaskCompletionSource(); + using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled())) + { + BridgeConnector.Socket.On("process-argvCompleted", (value) => + { + BridgeConnector.Socket.Off("process-argvCompleted"); + taskCompletionSource.SetResult( ((JArray)value).ToObject() ); + }); + + BridgeConnector.Socket.Emit("process-argv"); + + return taskCompletionSource.Task; + } + } + } + + /// + /// The process.execPath property returns the absolute pathname of the executable that started the Node.js process. Symbolic links, if any, are resolved. + /// + /// + /// + /// var path = await Electron.Process.ExecPathAsync; + /// + /// + public Task TypeAsync + { + get { - BridgeConnector.Socket.On("process-execPathCompleted", (text) => + CancellationToken cancellationToken = new(); + cancellationToken.ThrowIfCancellationRequested(); + + var taskCompletionSource = new TaskCompletionSource(); + using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled())) { - BridgeConnector.Socket.Off("process-execPathCompleted"); - taskCompletionSource.SetResult((string) text); - }); + BridgeConnector.Socket.On("process-typeCompleted", (text) => + { + BridgeConnector.Socket.Off("process-typeCompleted"); + taskCompletionSource.SetResult((string) text); + }); - BridgeConnector.Socket.Emit("process-execPath"); + BridgeConnector.Socket.Emit("process-type"); - return await taskCompletionSource.Task - .ConfigureAwait(false); + return taskCompletionSource.Task; + } } } } diff --git a/src/ElectronNET.Host/api/process.js b/src/ElectronNET.Host/api/process.js index 80bdaf79..00c929f4 100644 --- a/src/ElectronNET.Host/api/process.js +++ b/src/ElectronNET.Host/api/process.js @@ -6,5 +6,13 @@ module.exports = (socket) => { const value = process.execPath; electronSocket.emit('process-execPathCompleted', value); }); + socket.on('process-argv', () => { + const value = process.argv; + electronSocket.emit('process-argvCompleted', value); + }); + socket.on('process-type', () => { + const value = process.type; + electronSocket.emit('process-typeCompleted', value); + }); }; //# sourceMappingURL=process.js.map \ No newline at end of file diff --git a/src/ElectronNET.Host/api/process.js.map b/src/ElectronNET.Host/api/process.js.map index e2e659a4..1e69e30d 100644 --- a/src/ElectronNET.Host/api/process.js.map +++ b/src/ElectronNET.Host/api/process.js.map @@ -1 +1 @@ -{"version":3,"file":"process.js","sourceRoot":"","sources":["process.ts"],"names":[],"mappings":";AACA,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,EAAE;IACxB,cAAc,GAAG,MAAM,CAAC;IAExB,MAAM,CAAC,EAAE,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC;QAC/B,cAAc,CAAC,IAAI,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"} \ No newline at end of file +{"version":3,"file":"process.js","sourceRoot":"","sources":["process.ts"],"names":[],"mappings":";AACA,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,EAAE;IACxB,cAAc,GAAG,MAAM,CAAC;IAExB,MAAM,CAAC,EAAE,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC;QAC/B,cAAc,CAAC,IAAI,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,GAAG,EAAE;QAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;QAC3B,cAAc,CAAC,IAAI,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,GAAG,EAAE;QAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;QAC3B,cAAc,CAAC,IAAI,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"} \ No newline at end of file diff --git a/src/ElectronNET.Host/api/process.ts b/src/ElectronNET.Host/api/process.ts index a5598698..97c05698 100644 --- a/src/ElectronNET.Host/api/process.ts +++ b/src/ElectronNET.Host/api/process.ts @@ -8,4 +8,14 @@ export = (socket: Socket) => { const value = process.execPath; electronSocket.emit('process-execPathCompleted', value); }); + + socket.on('process-argv', () => { + const value = process.argv; + electronSocket.emit('process-argvCompleted', value); + }); + + socket.on('process-type', () => { + const value = process.type; + electronSocket.emit('process-typeCompleted', value); + }); }; From c01ef407afca1bea6024aa2985e91d0c5f6af294 Mon Sep 17 00:00:00 2001 From: Todd Schavey Date: Sun, 2 Jan 2022 22:46:53 -0500 Subject: [PATCH 4/6] fix #647 add to ElectronNET.API Process member interfaces for various fields --- src/ElectronNET.API/BridgeConnector.cs | 83 ++++++++++- src/ElectronNET.API/Entities/Versions.cs | 18 +++ src/ElectronNET.API/Process.cs | 169 +++++++++++++++-------- src/ElectronNET.Host/api/process.js | 50 ++++++- src/ElectronNET.Host/api/process.js.map | 2 +- src/ElectronNET.Host/api/process.ts | 58 +++++++- 6 files changed, 314 insertions(+), 66 deletions(-) create mode 100644 src/ElectronNET.API/Entities/Versions.cs diff --git a/src/ElectronNET.API/BridgeConnector.cs b/src/ElectronNET.API/BridgeConnector.cs index 23319e5e..a12b1304 100644 --- a/src/ElectronNET.API/BridgeConnector.cs +++ b/src/ElectronNET.API/BridgeConnector.cs @@ -1,4 +1,9 @@ -namespace ElectronNET.API +using System; +using Newtonsoft.Json.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace ElectronNET.API { internal static class BridgeConnector { @@ -28,6 +33,82 @@ public static SocketIoFacade Socket return _socket; } + } + + public static async Task GetValueOverSocketAsync(string eventString, string eventCompletedString) + { + CancellationToken cancellationToken = new(); + cancellationToken.ThrowIfCancellationRequested(); + + var taskCompletionSource = new TaskCompletionSource(); + using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled())) + { + BridgeConnector.Socket.On(eventCompletedString, (value) => + { + BridgeConnector.Socket.Off(eventCompletedString); + + if (value == null) + { + Console.WriteLine($"ERROR: BridgeConnector (event: '{eventString}') returned null. Socket loop hang."); + taskCompletionSource.SetCanceled(); + return; + } + + try + { + taskCompletionSource.SetResult( new JValue(value).ToObject() ); + } + catch (Exception e) + { + Console.WriteLine($"ERROR: BridgeConnector (event: '{eventString}') exception: {e.Message}. Socket loop hung."); + } + }); + + BridgeConnector.Socket.Emit(eventString); + + return await taskCompletionSource.Task.ConfigureAwait(false); + } + } + + public static async Task GetObjectOverSocketAsync(string eventString, string eventCompletedString) + { + CancellationToken cancellationToken = new(); + cancellationToken.ThrowIfCancellationRequested(); + + var taskCompletionSource = new TaskCompletionSource(); + using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled())) + { + BridgeConnector.Socket.On(eventCompletedString, (value) => + { + BridgeConnector.Socket.Off(eventCompletedString); + taskCompletionSource.SetResult( ((JObject)value).ToObject() ); + }); + + BridgeConnector.Socket.Emit(eventString); + + return await taskCompletionSource.Task.ConfigureAwait(false); + } + } + + public static async Task GetArrayOverSocketAsync(string eventString, string eventCompletedString) + { + CancellationToken cancellationToken = new(); + cancellationToken.ThrowIfCancellationRequested(); + + var taskCompletionSource = new TaskCompletionSource(); + using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled())) + { + BridgeConnector.Socket.On(eventCompletedString, (value) => + { + BridgeConnector.Socket.Off(eventCompletedString); + taskCompletionSource.SetResult( ((JArray)value).ToObject() ); + }); + + BridgeConnector.Socket.Emit(eventString); + + return await taskCompletionSource.Task.ConfigureAwait(false); + } } + } } \ No newline at end of file diff --git a/src/ElectronNET.API/Entities/Versions.cs b/src/ElectronNET.API/Entities/Versions.cs new file mode 100644 index 00000000..254a62c8 --- /dev/null +++ b/src/ElectronNET.API/Entities/Versions.cs @@ -0,0 +1,18 @@ +namespace ElectronNET.API +{ + /// + /// + /// + public class Versions + { + /// + /// Gets or sets a value representing Chrome's version string. + /// + public string Chrome { get; set; } + + /// + /// Gets or sets a value representing Electron's version string. + /// + public bool Electron { get; set; } + } +} \ No newline at end of file diff --git a/src/ElectronNET.API/Process.cs b/src/ElectronNET.API/Process.cs index 887eda39..0976d20b 100644 --- a/src/ElectronNET.API/Process.cs +++ b/src/ElectronNET.API/Process.cs @@ -37,92 +37,145 @@ internal static Process Instance private static readonly object _syncRoot = new(); /// - /// The process.execPath property returns the absolute pathname of the executable that started the Node.js process. Symbolic links, if any, are resolved. - /// - /// - /// - /// var path = await Electron.Process.ExecPathAsync; - /// - /// + /// The process.execPath property returns the absolute pathname of the executable that + /// started the Node.js process. Symbolic links, if any, are resolved. + /// public Task ExecPathAsync { get { - CancellationToken cancellationToken = new(); - cancellationToken.ThrowIfCancellationRequested(); - - var taskCompletionSource = new TaskCompletionSource(); - using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled())) - { - BridgeConnector.Socket.On("process-execPathCompleted", (text) => - { - BridgeConnector.Socket.Off("process-execPathCompleted"); - taskCompletionSource.SetResult((string) text); - }); - - BridgeConnector.Socket.Emit("process-execPath"); - - return taskCompletionSource.Task; - } + return BridgeConnector.GetValueOverSocketAsync( + "process-execPath", "process-execPath-Completed"); } } /// - /// TBD + /// The process.argv property returns an array containing the command-line arguments passed + /// when the Node.js process was launched. The first element will be process.execPath. See + /// process.argv0 if access to the original value of argv[0] is needed. The second element + /// will be the path to the JavaScript file being executed. The remaining elements will be + /// any additional command-line arguments /// - /// public Task ArgvAsync { get { - CancellationToken cancellationToken = new(); - cancellationToken.ThrowIfCancellationRequested(); + return BridgeConnector.GetArrayOverSocketAsync( + "process-argv", "process-argv-Completed"); + } + } - var taskCompletionSource = new TaskCompletionSource(); - using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled())) - { - BridgeConnector.Socket.On("process-argvCompleted", (value) => - { - BridgeConnector.Socket.Off("process-argvCompleted"); - taskCompletionSource.SetResult( ((JArray)value).ToObject() ); - }); + /// + /// The process.execPath property returns the absolute pathname of the executable that + /// started the Node.js process. Symbolic links, if any, are resolved. + /// + public Task TypeAsync + { + get + { + return BridgeConnector.GetValueOverSocketAsync( + "process-type", "process-type-Completed"); + } + } + + + /// + /// + /// + public Task VersionsAsync + { + get + { + return BridgeConnector.GetValueOverSocketAsync( + "process-versions", "process-versions-Completed"); + } + } + + + /// + /// + /// + public Task DefaultAppAsync + { + get + { + return BridgeConnector.GetValueOverSocketAsync( + "process-defaultApp", "process-defaultApp-Completed"); + } + } - BridgeConnector.Socket.Emit("process-argv"); + /// + /// + /// + public Task IsMainFrameAsync + { + get + { + return BridgeConnector.GetValueOverSocketAsync( + "process-isMainFrame", "process-isMainFrame-Completed"); + } + } - return taskCompletionSource.Task; - } + /// + /// + /// + public Task ResourcesPathAsync + { + get + { + return BridgeConnector.GetValueOverSocketAsync( + "process-resourcesPath", "process-resourcesPath-Completed"); } } /// - /// The process.execPath property returns the absolute pathname of the executable that started the Node.js process. Symbolic links, if any, are resolved. + /// /// - /// - /// - /// var path = await Electron.Process.ExecPathAsync; - /// - /// - public Task TypeAsync + public Task UpTimeAsync { get { - CancellationToken cancellationToken = new(); - cancellationToken.ThrowIfCancellationRequested(); + return BridgeConnector.GetValueOverSocketAsync( + "process-uptime", "process-uptime-Completed"); + } + } - var taskCompletionSource = new TaskCompletionSource(); - using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled())) - { - BridgeConnector.Socket.On("process-typeCompleted", (text) => - { - BridgeConnector.Socket.Off("process-typeCompleted"); - taskCompletionSource.SetResult((string) text); - }); + /// + /// + /// + public Task PidAsync + { + get + { + return BridgeConnector.GetValueOverSocketAsync( + "process-pid", "process-pid-Completed"); + } + } - BridgeConnector.Socket.Emit("process-type"); - return taskCompletionSource.Task; - } + /// + /// + /// + public Task ArchAsync + { + get + { + return BridgeConnector.GetValueOverSocketAsync( + "process-arch", "process-arch-Completed"); + } + } + + /// + /// + /// + public Task PlatformAsync + { + get + { + return BridgeConnector.GetValueOverSocketAsync( + "process-platform", "process-platform-Completed"); } } + } } diff --git a/src/ElectronNET.Host/api/process.js b/src/ElectronNET.Host/api/process.js index 00c929f4..36c08b4a 100644 --- a/src/ElectronNET.Host/api/process.js +++ b/src/ElectronNET.Host/api/process.js @@ -4,15 +4,59 @@ module.exports = (socket) => { electronSocket = socket; socket.on('process-execPath', () => { const value = process.execPath; - electronSocket.emit('process-execPathCompleted', value); + electronSocket.emit('process-execPath-Completed', value); }); socket.on('process-argv', () => { const value = process.argv; - electronSocket.emit('process-argvCompleted', value); + electronSocket.emit('process-argv-Completed', value); }); socket.on('process-type', () => { const value = process.type; - electronSocket.emit('process-typeCompleted', value); + electronSocket.emit('process-type-Completed', value); + }); + socket.on('process-versions', () => { + const value = process.versions; + electronSocket.emit('process-versions-Completed', value); + }); + socket.on('process-defaultApp', () => { + if (process.defaultApp === undefined) { + electronSocket.emit('process-defaultApp-Completed', false); + return; + } + electronSocket.emit('process-defaultApp-Completed', process.defaultApp); + }); + socket.on('process-isMainFrame', () => { + if (process.isMainFrame === undefined) { + electronSocket.emit('process-isMainFrame-Completed', false); + return; + } + electronSocket.emit('process-isMainFrame-Completed', process.isMainFrame); + }); + socket.on('process-resourcesPath', () => { + const value = process.resourcesPath; + electronSocket.emit('process-resourcesPath-Completed', value); + }); + socket.on('process-uptime', () => { + let value = process.uptime(); + if (value === undefined) { + value = -1; + } + electronSocket.emit('process-uptime-Completed', value); + }); + socket.on('process-pid', () => { + if (process.pid === undefined) { + electronSocket.emit('process-pid-Completed', -1); + return; + } + electronSocket.emit('process-pid-Completed', process.pid); + }); + socket.on('process-arch', () => { + const value = process.arch; + electronSocket.emit('process-arch-Completed', value); + }); + socket.on('process-platform', () => { + const value = process.platform; + electronSocket.emit('process-platform-Completed', value); }); }; //# sourceMappingURL=process.js.map \ No newline at end of file diff --git a/src/ElectronNET.Host/api/process.js.map b/src/ElectronNET.Host/api/process.js.map index 1e69e30d..096946ca 100644 --- a/src/ElectronNET.Host/api/process.js.map +++ b/src/ElectronNET.Host/api/process.js.map @@ -1 +1 @@ -{"version":3,"file":"process.js","sourceRoot":"","sources":["process.ts"],"names":[],"mappings":";AACA,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,EAAE;IACxB,cAAc,GAAG,MAAM,CAAC;IAExB,MAAM,CAAC,EAAE,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC;QAC/B,cAAc,CAAC,IAAI,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,GAAG,EAAE;QAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;QAC3B,cAAc,CAAC,IAAI,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,GAAG,EAAE;QAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;QAC3B,cAAc,CAAC,IAAI,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"} \ No newline at end of file +{"version":3,"file":"process.js","sourceRoot":"","sources":["process.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/ElectronNET.Host/api/process.ts b/src/ElectronNET.Host/api/process.ts index 97c05698..ad04dbf2 100644 --- a/src/ElectronNET.Host/api/process.ts +++ b/src/ElectronNET.Host/api/process.ts @@ -6,16 +6,68 @@ export = (socket: Socket) => { socket.on('process-execPath', () => { const value = process.execPath; - electronSocket.emit('process-execPathCompleted', value); + electronSocket.emit('process-execPath-Completed', value); }); socket.on('process-argv', () => { const value = process.argv; - electronSocket.emit('process-argvCompleted', value); + electronSocket.emit('process-argv-Completed', value); }); socket.on('process-type', () => { const value = process.type; - electronSocket.emit('process-typeCompleted', value); + electronSocket.emit('process-type-Completed', value); }); + + socket.on('process-versions', () => { + const value = process.versions; + electronSocket.emit('process-versions-Completed', value); + }); + + socket.on('process-defaultApp', () => { + if (process.defaultApp === undefined) { + electronSocket.emit('process-defaultApp-Completed', false); + return; + } + electronSocket.emit('process-defaultApp-Completed', process.defaultApp); + }); + + socket.on('process-isMainFrame', () => { + if (process.isMainFrame === undefined) { + electronSocket.emit('process-isMainFrame-Completed', false); + return; + } + electronSocket.emit('process-isMainFrame-Completed', process.isMainFrame); + }); + + socket.on('process-resourcesPath', () => { + const value = process.resourcesPath; + electronSocket.emit('process-resourcesPath-Completed', value); + }); + + socket.on('process-uptime', () => { + let value = process.uptime(); + if (value === undefined) { + value = -1; + } + electronSocket.emit('process-uptime-Completed', value); + }); + + socket.on('process-pid', () => { + if (process.pid === undefined) { + electronSocket.emit('process-pid-Completed', -1); + return; + } + electronSocket.emit('process-pid-Completed', process.pid); + }); + + socket.on('process-arch', () => { + const value = process.arch; + electronSocket.emit('process-arch-Completed', value); + }); + + socket.on('process-platform', () => { + const value = process.platform; + electronSocket.emit('process-platform-Completed', value); + }) }; From 8daf4d149801b24060735fb04dd12fa0aaac301f Mon Sep 17 00:00:00 2001 From: Todd Schavey Date: Mon, 3 Jan 2022 00:21:48 -0500 Subject: [PATCH 5/6] #647 update XML documentation to ElectronNET.API Process members --- src/ElectronNET.API/Process.cs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/ElectronNET.API/Process.cs b/src/ElectronNET.API/Process.cs index 0976d20b..b4a9d097 100644 --- a/src/ElectronNET.API/Process.cs +++ b/src/ElectronNET.API/Process.cs @@ -80,7 +80,8 @@ public Task TypeAsync /// - /// + /// The process.versions property returns an object listing the version strings of + /// chrome and electron. /// public Task VersionsAsync { @@ -93,7 +94,8 @@ public Task VersionsAsync /// - /// + /// A Boolean. When app is started by being passed as parameter to the default app, this + /// property is true in the main process, otherwise it is false. /// public Task DefaultAppAsync { @@ -105,7 +107,8 @@ public Task DefaultAppAsync } /// - /// + /// A Boolean, true when the current renderer context is the "main" renderer frame. If you + /// want the ID of the current frame you should use webFrame.routingId /// public Task IsMainFrameAsync { @@ -117,7 +120,7 @@ public Task IsMainFrameAsync } /// - /// + /// A String representing the path to the resources directory. /// public Task ResourcesPathAsync { @@ -129,7 +132,8 @@ public Task ResourcesPathAsync } /// - /// + /// The number of seconds the current Node.js process has been running. The return value + /// includes fractions of a second. Use Math.floor() to get whole seconds. /// public Task UpTimeAsync { @@ -141,7 +145,7 @@ public Task UpTimeAsync } /// - /// + /// The PID of the electron process /// public Task PidAsync { @@ -154,7 +158,7 @@ public Task PidAsync /// - /// + /// The operating system CPU architecture for which the Node.js binary was compiled /// public Task ArchAsync { @@ -166,7 +170,7 @@ public Task ArchAsync } /// - /// + /// A string identifying the operating system platform on which the Node.js process is running /// public Task PlatformAsync { From f9601a6e3e7fb0d2c714088ded8bfc137d01a6bf Mon Sep 17 00:00:00 2001 From: Todd Schavey Date: Tue, 4 Jan 2022 12:11:52 -0500 Subject: [PATCH 6/6] fix #647 make ProcessVersions Entity a record to ensure readonly access to props This is to address a PR #648 review comment to ensure that only the external users are not able to modify the instance values. --- .../Entities/ProcessVersions.cs | 10 ++++++++++ src/ElectronNET.API/Entities/Versions.cs | 18 ------------------ src/ElectronNET.API/Process.cs | 4 ++-- 3 files changed, 12 insertions(+), 20 deletions(-) create mode 100644 src/ElectronNET.API/Entities/ProcessVersions.cs delete mode 100644 src/ElectronNET.API/Entities/Versions.cs diff --git a/src/ElectronNET.API/Entities/ProcessVersions.cs b/src/ElectronNET.API/Entities/ProcessVersions.cs new file mode 100644 index 00000000..df41db65 --- /dev/null +++ b/src/ElectronNET.API/Entities/ProcessVersions.cs @@ -0,0 +1,10 @@ +namespace ElectronNET.API +{ + /// + /// An object listing the version strings specific to Electron + /// + /// Value representing Chrome's version string + /// Value representing Electron's version string + /// + public record ProcessVersions(string Chrome, string Electron); +} \ No newline at end of file diff --git a/src/ElectronNET.API/Entities/Versions.cs b/src/ElectronNET.API/Entities/Versions.cs deleted file mode 100644 index 254a62c8..00000000 --- a/src/ElectronNET.API/Entities/Versions.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace ElectronNET.API -{ - /// - /// - /// - public class Versions - { - /// - /// Gets or sets a value representing Chrome's version string. - /// - public string Chrome { get; set; } - - /// - /// Gets or sets a value representing Electron's version string. - /// - public bool Electron { get; set; } - } -} \ No newline at end of file diff --git a/src/ElectronNET.API/Process.cs b/src/ElectronNET.API/Process.cs index b4a9d097..e2217b7c 100644 --- a/src/ElectronNET.API/Process.cs +++ b/src/ElectronNET.API/Process.cs @@ -83,11 +83,11 @@ public Task TypeAsync /// The process.versions property returns an object listing the version strings of /// chrome and electron. /// - public Task VersionsAsync + public Task VersionsAsync { get { - return BridgeConnector.GetValueOverSocketAsync( + return BridgeConnector.GetValueOverSocketAsync( "process-versions", "process-versions-Completed"); } }