@devscholar/node-ps1-dotnet 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/EnsureBom.ps1 +27 -0
  2. package/LICENSE.md +22 -0
  3. package/README.md +65 -0
  4. package/examples/console/await-delay/await-delay.ts +14 -0
  5. package/examples/console/console-input/console-input.ts +18 -0
  6. package/examples/winforms/counter/counter.ts +47 -0
  7. package/examples/winforms/drag-box/drag-box.ts +62 -0
  8. package/examples/wpf/counter/counter.ts +55 -0
  9. package/examples/wpf/drag-box/drag-box.ts +84 -0
  10. package/examples/wpf/webview2-browser/WebView2Libs/Microsoft.Web.WebView2.Core.dll +0 -0
  11. package/examples/wpf/webview2-browser/WebView2Libs/Microsoft.Web.WebView2.Core.dll.backup +0 -0
  12. package/examples/wpf/webview2-browser/WebView2Libs/Microsoft.Web.WebView2.Wpf.dll +0 -0
  13. package/examples/wpf/webview2-browser/WebView2Libs/Microsoft.Web.WebView2.Wpf.dll.backup +0 -0
  14. package/examples/wpf/webview2-browser/WebView2Libs/WebView2License.txt +27 -0
  15. package/examples/wpf/webview2-browser/counter.html +31 -0
  16. package/examples/wpf/webview2-browser/webview2-browser.ts +90 -0
  17. package/package.json +19 -0
  18. package/scripts/PsBridge/BridgeState.cs +39 -0
  19. package/scripts/PsBridge/Protocol.cs +222 -0
  20. package/scripts/PsBridge/PsBridge.psd1 +10 -0
  21. package/scripts/PsBridge/PsBridge.psm1 +22 -0
  22. package/scripts/PsBridge/PsHost.cs +393 -0
  23. package/scripts/PsBridge/PsHostEntry.cs +23 -0
  24. package/scripts/PsBridge/Reflection.cs +830 -0
  25. package/scripts/PsHost.ps1 +11 -0
  26. package/src/index.ts +510 -0
  27. package/src/ipc.ts +182 -0
  28. package/src/types.ts +21 -0
  29. package/src/utils.ts +13 -0
  30. package/start.js +67 -0
  31. package/tsconfig.json +14 -0
