diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/ExecutablesCollector.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/ExecutablesCollector.cs index b4e44ef..706c587 100644 --- a/WelsonJS.Toolkit/WelsonJS.Launcher/ExecutablesCollector.cs +++ b/WelsonJS.Toolkit/WelsonJS.Launcher/ExecutablesCollector.cs @@ -16,6 +16,7 @@ namespace WelsonJS.Launcher { executables.AddRange(GetInstalledSoftwareExecutables()); executables.AddRange(GetExecutablesFromPath()); + executables.AddRange(GetExecutablesFromNetFx()); } public List GetExecutables() @@ -96,11 +97,11 @@ namespace WelsonJS.Launcher private List GetExecutablesFromPath() { List executables = new List(); - string pathEnv = Environment.GetEnvironmentVariable("PATH"); + string[] paths = Environment.GetEnvironmentVariable("PATH")?.Split(';'); - if (!string.IsNullOrEmpty(pathEnv)) + if (paths != null) { - foreach (string path in pathEnv.Split(';')) + foreach (string path in paths) { if (Directory.Exists(path)) { @@ -118,5 +119,38 @@ namespace WelsonJS.Launcher return executables; } + + private List GetExecutablesFromNetFx() + { + List executables = new List(); + + string windir = Environment.GetEnvironmentVariable("WINDIR"); + + if (!string.IsNullOrEmpty(windir)) + { + string[] paths = new string[] + { + Path.Combine(windir, "Microsoft.NET", "Framework"), + Path.Combine(windir, "Microsoft.NET", "Framework64") + }; + + foreach (string path in paths) + { + if (Directory.Exists(path)) + { + try + { + executables.AddRange(Directory.GetFiles(path, "*.exe", SearchOption.AllDirectories)); + } + catch (Exception ex) + { + Debug.WriteLine($"Error enumerating executables in '{path}': {ex}"); + } + } + } + } + + return executables; + } } } diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.Designer.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.Designer.cs index 5a9b55f..c338406 100644 --- a/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.Designer.cs +++ b/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.Designer.cs @@ -45,9 +45,10 @@ this.startCodeEditorToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.notifyIcon1 = new System.Windows.Forms.NotifyIcon(this.components); this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.openLauncherToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.openCodeEditorToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.openLauncherToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.openMicrosoftCopilotToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.menuStrip1.SuspendLayout(); this.contextMenuStrip1.SuspendLayout(); this.SuspendLayout(); @@ -55,10 +56,9 @@ // button1 // this.button1.Image = global::WelsonJS.Launcher.Properties.Resources.icon_zip_128; - this.button1.Location = new System.Drawing.Point(34, 100); - this.button1.Margin = new System.Windows.Forms.Padding(4); + this.button1.Location = new System.Drawing.Point(24, 67); this.button1.Name = "button1"; - this.button1.Size = new System.Drawing.Size(286, 300); + this.button1.Size = new System.Drawing.Size(200, 200); this.button1.TabIndex = 0; this.button1.Text = "From ZIP file..."; this.button1.TextAlign = System.Drawing.ContentAlignment.BottomCenter; @@ -68,10 +68,9 @@ // button2 // this.button2.Image = global::WelsonJS.Launcher.Properties.Resources.icon_link_128; - this.button2.Location = new System.Drawing.Point(329, 100); - this.button2.Margin = new System.Windows.Forms.Padding(4); + this.button2.Location = new System.Drawing.Point(230, 67); this.button2.Name = "button2"; - this.button2.Size = new System.Drawing.Size(286, 300); + this.button2.Size = new System.Drawing.Size(200, 200); this.button2.TabIndex = 1; this.button2.Text = "From external link..."; this.button2.TextAlign = System.Drawing.ContentAlignment.BottomCenter; @@ -81,20 +80,18 @@ // label1 // this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(34, 62); - this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label1.Location = new System.Drawing.Point(24, 41); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(450, 18); + this.label1.Size = new System.Drawing.Size(312, 12); this.label1.TabIndex = 2; this.label1.Text = "Choose the location of WelsonJS application package."; // // linkLabel1 // this.linkLabel1.AutoSize = true; - this.linkLabel1.Location = new System.Drawing.Point(34, 518); - this.linkLabel1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.linkLabel1.Location = new System.Drawing.Point(24, 345); this.linkLabel1.Name = "linkLabel1"; - this.linkLabel1.Size = new System.Drawing.Size(318, 18); + this.linkLabel1.Size = new System.Drawing.Size(219, 12); this.linkLabel1.TabIndex = 3; this.linkLabel1.TabStop = true; this.linkLabel1.Text = "https://github.com/gnh1201/welsonjs"; @@ -103,10 +100,9 @@ // checkBox1 // this.checkBox1.AutoSize = true; - this.checkBox1.Location = new System.Drawing.Point(37, 422); - this.checkBox1.Margin = new System.Windows.Forms.Padding(4); + this.checkBox1.Location = new System.Drawing.Point(26, 281); this.checkBox1.Name = "checkBox1"; - this.checkBox1.Size = new System.Drawing.Size(256, 22); + this.checkBox1.Size = new System.Drawing.Size(184, 16); this.checkBox1.TabIndex = 4; this.checkBox1.Text = "I want to use specific script "; this.checkBox1.UseVisualStyleBackColor = true; @@ -115,19 +111,17 @@ // textBox1 // this.textBox1.Enabled = false; - this.textBox1.Location = new System.Drawing.Point(306, 417); - this.textBox1.Margin = new System.Windows.Forms.Padding(4); + this.textBox1.Location = new System.Drawing.Point(214, 278); this.textBox1.Name = "textBox1"; - this.textBox1.Size = new System.Drawing.Size(155, 28); + this.textBox1.Size = new System.Drawing.Size(110, 21); this.textBox1.TabIndex = 5; // // checkBox2 // this.checkBox2.AutoSize = true; - this.checkBox2.Location = new System.Drawing.Point(37, 458); - this.checkBox2.Margin = new System.Windows.Forms.Padding(4); + this.checkBox2.Location = new System.Drawing.Point(26, 305); this.checkBox2.Name = "checkBox2"; - this.checkBox2.Size = new System.Drawing.Size(352, 22); + this.checkBox2.Size = new System.Drawing.Size(254, 16); this.checkBox2.TabIndex = 6; this.checkBox2.Text = "This is an Interactive Service Application"; this.checkBox2.UseVisualStyleBackColor = true; @@ -138,8 +132,7 @@ this.settingsToolStripMenuItem}); this.menuStrip1.Location = new System.Drawing.Point(0, 0); this.menuStrip1.Name = "menuStrip1"; - this.menuStrip1.Padding = new System.Windows.Forms.Padding(9, 3, 0, 3); - this.menuStrip1.Size = new System.Drawing.Size(659, 25); + this.menuStrip1.Size = new System.Drawing.Size(461, 24); this.menuStrip1.TabIndex = 7; this.menuStrip1.Text = "menuStrip1"; // @@ -150,43 +143,44 @@ this.instancesToolStripMenuItem, this.runAsAdministratorToolStripMenuItem, this.globalSettingsToolStripMenuItem, - this.startCodeEditorToolStripMenuItem}); + this.startCodeEditorToolStripMenuItem, + this.openMicrosoftCopilotToolStripMenuItem}); this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem"; - this.settingsToolStripMenuItem.Size = new System.Drawing.Size(62, 19); + this.settingsToolStripMenuItem.Size = new System.Drawing.Size(62, 20); this.settingsToolStripMenuItem.Text = "Settings"; // // userdefinedVariablesToolStripMenuItem // this.userdefinedVariablesToolStripMenuItem.Name = "userdefinedVariablesToolStripMenuItem"; - this.userdefinedVariablesToolStripMenuItem.Size = new System.Drawing.Size(196, 22); + this.userdefinedVariablesToolStripMenuItem.Size = new System.Drawing.Size(210, 22); this.userdefinedVariablesToolStripMenuItem.Text = "User-defined variables"; this.userdefinedVariablesToolStripMenuItem.Click += new System.EventHandler(this.userdefinedVariablesToolStripMenuItem_Click); // // instancesToolStripMenuItem // this.instancesToolStripMenuItem.Name = "instancesToolStripMenuItem"; - this.instancesToolStripMenuItem.Size = new System.Drawing.Size(196, 22); + this.instancesToolStripMenuItem.Size = new System.Drawing.Size(210, 22); this.instancesToolStripMenuItem.Text = "Instances"; this.instancesToolStripMenuItem.Click += new System.EventHandler(this.instancesToolStripMenuItem_Click); // // runAsAdministratorToolStripMenuItem // this.runAsAdministratorToolStripMenuItem.Name = "runAsAdministratorToolStripMenuItem"; - this.runAsAdministratorToolStripMenuItem.Size = new System.Drawing.Size(196, 22); + this.runAsAdministratorToolStripMenuItem.Size = new System.Drawing.Size(210, 22); this.runAsAdministratorToolStripMenuItem.Text = "Run as Administrator..."; this.runAsAdministratorToolStripMenuItem.Click += new System.EventHandler(this.runAsAdministratorToolStripMenuItem_Click); // // globalSettingsToolStripMenuItem // this.globalSettingsToolStripMenuItem.Name = "globalSettingsToolStripMenuItem"; - this.globalSettingsToolStripMenuItem.Size = new System.Drawing.Size(196, 22); + this.globalSettingsToolStripMenuItem.Size = new System.Drawing.Size(210, 22); this.globalSettingsToolStripMenuItem.Text = "Global settings..."; this.globalSettingsToolStripMenuItem.Click += new System.EventHandler(this.globalSettingsToolStripMenuItem_Click); // // startCodeEditorToolStripMenuItem // this.startCodeEditorToolStripMenuItem.Name = "startCodeEditorToolStripMenuItem"; - this.startCodeEditorToolStripMenuItem.Size = new System.Drawing.Size(196, 22); + this.startCodeEditorToolStripMenuItem.Size = new System.Drawing.Size(210, 22); this.startCodeEditorToolStripMenuItem.Text = "Start the code editor..."; this.startCodeEditorToolStripMenuItem.Click += new System.EventHandler(this.startCodeEditorToolStripMenuItem_Click); // @@ -203,7 +197,13 @@ this.openCodeEditorToolStripMenuItem, this.exitToolStripMenuItem}); this.contextMenuStrip1.Name = "contextMenuStrip1"; - this.contextMenuStrip1.Size = new System.Drawing.Size(199, 92); + this.contextMenuStrip1.Size = new System.Drawing.Size(199, 70); + // + // openLauncherToolStripMenuItem + // + this.openLauncherToolStripMenuItem.Name = "openLauncherToolStripMenuItem"; + this.openLauncherToolStripMenuItem.Size = new System.Drawing.Size(198, 22); + this.openLauncherToolStripMenuItem.Text = "Open the launcher..."; // // openCodeEditorToolStripMenuItem // @@ -218,17 +218,18 @@ this.exitToolStripMenuItem.Size = new System.Drawing.Size(198, 22); this.exitToolStripMenuItem.Text = "Exit"; // - // openLauncherToolStripMenuItem + // openMicrosoftCopilotToolStripMenuItem // - this.openLauncherToolStripMenuItem.Name = "openLauncherToolStripMenuItem"; - this.openLauncherToolStripMenuItem.Size = new System.Drawing.Size(198, 22); - this.openLauncherToolStripMenuItem.Text = "Open the launcher..."; + this.openMicrosoftCopilotToolStripMenuItem.Name = "openMicrosoftCopilotToolStripMenuItem"; + this.openMicrosoftCopilotToolStripMenuItem.Size = new System.Drawing.Size(210, 22); + this.openMicrosoftCopilotToolStripMenuItem.Text = "Open Microsoft Copilot..."; + this.openMicrosoftCopilotToolStripMenuItem.Click += new System.EventHandler(this.openMicrosoftCopilotToolStripMenuItem_Click); // // MainForm // - this.AutoScaleDimensions = new System.Drawing.SizeF(10F, 18F); + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(659, 573); + this.ClientSize = new System.Drawing.Size(461, 382); this.Controls.Add(this.checkBox2); this.Controls.Add(this.textBox1); this.Controls.Add(this.checkBox1); @@ -240,7 +241,6 @@ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.Icon = global::WelsonJS.Launcher.Properties.Resources.favicon; this.MainMenuStrip = this.menuStrip1; - this.Margin = new System.Windows.Forms.Padding(4); this.MaximizeBox = false; this.Name = "MainForm"; this.Text = "WelsonJS Application Launcher"; @@ -273,6 +273,7 @@ private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem openCodeEditorToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem openLauncherToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem openMicrosoftCopilotToolStripMenuItem; } } diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs index 18d17c1..0f713b2 100644 --- a/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs +++ b/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs @@ -270,5 +270,10 @@ namespace WelsonJS.Launcher Process.Start(Program.resourceServer.GetPrefix()); } } + + private void openMicrosoftCopilotToolStripMenuItem_Click(object sender, EventArgs e) + { + Program.OpenWebBrowser("https://copilot.microsoft.com/"); + } } } diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs index 6660b72..f063773 100644 --- a/WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs +++ b/WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs @@ -124,5 +124,22 @@ namespace WelsonJS.Launcher return workingDirectory; } + + public static void OpenWebBrowser(string url) + { + string userDataDir = Path.Combine(GetAppDataPath(), "EdgeUserProfile"); + string[] arguments = { + $"\"{url}\"", + "--remote-debugging-port=9222", + $"--user-data-dir=\"{userDataDir}\"" + }; + + Process.Start(new ProcessStartInfo + { + FileName = "msedge.exe", + Arguments = string.Join(" ", arguments), + UseShellExecute = true + }); + } } } diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceServer.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceServer.cs index f93f707..26f3884 100644 --- a/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceServer.cs +++ b/WelsonJS.Toolkit/WelsonJS.Launcher/ResourceServer.cs @@ -1,14 +1,15 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; using System.Net; +using System.Net.Http; using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; +using System.Xml; using System.Xml.Linq; namespace WelsonJS.Launcher @@ -46,7 +47,7 @@ namespace WelsonJS.Launcher _listener.Start(); // Open the web browser - Process.Start(_prefix); + Program.OpenWebBrowser(_prefix); // Run a task with cancellation token _serverTask = Task.Run(() => ListenLoop(_cts.Token)); @@ -94,9 +95,18 @@ namespace WelsonJS.Launcher } // Serve the code completion (word suggestion) - if (path.StartsWith("completion/", StringComparison.OrdinalIgnoreCase)) + const string completionPrefix = "completion/"; + if (path.StartsWith(completionPrefix, StringComparison.OrdinalIgnoreCase)) { - ServeCompletion(context, path.Substring("completion/".Length)); + ServeCompletion(context, path.Substring(completionPrefix.Length)); + return; + } + + // Serve the DevTools Protocol + const string devtoolsPrefix = "devtools/"; + if (path.StartsWith(devtoolsPrefix, StringComparison.OrdinalIgnoreCase)) + { + ServeDevTools(context, path.Substring(devtoolsPrefix.Length - 1)); return; } @@ -106,8 +116,6 @@ namespace WelsonJS.Launcher private void ServeCompletion(HttpListenerContext context, string word) { - int statusCode = 200; - try { List executables = _executablesCollector.GetExecutables(); @@ -133,44 +141,39 @@ namespace WelsonJS.Launcher )) ); - byte[] data = Encoding.UTF8.GetBytes( - "\r\n" + - response.ToString() - ); + ServeResource(context, response.ToString(), "application/xml"); + } + catch (Exception ex) + { + ServeResource(context, $"Failed to process completion request. {ex.Message}", "application/xml", 500); + } + } - context.Response.StatusCode = statusCode; - context.Response.ContentType = "application/xml"; - context.Response.ContentLength64 = data.Length; - using (Stream outputStream = context.Response.OutputStream) + private void ServeDevTools(HttpListenerContext context, string endpoint) + { + try + { + using (HttpClient client = new HttpClient()) { - outputStream.Write(data, 0, data.Length); + string url = "http://localhost:9222" + endpoint; + string data = client.GetStringAsync(url).GetAwaiter().GetResult(); + + ServeResource(context, data, "application/json"); } } catch (Exception ex) { - byte[] errorData = Encoding.UTF8.GetBytes( - "\r\n" + - $"Failed to process completion request. {ex.Message}" - ); - context.Response.StatusCode = 500; - context.Response.ContentType = "application/xml"; - context.Response.ContentLength64 = errorData.Length; - using (Stream outputStream = context.Response.OutputStream) - { - outputStream.Write(errorData, 0, errorData.Length); - } + ServeResource(context, $"Failed to process DevTools request. {ex.Message}", "application/xml", 500); } } - private void ServeResource(HttpListenerContext context, byte[] data, string mimeType = "text/html") + private void ServeResource(HttpListenerContext context, byte[] data, string mimeType = "text/html", int statusCode = 200) { - int statusCode = 200; + string xmlHeader = ""; if (data == null) { - data = "text/html".Equals(mimeType, StringComparison.OrdinalIgnoreCase) ? - Encoding.UTF8.GetBytes("

Could not find the resource.

") : - Encoding.UTF8.GetBytes("Could not find the resource.") - ; + data = Encoding.UTF8.GetBytes(xmlHeader + "\r\nCould not find the resource."); + mimeType = "application/xml"; statusCode = 404; } @@ -183,6 +186,24 @@ namespace WelsonJS.Launcher } } + private void ServeResource(HttpListenerContext context, string data, string mimeType = "text/html", int statusCode = 200) + { + string xmlHeader = ""; + + if (data == null) + { + data = xmlHeader + "\r\nCould not find the resource."; + mimeType = "application/xml"; + statusCode = 404; + } + else if (mimeType == "application/xml" && !data.StartsWith("True True +