diff --git a/src/ElectronNET.API/API/Electron.cs b/src/ElectronNET.API/API/Electron.cs index 23f9902d..5c636164 100644 --- a/src/ElectronNET.API/API/Electron.cs +++ b/src/ElectronNET.API/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..e2217b7c --- /dev/null +++ b/src/ElectronNET.API/Process.cs @@ -0,0 +1,185 @@ +using System.Threading; +using System.Threading.Tasks; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +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(); + + /// + /// 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 + { + return BridgeConnector.GetValueOverSocketAsync( + "process-execPath", "process-execPath-Completed"); + } + } + + /// + /// 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 + { + return BridgeConnector.GetArrayOverSocketAsync( + "process-argv", "process-argv-Completed"); + } + } + + /// + /// 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"); + } + } + + + /// + /// The process.versions property returns an object listing the version strings of + /// chrome and electron. + /// + public Task VersionsAsync + { + get + { + return BridgeConnector.GetValueOverSocketAsync( + "process-versions", "process-versions-Completed"); + } + } + + + /// + /// 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 + { + get + { + return BridgeConnector.GetValueOverSocketAsync( + "process-defaultApp", "process-defaultApp-Completed"); + } + } + + /// + /// 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 + { + get + { + return BridgeConnector.GetValueOverSocketAsync( + "process-isMainFrame", "process-isMainFrame-Completed"); + } + } + + /// + /// A String representing the path to the resources directory. + /// + public Task ResourcesPathAsync + { + get + { + return BridgeConnector.GetValueOverSocketAsync( + "process-resourcesPath", "process-resourcesPath-Completed"); + } + } + + /// + /// 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 + { + get + { + return BridgeConnector.GetValueOverSocketAsync( + "process-uptime", "process-uptime-Completed"); + } + } + + /// + /// The PID of the electron process + /// + public Task PidAsync + { + get + { + return BridgeConnector.GetValueOverSocketAsync( + "process-pid", "process-pid-Completed"); + } + } + + + /// + /// The operating system CPU architecture for which the Node.js binary was compiled + /// + public Task ArchAsync + { + get + { + return BridgeConnector.GetValueOverSocketAsync( + "process-arch", "process-arch-Completed"); + } + } + + /// + /// A string identifying the operating system platform on which the Node.js process is running + /// + 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 new file mode 100644 index 00000000..36c08b4a --- /dev/null +++ b/src/ElectronNET.Host/api/process.js @@ -0,0 +1,62 @@ +"use strict"; +let electronSocket; +module.exports = (socket) => { + electronSocket = socket; + socket.on('process-execPath', () => { + const value = process.execPath; + electronSocket.emit('process-execPath-Completed', value); + }); + socket.on('process-argv', () => { + const value = process.argv; + electronSocket.emit('process-argv-Completed', value); + }); + socket.on('process-type', () => { + const value = process.type; + 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 new file mode 100644 index 00000000..096946ca --- /dev/null +++ b/src/ElectronNET.Host/api/process.js.map @@ -0,0 +1 @@ +{"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 new file mode 100644 index 00000000..ad04dbf2 --- /dev/null +++ b/src/ElectronNET.Host/api/process.ts @@ -0,0 +1,73 @@ +import { Socket } from 'net'; +let electronSocket; + +export = (socket: Socket) => { + electronSocket = socket; + + socket.on('process-execPath', () => { + const value = process.execPath; + electronSocket.emit('process-execPath-Completed', value); + }); + + socket.on('process-argv', () => { + const value = process.argv; + electronSocket.emit('process-argv-Completed', value); + }); + + socket.on('process-type', () => { + const value = process.type; + 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); + }) +}; diff --git a/src/ElectronNET.Host/main.js b/src/ElectronNET.Host/main.js index 4019948a..43c18e2e 100644 --- a/src/ElectronNET.Host/main.js +++ b/src/ElectronNET.Host/main.js @@ -16,6 +16,7 @@ let nativeTheme; let dock; let launchFile; let launchUrl; +let processApi; let manifestJsonFileName = 'package.json'; let unpackedelectron = false; diff --git a/src/ElectronNET.Host/package-lock.json b/src/ElectronNET.Host/package-lock.json index 4a45d86d..b33937e9 100644 --- a/src/ElectronNET.Host/package-lock.json +++ b/src/ElectronNET.Host/package-lock.json @@ -18,7 +18,7 @@ }, "devDependencies": { "@types/node": "^22.18", - "electron": "^30.0.3", + "electron": "^35.7.5", "eslint": "^9.37.0", "typescript": "^5.9.3" } @@ -699,14 +699,15 @@ "optional": true }, "node_modules/electron": { - "version": "30.5.1", - "resolved": "https://registry.npmjs.org/electron/-/electron-30.5.1.tgz", - "integrity": "sha512-AhL7+mZ8Lg14iaNfoYTkXQ2qee8mmsQyllKdqxlpv/zrKgfxz6jNVtcRRbQtLxtF8yzcImWdfTQROpYiPumdbw==", + "version": "35.7.5", + "resolved": "https://registry.npmjs.org/electron/-/electron-35.7.5.tgz", + "integrity": "sha512-dnL+JvLraKZl7iusXTVTGYs10TKfzUi30uEDTqsmTm0guN9V2tbOjTzyIZbh9n3ygUjgEYyo+igAwMRXIi3IPw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "dependencies": { "@electron/get": "^2.0.0", - "@types/node": "^20.9.0", + "@types/node": "^22.7.7", "extract-zip": "^2.0.1" }, "bin": { @@ -778,15 +779,6 @@ "node": ">= 10.0.0" } }, - "node_modules/electron/node_modules/@types/node": { - "version": "20.19.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.21.tgz", - "integrity": "sha512-CsGG2P3I5y48RPMfprQGfy4JPRZ6csfC3ltBZSRItG3ngggmNY/qs2uZKp4p9VbrpqNNSMzUZNFZKzgOGnd/VA==", - "dev": true, - "dependencies": { - "undici-types": "~6.21.0" - } - }, "node_modules/end-of-stream": { "version": "1.4.5", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", diff --git a/src/ElectronNET.Host/package.json b/src/ElectronNET.Host/package.json index 183fca0a..18263315 100644 --- a/src/ElectronNET.Host/package.json +++ b/src/ElectronNET.Host/package.json @@ -21,7 +21,7 @@ }, "devDependencies": { "@types/node": "^22.18", - "electron": "^30.0.3", + "electron": "^35.7.5", "eslint": "^9.37.0", "typescript": "^5.9.3" }