package/EnsureBom.ps1 ADDED
@@ -0,0 +1,27 @@
1
+ $ErrorActionPreference = 'Stop'
2
+
3
+ $extensions = @('.c', '.cpp', '.ps1')
4
+ $rootPath = (Get-Location).Path
5
+ $scriptPath = $MyInvocation.MyCommand.Path
6
+
7
+ $files = Get-ChildItem -Path $rootPath -Recurse -File | Where-Object { $extensions -contains $_.Extension }
8
+
9
+ foreach ($file in $files) {
10
+ if ($file.FullName -eq $scriptPath) {
11
+ continue
12
+ }
13
+
14
+ $bytes = [System.IO.File]::ReadAllBytes($file.FullName)
15
+ $hasBom = $bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF
16
+
17
+ if ($hasBom) {
18
+ Write-Host "Skipped (already BOM): $($file.FullName)"
19
+ continue
20
+ }
21
+
22
+ $content = [System.Text.Encoding]::UTF8.GetString($bytes)
23
+ [System.IO.File]::WriteAllText($file.FullName, $content, [System.Text.UTF8Encoding]::new($true))
24
+ Write-Host "Converted: $($file.FullName)"
25
+ }
26
+
27
+ Write-Host "Done."
package/LICENSE.md ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) DevScholar
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,65 @@
1
+ # Node PS1 for .NET
2
+
3
+ ⚠️ This project is still in pre-alpha stage, and API is subject to change.
4
+
5
+ This is a project that mimics the [Node API for .NET](https://github.com/microsoft/node-api-dotnet), aiming to utilize the built-in PowerShell 5.1 in Windows to replace the full high-version .NET runtime, thereby reducing the program's size. Since this project uses IPC instead of C++ Addon, it is compatible not only with Node but also with Deno and Bun. You can run its example programs in the examples folder.
6
+
7
+ # Requirements
8
+
9
+ - **Node.js** 22+ (uses `--experimental-transform-types` for native TypeScript support)
10
+ - **PowerShell** 5.1 (built-in on Windows 10/11)
11
+ - **.NET Framework** 4.5+ (required by PowerShell 5.1, pre-installed on Windows 10/11)
12
+
13
+ > Note: This project is Windows-only due to its dependency on PowerShell 5.1.
14
+
15
+ # Examples
16
+
17
+ You can use the `--runtime=[node|deno|bun]` option to specify the runtime. For example:
18
+
19
+ ```bat
20
+ node start.js examples/console/console-input/console-input.ts --runtime=deno
21
+ ```
22
+
23
+ ## Console Apps
24
+
25
+ ### Console Input App
26
+
27
+ ```bat
28
+ node start.js examples/console/console-input/console-input.ts
29
+ ```
30
+ ### Await Delay App
31
+
32
+ ```bat
33
+ node start.js examples/console/await-delay/await-delay.ts
34
+ ```
35
+
36
+ ## GUI Apps
37
+
38
+ ### WinForms Counter App
39
+
40
+ ```bat
41
+ node start.js examples/winforms/counter/counter.ts
42
+ ```
43
+ ### WinForms Drag Box App
44
+
45
+ ```bat
46
+ node start.js examples/winforms/drag-box/drag-box.ts
47
+ ```
48
+ ### WPF Counter App
49
+
50
+ ```bat
51
+ node start.js examples/wpf/counter/counter.ts
52
+ ```
53
+ ### WPF Drag Box App
54
+
55
+ ```bat
56
+ node start.js examples/wpf/drag-box/drag-box.ts
57
+ ```
58
+ ### WPF WebView2 Browser
59
+
60
+ ```bat
61
+ node start.js examples/wpf/webview2-browser/webview2-browser.ts
62
+ ```
63
+ # License
64
+
65
+ This project is licensed under the MIT License. See the [LICENSE](LICENSE.md) file for details.
@@ -0,0 +1,14 @@
1
+ // examples/console/await-delay/await-delay.ts
2
+ import dotnet from '../../../src/index.ts';
3
+
4
+ const System = dotnet.System as any;
5
+ const Console = System.Console;
6
+ const Task = System.Threading.Tasks.Task;
7
+ const Path = System.IO.Path;
8
+
9
+ Console.WriteLine('0s');
10
+ await Task.Delay(1000);
11
+ await Console.Out.WriteLineAsync("1s");
12
+ await Task.Delay(1000);
13
+ await Console.Out.WriteLineAsync("2s");
14
+ await Task.Delay(1000);
@@ -0,0 +1,18 @@
1
+ // examples/console/console-input/console-input.ts
2
+ import dotnet from '../../../src/index.ts';
3
+
4
+ const System = dotnet.System as any;
5
+ const Console = System.Console;
6
+
7
+ Console.WriteLine("=== Greeting Program ===");
8
+ Console.Write("Please enter your name: ");
9
+
10
+ const name = Console.ReadLine();
11
+
12
+ if (name && name.trim() !== "") {
13
+ Console.WriteLine(`Hello, ${name}! Welcome to this program!`);
14
+ } else {
15
+ Console.WriteLine("Hello, friend! Welcome to this program!");
16
+ }
17
+
18
+ Console.WriteLine("Program ended.");
@@ -0,0 +1,47 @@
1
+ // examples/winforms/counter/counter.ts
2
+ import dotnet from '../../../src/index.ts';
3
+
4
+ dotnet.load('System.Windows.Forms');
5
+ dotnet.load('System.Drawing');
6
+
7
+ const System = dotnet.System as any;
8
+ const Forms = System.Windows.Forms;
9
+ const Drawing = System.Drawing;
10
+
11
+ let clickCount = 0;
12
+
13
+ console.log("--- WinForms Counter (XP Style) ---");
14
+
15
+ Forms.Application.EnableVisualStyles();
16
+ Forms.Application.SetCompatibleTextRenderingDefault(false);
17
+
18
+ const form = new Forms.Form();
19
+ form.Text = "Counter App";
20
+ form.Width = 640;
21
+ form.Height = 480;
22
+ form.StartPosition = 1;
23
+
24
+ const label = new Forms.Label();
25
+ label.Text = "Clicks: 0";
26
+ label.Font = new Drawing.Font("Arial", 24);
27
+ label.AutoSize = true;
28
+ label.Location = new Drawing.Point(90, 30);
29
+ form.Controls.Add(label);
30
+
31
+ const button = new Forms.Button();
32
+ button.Text = "Click to Add";
33
+ button.Font = new Drawing.Font("Arial", 14);
34
+ button.AutoSize = true;
35
+ button.Location = new Drawing.Point(100, 90);
36
+
37
+ button.add_Click(() => {
38
+ clickCount++;
39
+ const message = `Clicked ${clickCount} times`;
40
+ label.Text = message;
41
+ console.log(message);
42
+ });
43
+
44
+ form.Controls.Add(button);
45
+
46
+ console.log("Click the button to increase the counter...");
47
+ Forms.Application.Run(form);
@@ -0,0 +1,62 @@
1
+ // examples/winforms/drag-box/drag-box.ts
2
+ import dotnet from '../../../src/index.ts';
3
+
4
+ dotnet.load('System.Windows.Forms');
5
+ dotnet.load('System.Drawing');
6
+
7
+ const System = dotnet.System as any;
8
+ const Forms = System.Windows.Forms;
9
+ const Drawing = System.Drawing;
10
+
11
+ console.log("--- WinForms Draggable Box ---");
12
+
13
+ Forms.Application.EnableVisualStyles();
14
+ Forms.Application.SetCompatibleTextRenderingDefault(false);
15
+
16
+ const form = new Forms.Form();
17
+ form.Text = "Draggable Box Example (High Frequency IPC)";
18
+ form.Width = 800;
19
+ form.Height = 600;
20
+ form.StartPosition = 1; // CenterScreen
21
+
22
+ const box = new Forms.Panel();
23
+ box.BackColor = Drawing.Color.Red;
24
+ box.Width = 100;
25
+ box.Height = 100;
26
+
27
+ // Track position locally to avoid synchronous read overhead over IPC
28
+ let currentX = 350;
29
+ let currentY = 250;
30
+ box.Location = new Drawing.Point(currentX, currentY);
31
+
32
+ form.Controls.Add(box);
33
+
34
+ // State tracking for drag and drop
35
+ let isDragging = false;
36
+ let startDragOffsetX = 0;
37
+ let startDragOffsetY = 0;
38
+
39
+ box.add_MouseDown((sender: any, e: any) => {
40
+ isDragging = true;
41
+ startDragOffsetX = e.X;
42
+ startDragOffsetY = e.Y;
43
+ box.BackColor = Drawing.Color.DarkRed; // Visual feedback
44
+ });
45
+
46
+ box.add_MouseUp((sender: any, e: any) => {
47
+ isDragging = false;
48
+ box.BackColor = Drawing.Color.Red;
49
+ });
50
+
51
+ box.add_MouseMove((sender: any, e: any) => {
52
+ if (isDragging) {
53
+ currentX = currentX + e.X - startDragOffsetX;
54
+ currentY = currentY + e.Y - startDragOffsetY;
55
+
56
+ box.Left = currentX;
57
+ box.Top = currentY;
58
+ }
59
+ });
60
+
61
+ console.log("Initialization complete. Try dragging the red box!");
62
+ Forms.Application.Run(form);
@@ -0,0 +1,55 @@
1
+ import dotnet from '../../../src/index.ts';
2
+
3
+ dotnet.load('PresentationFramework');
4
+ dotnet.load('PresentationCore');
5
+ dotnet.load('WindowsBase');
6
+
7
+ const System = dotnet.System as any;
8
+ const Windows = System.Windows;
9
+ const Controls = System.Windows.Controls;
10
+ const Media = System.Windows.Media;
11
+
12
+ let clickCount = 0;
13
+
14
+ console.log("--- WPF Counter ---");
15
+
16
+ const mainWindow = new Windows.Window();
17
+ mainWindow.Title = "WPF Counter App";
18
+ mainWindow.Width = 400;
19
+ mainWindow.Height = 300;
20
+ mainWindow.WindowStartupLocation = Windows.WindowStartupLocation.CenterScreen;
21
+
22
+ const stackPanel = new Controls.StackPanel();
23
+ stackPanel.Margin = new Windows.Thickness(20);
24
+ stackPanel.HorizontalAlignment = Windows.HorizontalAlignment.Center;
25
+ stackPanel.VerticalAlignment = Windows.VerticalAlignment.Center;
26
+
27
+ const label = new Controls.Label();
28
+ label.Content = "Clicks: 0";
29
+ label.FontSize = 32;
30
+ label.FontFamily = new Media.FontFamily("Arial");
31
+ label.HorizontalContentAlignment = Windows.HorizontalAlignment.Center;
32
+ label.Margin = new Windows.Thickness(0, 0, 0, 20);
33
+ stackPanel.Children.Add(label);
34
+
35
+ const button = new Controls.Button();
36
+ button.Content = "Click to Add";
37
+ button.FontSize = 18;
38
+ button.Padding = new Windows.Thickness(20, 10, 20, 10);
39
+ button.HorizontalAlignment = Windows.HorizontalAlignment.Center;
40
+
41
+ button.add_Click((sender: any, e: any) => {
42
+ clickCount++;
43
+ const message = `Clicked ${clickCount} times`;
44
+ label.Content = message;
45
+ console.log(message);
46
+ });
47
+
48
+ stackPanel.Children.Add(button);
49
+
50
+ mainWindow.Content = stackPanel;
51
+
52
+ console.log("Click the button to increase the counter...");
53
+
54
+ const app = new Windows.Application();
55
+ app.Run(mainWindow);
@@ -0,0 +1,84 @@
1
+ // examples/wpf/drag-box/drag-box.ts
2
+ import dotnet from '../../../src/index.ts';
3
+
4
+ dotnet.load('PresentationFramework');
5
+ dotnet.load('PresentationCore');
6
+ dotnet.load('WindowsBase');
7
+
8
+ const System = dotnet.System as any;
9
+ const Windows = System.Windows;
10
+ const Controls = System.Windows.Controls;
11
+ const Media = System.Windows.Media;
12
+ const Input = System.Windows.Input;
13
+
14
+ console.log("--- WPF Draggable Box ---");
15
+
16
+ const mainWindow = new Windows.Window();
17
+ mainWindow.Title = "WPF Draggable Box Example (High Frequency IPC)";
18
+ mainWindow.Width = 800;
19
+ mainWindow.Height = 600;
20
+ mainWindow.WindowStartupLocation = Windows.WindowStartupLocation.CenterScreen;
21
+
22
+ // Create a canvas for absolute positioning
23
+ const canvas = new Controls.Canvas();
24
+ canvas.Background = Media.Brushes.LightGray;
25
+
26
+ // Create the draggable box
27
+ const box = new Controls.Border();
28
+ box.Width = 100;
29
+ box.Height = 100;
30
+ box.Background = Media.Brushes.Red;
31
+ box.BorderBrush = Media.Brushes.DarkRed;
32
+ box.BorderThickness = new Windows.Thickness(2);
33
+
34
+ const transform = new Media.TranslateTransform();
35
+ box.RenderTransform = transform;
36
+
37
+ transform.X = 350;
38
+ transform.Y = 250;
39
+
40
+ canvas.Children.Add(box);
41
+
42
+ // State tracking for drag and drop
43
+ let isDragging = false;
44
+ let startMouseX = 0;
45
+ let startMouseY = 0;
46
+ let startBoxX = 0;
47
+ let startBoxY = 0;
48
+
49
+ box.add_MouseDown((sender: any, e: any) => {
50
+ console.log('[DEBUG] MouseDown');
51
+ isDragging = true;
52
+ const pos = e.GetPosition(canvas);
53
+ startMouseX = pos.X;
54
+ startMouseY = pos.Y;
55
+ startBoxX = transform.X;
56
+ startBoxY = transform.Y;
57
+ box.Background = Media.Brushes.DarkRed;
58
+ box.CaptureMouse();
59
+ });
60
+
61
+ // Mouse up event - stop dragging
62
+ box.add_MouseUp((sender: any, e: any) => {
63
+ console.log('[DEBUG] MouseUp');
64
+ isDragging = false;
65
+ box.Background = Media.Brushes.Red;
66
+ box.ReleaseMouseCapture();
67
+ });
68
+
69
+ // Mouse move event - handle dragging
70
+ box.add_MouseMove((sender: any, e: any) => {
71
+ if (isDragging) {
72
+ const currentPos = e.GetPosition(canvas);
73
+
74
+ transform.X = startBoxX + (currentPos.X - startMouseX);
75
+ transform.Y = startBoxY + (currentPos.Y - startMouseY);
76
+ }
77
+ });
78
+
79
+ mainWindow.Content = canvas;
80
+
81
+ console.log("Initialization complete. Try dragging the red box!");
82
+
83
+ const app = new Windows.Application();
84
+ app.Run(mainWindow);
@@ -0,0 +1,27 @@
1
+ Copyright (C) Microsoft Corporation. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions are
5
+ met:
6
+
7
+ * Redistributions of source code must retain the above copyright
8
+ notice, this list of conditions and the following disclaimer.
9
+ * Redistributions in binary form must reproduce the above
10
+ copyright notice, this list of conditions and the following disclaimer
11
+ in the documentation and/or other materials provided with the
12
+ distribution.
13
+ * The name of Microsoft Corporation, or the names of its contributors
14
+ may not be used to endorse or promote products derived from this
15
+ software without specific prior written permission.
16
+
17
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,31 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <title>Counter</title>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ </head>
8
+ <body>
9
+ <h1>Counter App</h1>
10
+ <p id="display">Clicks: 0</p>
11
+ <button id="btn">Click to Add</button>
12
+
13
+ <script>
14
+ let clickCount = 0;
15
+ const display = document.getElementById('display');
16
+ const button = document.getElementById('btn');
17
+
18
+ button.addEventListener('click', function() {
19
+ clickCount++;
20
+ const message = 'Button clicked ' + clickCount + ' times';
21
+ display.textContent = message;
22
+
23
+ if (window.chrome && window.chrome.webview) {
24
+ window.chrome.webview.postMessage(message);
25
+ } else {
26
+ alert('chrome.webview not available! Click: ' + message);
27
+ }
28
+ });
29
+ </script>
30
+ </body>
31
+ </html>
@@ -0,0 +1,90 @@
1
+ import dotnet from '../../../src/index.ts';
2
+ import * as fs from 'node:fs';
3
+ import * as path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = path.dirname(__filename);
8
+
9
+ const System = dotnet.System as any;
10
+ const Windows = System.Windows;
11
+ const Controls = System.Windows.Controls;
12
+
13
+ const webview2LibPath = path.join(__dirname, 'WebView2Libs');
14
+
15
+ try {
16
+ System.Reflection.Assembly.LoadFrom(path.join(webview2LibPath, 'Microsoft.Web.WebView2.Core.dll'));
17
+ System.Reflection.Assembly.LoadFrom(path.join(webview2LibPath, 'Microsoft.Web.WebView2.Wpf.dll'));
18
+ } catch (e) {
19
+ console.error("Core Dll Load Failed:", e);
20
+ }
21
+
22
+ const WebView2WpfAssembly = System.Reflection.Assembly.LoadFrom(path.join(webview2LibPath, 'Microsoft.Web.WebView2.Wpf.dll'));
23
+
24
+ const USER_DATA_FOLDER = path.join(__dirname, 'WebView2_Data');
25
+ const COUNTER_HTML_PATH = path.join(__dirname, 'counter.html');
26
+
27
+ console.log('--- Initializing WebView2 (Counter App) ---');
28
+
29
+ const WebView2Type = WebView2WpfAssembly.GetType('Microsoft.Web.WebView2.Wpf.WebView2');
30
+ const webView = new WebView2Type();
31
+
32
+ const CreationPropertiesType = WebView2WpfAssembly.GetType('Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties');
33
+ const props = new CreationPropertiesType();
34
+ if (!fs.existsSync(USER_DATA_FOLDER)) fs.mkdirSync(USER_DATA_FOLDER, { recursive: true });
35
+ props.UserDataFolder = USER_DATA_FOLDER;
36
+ props.Language = "zh-CN";
37
+ webView.CreationProperties = props;
38
+
39
+ const browserWindow = new Windows.Window();
40
+ browserWindow.Title = 'Counter App - WebView2';
41
+ browserWindow.Width = 500;
42
+ browserWindow.Height = 400;
43
+ browserWindow.WindowStartupLocation = Windows.WindowStartupLocation.CenterScreen;
44
+
45
+ const grid = new Controls.Grid();
46
+ browserWindow.Content = grid;
47
+ grid.Children.Add(webView);
48
+
49
+ webView.add_CoreWebView2InitializationCompleted((sender: any, e: any) => {
50
+ if (e.IsSuccess) {
51
+ console.log('WebView2 Initialized Successfully');
52
+
53
+ const coreWebView2 = webView.CoreWebView2;
54
+
55
+ coreWebView2.add_WebMessageReceived((sender2: any, e2: any) => {
56
+ const message = e2.TryGetWebMessageAsString();
57
+ if (message) {
58
+ console.log('[WebView2] ' + message);
59
+ }
60
+ });
61
+
62
+ const script = `
63
+ (function() {
64
+ var originalLog = console.log;
65
+ console.log = function(msg) {
66
+ originalLog(msg);
67
+ if (window.chrome && window.chrome.webview) {
68
+ window.chrome.webview.postMessage(msg);
69
+ }
70
+ };
71
+ })();
72
+ `;
73
+ coreWebView2.ExecuteJavaScript(script);
74
+ } else {
75
+ console.error('FAILURE: Init failed', e.InitializationException?.Message);
76
+ }
77
+ });
78
+
79
+ webView.add_NavigationCompleted((sender: any, e: any) => {
80
+ console.log('Page Loaded Successfully');
81
+ });
82
+
83
+ webView.Source = new System.Uri(COUNTER_HTML_PATH);
84
+
85
+ browserWindow.add_Closed((sender: any, e: any) => {
86
+ process.exit(0);
87
+ });
88
+
89
+ const app = new Windows.Application();
90
+ app.Run(browserWindow);
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@devscholar/node-ps1-dotnet",
3
+ "version": "0.0.0",
4
+ "description": "Node.js to .NET interop via IPC",
5
+ "main": "dist/index.js",
6
+ "type": "module",
7
+ "scripts": {
8
+ "test": "echo \"Error: no test specified\" && exit 1",
9
+ "start": "node start.js examples/winforms/counter/counter.ts",
10
+ "build": "tsc"
11
+ },
12
+ "keywords": ["dotnet", "winforms", "interop", "bridge", "ipc"],
13
+ "author": "",
14
+ "license": "ISC",
15
+ "devDependencies": {
16
+ "@types/node": "^25.0.10",
17
+ "typescript": "^5.9.3"
18
+ }
19
+ }
@@ -0,0 +1,39 @@
1
+ // scripts/PsBridge/BridgeState.cs
2
+ using System;
3
+ using System.Collections.Concurrent;
4
+ using System.Collections.Generic;
5
+ using System.IO;
6
+ using System.IO.Pipes;
7
+ using System.Threading;
8
+
9
+ public static class BridgeState
10
+ {
11
+ private static Dictionary<string, object> _objectStore;
12
+ public static Dictionary<string, object> ObjectStore
13
+ {
14
+ get { return _objectStore; }
15
+ }
16
+
17
+ public static StreamReader Reader { get; set; }
18
+ public static StreamWriter Writer { get; set; }
19
+ public static NamedPipeServerStream PipeServer { get; set; }
20
+ public static string PipeName { get; set; }
21
+
22
+ // SynchronizationContext for UI framework dispatching
23
+ public static SynchronizationContext MainSyncContext { get; set; }
24
+
25
+ // Flag to indicate the bridge is closing
26
+ public static bool IsClosing { get; set; }
27
+
28
+ // Command queue for thread-safe communication
29
+ public static BlockingCollection<Dictionary<string, object>> CommandQueue { get; set; }
30
+ public static BlockingCollection<Dictionary<string, object>> ReplyQueue { get; set; }
31
+
32
+ static BridgeState()
33
+ {
34
+ _objectStore = new Dictionary<string, object>();
35
+ CommandQueue = new BlockingCollection<Dictionary<string, object>>();
36
+ ReplyQueue = new BlockingCollection<Dictionary<string, object>>();
37
+ IsClosing = false;
38
+ }
39
+ }