Repository: gnh1201/welsonjs
Pull request #213: Adapt a code review, SRI, CORS, etc.
Author: login: gnh1201
Created: 2025-03-31T05:28:34Z | Merged: 2025-03-31T08:41:06Z

Adapt a code review, SRI, CORS, etc.

## Summary by Sourcery

Refactor and improve the WelsonJS Launcher application with various UI, code quality, and security enhancements

Bug Fixes:
- Fixed potential null reference and parsing issues in various methods
- Improved error handling in file and registry operations

Enhancements:
- Renamed control variables to more descriptive names for better code readability
- Improved resource management by using 'using' statements
- Added safe invocation method for cross-thread UI updates
- Integrated configuration settings from app configuration

Documentation:
- Updated HTML editor to use SRI (Subresource Integrity) for external resources
- Replaced hardcoded URLs with configurable settings

Chores:
- Standardized naming conventions across forms
- Simplified and cleaned up code structure

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Introduced a ZIP file selection interface for streamlined package handling.
  - Updated external link functionality now displays a “coming soon” message.
  - Added new properties for Copilot URL, Repository URL, and Resource Server Prefix to enhance resource management.

- **Refactor**
  - Redesigned several forms for a more compact and intuitive user experience.
  - Renamed and restructured UI controls for enhanced clarity and consistency.
  - Upgraded resource links and configuration settings to improve security, performance, and startup simplicity.
  - Simplified the toolkit access by removing the SAS token from the URL.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/EnvForm.Designer.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/EnvForm.Designer.cs
index 8d27986e..c8d4aaad 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/EnvForm.Designer.cs
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/EnvForm.Designer.cs
@@ -28,11 +28,11 @@ protected override void Dispose(bool disposing)
         /// </summary>
         private void InitializeComponent()
         {
-            this.groupBox1 = new System.Windows.Forms.GroupBox();
-            this.listView1 = new System.Windows.Forms.ListView();
+            this.gbUserDefinedVariables = new System.Windows.Forms.GroupBox();
+            this.lvUserDefinedVariables = new System.Windows.Forms.ListView();
             this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
             this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
-            this.groupBox2 = new System.Windows.Forms.GroupBox();
+            this.gbUpdateUserDefinedVariable = new System.Windows.Forms.GroupBox();
             this.checkDeleteVariable = new System.Windows.Forms.CheckBox();
             this.btnOk = new System.Windows.Forms.Button();
             this.btnOpenFile = new System.Windows.Forms.Button();
@@ -41,39 +41,36 @@ private void InitializeComponent()
             this.textSetName = new System.Windows.Forms.TextBox();
             this.labelSetValue = new System.Windows.Forms.Label();
             this.labelSetName = new System.Windows.Forms.Label();
-            this.groupBox3 = new System.Windows.Forms.GroupBox();
+            this.gbImportAndExport = new System.Windows.Forms.GroupBox();
             this.btnExport = new System.Windows.Forms.Button();
             this.btnImport = new System.Windows.Forms.Button();
-            this.groupBox1.SuspendLayout();
-            this.groupBox2.SuspendLayout();
-            this.groupBox3.SuspendLayout();
+            this.gbUserDefinedVariables.SuspendLayout();
+            this.gbUpdateUserDefinedVariable.SuspendLayout();
+            this.gbImportAndExport.SuspendLayout();
             this.SuspendLayout();
             // 
-            // groupBox1
+            // gbUserDefinedVariables
             // 
-            this.groupBox1.Controls.Add(this.listView1);
-            this.groupBox1.Location = new System.Drawing.Point(17, 18);
-            this.groupBox1.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
-            this.groupBox1.Name = "groupBox1";
-            this.groupBox1.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4);
-            this.groupBox1.Size = new System.Drawing.Size(599, 255);
-            this.groupBox1.TabIndex = 0;
-            this.groupBox1.TabStop = false;
-            this.groupBox1.Text = "User-defined variables";
+            this.gbUserDefinedVariables.Controls.Add(this.lvUserDefinedVariables);
+            this.gbUserDefinedVariables.Location = new System.Drawing.Point(12, 12);
+            this.gbUserDefinedVariables.Name = "gbUserDefinedVariables";
+            this.gbUserDefinedVariables.Size = new System.Drawing.Size(419, 170);
+            this.gbUserDefinedVariables.TabIndex = 0;
+            this.gbUserDefinedVariables.TabStop = false;
+            this.gbUserDefinedVariables.Text = "User-defined variables";
             // 
-            // listView1
+            // lvUserDefinedVariables
             // 
-            this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+            this.lvUserDefinedVariables.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
             this.columnHeader1,
             this.columnHeader2});
-            this.listView1.HideSelection = false;
-            this.listView1.Location = new System.Drawing.Point(23, 39);
-            this.listView1.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
-            this.listView1.Name = "listView1";
-            this.listView1.Size = new System.Drawing.Size(550, 192);
-            this.listView1.TabIndex = 0;
-            this.listView1.UseCompatibleStateImageBehavior = false;
-            this.listView1.SelectedIndexChanged += new System.EventHandler(this.ListView1_SelectedIndexChanged);
+            this.lvUserDefinedVariables.HideSelection = false;
+            this.lvUserDefinedVariables.Location = new System.Drawing.Point(16, 26);
+            this.lvUserDefinedVariables.Name = "lvUserDefinedVariables";
+            this.lvUserDefinedVariables.Size = new System.Drawing.Size(386, 129);
+            this.lvUserDefinedVariables.TabIndex = 0;
+            this.lvUserDefinedVariables.UseCompatibleStateImageBehavior = false;
+            this.lvUserDefinedVariables.SelectedIndexChanged += new System.EventHandler(this.lvUserDefinedVariables_SelectedIndexChanged);
             // 
             // columnHeader1
             // 
@@ -83,32 +80,29 @@ private void InitializeComponent()
             // 
             this.columnHeader2.Text = "Value";
             // 
-            // groupBox2
-            // 
-            this.groupBox2.Controls.Add(this.checkDeleteVariable);
-            this.groupBox2.Controls.Add(this.btnOk);
-            this.groupBox2.Controls.Add(this.btnOpenFile);
-            this.groupBox2.Controls.Add(this.btnOpenDirectory);
-            this.groupBox2.Controls.Add(this.textSetValue);
-            this.groupBox2.Controls.Add(this.textSetName);
-            this.groupBox2.Controls.Add(this.labelSetValue);
-            this.groupBox2.Controls.Add(this.labelSetName);
-            this.groupBox2.Location = new System.Drawing.Point(17, 282);
-            this.groupBox2.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
-            this.groupBox2.Name = "groupBox2";
-            this.groupBox2.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4);
-            this.groupBox2.Size = new System.Drawing.Size(599, 344);
-            this.groupBox2.TabIndex = 1;
-            this.groupBox2.TabStop = false;
-            this.groupBox2.Text = "Update the user-defined variable";
+            // gbUpdateUserDefinedVariable
+            // 
+            this.gbUpdateUserDefinedVariable.Controls.Add(this.checkDeleteVariable);
+            this.gbUpdateUserDefinedVariable.Controls.Add(this.btnOk);
+            this.gbUpdateUserDefinedVariable.Controls.Add(this.btnOpenFile);
+            this.gbUpdateUserDefinedVariable.Controls.Add(this.btnOpenDirectory);
+            this.gbUpdateUserDefinedVariable.Controls.Add(this.textSetValue);
+            this.gbUpdateUserDefinedVariable.Controls.Add(this.textSetName);
+            this.gbUpdateUserDefinedVariable.Controls.Add(this.labelSetValue);
+            this.gbUpdateUserDefinedVariable.Controls.Add(this.labelSetName);
+            this.gbUpdateUserDefinedVariable.Location = new System.Drawing.Point(12, 188);
+            this.gbUpdateUserDefinedVariable.Name = "gbUpdateUserDefinedVariable";
+            this.gbUpdateUserDefinedVariable.Size = new System.Drawing.Size(419, 229);
+            this.gbUpdateUserDefinedVariable.TabIndex = 1;
+            this.gbUpdateUserDefinedVariable.TabStop = false;
+            this.gbUpdateUserDefinedVariable.Text = "Update the user-defined variable";
             // 
             // checkDeleteVariable
             // 
             this.checkDeleteVariable.AutoSize = true;
-            this.checkDeleteVariable.Location = new System.Drawing.Point(44, 132);
-            this.checkDeleteVariable.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+            this.checkDeleteVariable.Location = new System.Drawing.Point(31, 88);
             this.checkDeleteVariable.Name = "checkDeleteVariable";
-            this.checkDeleteVariable.Size = new System.Drawing.Size(178, 22);
+            this.checkDeleteVariable.Size = new System.Drawing.Size(131, 16);
             this.checkDeleteVariable.TabIndex = 7;
             this.checkDeleteVariable.Text = "Delete this variable";
             this.checkDeleteVariable.UseVisualStyleBackColor = true;
@@ -116,10 +110,9 @@ private void InitializeComponent()
             // btnOk
             // 
             this.btnOk.Image = global::WelsonJS.Launcher.Properties.Resources.icon_check_32;
-            this.btnOk.Location = new System.Drawing.Point(433, 184);
-            this.btnOk.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+            this.btnOk.Location = new System.Drawing.Point(303, 123);
             this.btnOk.Name = "btnOk";
-            this.btnOk.Size = new System.Drawing.Size(123, 129);
+            this.btnOk.Size = new System.Drawing.Size(86, 86);
             this.btnOk.TabIndex = 6;
             this.btnOk.Text = "Ok";
             this.btnOk.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
@@ -130,11 +123,10 @@ private void InitializeComponent()
             // 
             this.btnOpenFile.Image = global::WelsonJS.Launcher.Properties.Resources.icon_file_32;
             this.btnOpenFile.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
-            this.btnOpenFile.Location = new System.Drawing.Point(44, 254);
-            this.btnOpenFile.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+            this.btnOpenFile.Location = new System.Drawing.Point(31, 169);
             this.btnOpenFile.Name = "btnOpenFile";
-            this.btnOpenFile.Padding = new System.Windows.Forms.Padding(16, 0, 0, 0);
-            this.btnOpenFile.Size = new System.Drawing.Size(287, 60);
+            this.btnOpenFile.Padding = new System.Windows.Forms.Padding(11, 0, 0, 0);
+            this.btnOpenFile.Size = new System.Drawing.Size(201, 40);
             this.btnOpenFile.TabIndex = 5;
             this.btnOpenFile.Text = "Open the file...";
             this.btnOpenFile.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
@@ -146,11 +138,10 @@ private void InitializeComponent()
             // 
             this.btnOpenDirectory.Image = global::WelsonJS.Launcher.Properties.Resources.icon_directory_32;
             this.btnOpenDirectory.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
-            this.btnOpenDirectory.Location = new System.Drawing.Point(44, 184);
-            this.btnOpenDirectory.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+            this.btnOpenDirectory.Location = new System.Drawing.Point(31, 123);
             this.btnOpenDirectory.Name = "btnOpenDirectory";
-            this.btnOpenDirectory.Padding = new System.Windows.Forms.Padding(16, 0, 0, 0);
-            this.btnOpenDirectory.Size = new System.Drawing.Size(287, 60);
+            this.btnOpenDirectory.Padding = new System.Windows.Forms.Padding(11, 0, 0, 0);
+            this.btnOpenDirectory.Size = new System.Drawing.Size(201, 40);
             this.btnOpenDirectory.TabIndex = 4;
             this.btnOpenDirectory.Text = "Open the directory...";
             this.btnOpenDirectory.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
@@ -160,62 +151,55 @@ private void InitializeComponent()
             // 
             // textSetValue
             // 
-            this.textSetValue.Location = new System.Drawing.Point(140, 82);
-            this.textSetValue.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+            this.textSetValue.Location = new System.Drawing.Point(98, 55);
             this.textSetValue.Name = "textSetValue";
-            this.textSetValue.Size = new System.Drawing.Size(414, 28);
+            this.textSetValue.Size = new System.Drawing.Size(291, 21);
             this.textSetValue.TabIndex = 3;
             // 
             // textSetName
             // 
-            this.textSetName.Location = new System.Drawing.Point(140, 42);
-            this.textSetName.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+            this.textSetName.Location = new System.Drawing.Point(98, 28);
             this.textSetName.Name = "textSetName";
-            this.textSetName.Size = new System.Drawing.Size(414, 28);
+            this.textSetName.Size = new System.Drawing.Size(291, 21);
             this.textSetName.TabIndex = 2;
             // 
             // labelSetValue
             // 
             this.labelSetValue.AutoSize = true;
-            this.labelSetValue.Location = new System.Drawing.Point(41, 88);
-            this.labelSetValue.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+            this.labelSetValue.Location = new System.Drawing.Point(29, 59);
             this.labelSetValue.Name = "labelSetValue";
-            this.labelSetValue.Size = new System.Drawing.Size(89, 18);
+            this.labelSetValue.Size = new System.Drawing.Size(61, 12);
             this.labelSetValue.TabIndex = 1;
             this.labelSetValue.Text = "Set value:";
             // 
             // labelSetName
             // 
             this.labelSetName.AutoSize = true;
-            this.labelSetName.Location = new System.Drawing.Point(41, 46);
-            this.labelSetName.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+            this.labelSetName.Location = new System.Drawing.Point(29, 31);
             this.labelSetName.Name = "labelSetName";
-            this.labelSetName.Size = new System.Drawing.Size(91, 18);
+            this.labelSetName.Size = new System.Drawing.Size(63, 12);
             this.labelSetName.TabIndex = 0;
             this.labelSetName.Text = "Set name:";
             // 
-            // groupBox3
+            // gbImportAndExport
             // 
-            this.groupBox3.Controls.Add(this.btnExport);
-            this.groupBox3.Controls.Add(this.btnImport);
-            this.groupBox3.Location = new System.Drawing.Point(17, 634);
-            this.groupBox3.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
-            this.groupBox3.Name = "groupBox3";
-            this.groupBox3.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4);
-            this.groupBox3.Size = new System.Drawing.Size(599, 134);
-            this.groupBox3.TabIndex = 2;
-            this.groupBox3.TabStop = false;
-            this.groupBox3.Text = "Import and export";
+            this.gbImportAndExport.Controls.Add(this.btnExport);
+            this.gbImportAndExport.Controls.Add(this.btnImport);
+            this.gbImportAndExport.Location = new System.Drawing.Point(12, 423);
+            this.gbImportAndExport.Name = "gbImportAndExport";
+            this.gbImportAndExport.Size = new System.Drawing.Size(419, 89);
+            this.gbImportAndExport.TabIndex = 2;
+            this.gbImportAndExport.TabStop = false;
+            this.gbImportAndExport.Text = "Import and export";
             // 
             // btnExport
             // 
             this.btnExport.Image = global::WelsonJS.Launcher.Properties.Resources.icon_export_32;
             this.btnExport.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
-            this.btnExport.Location = new System.Drawing.Point(304, 44);
-            this.btnExport.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+            this.btnExport.Location = new System.Drawing.Point(213, 29);
             this.btnExport.Name = "btnExport";
-            this.btnExport.Padding = new System.Windows.Forms.Padding(16, 0, 0, 0);
-            this.btnExport.Size = new System.Drawing.Size(251, 60);
+            this.btnExport.Padding = new System.Windows.Forms.Padding(11, 0, 0, 0);
+            this.btnExport.Size = new System.Drawing.Size(176, 40);
             this.btnExport.TabIndex = 6;
             this.btnExport.Text = "Export";
             this.btnExport.UseVisualStyleBackColor = true;
@@ -225,11 +209,10 @@ private void InitializeComponent()
             // 
             this.btnImport.Image = global::WelsonJS.Launcher.Properties.Resources.icon_import_32;
             this.btnImport.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
-            this.btnImport.Location = new System.Drawing.Point(44, 44);
-            this.btnImport.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+            this.btnImport.Location = new System.Drawing.Point(31, 29);
             this.btnImport.Name = "btnImport";
-            this.btnImport.Padding = new System.Windows.Forms.Padding(16, 0, 0, 0);
-            this.btnImport.Size = new System.Drawing.Size(251, 60);
+            this.btnImport.Padding = new System.Windows.Forms.Padding(11, 0, 0, 0);
+            this.btnImport.Size = new System.Drawing.Size(176, 40);
             this.btnImport.TabIndex = 5;
             this.btnImport.Text = "Import";
             this.btnImport.UseVisualStyleBackColor = true;
@@ -237,30 +220,29 @@ private void InitializeComponent()
             // 
             // EnvForm
             // 
-            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(639, 794);
-            this.Controls.Add(this.groupBox3);
-            this.Controls.Add(this.groupBox2);
-            this.Controls.Add(this.groupBox1);
+            this.ClientSize = new System.Drawing.Size(447, 529);
+            this.Controls.Add(this.gbImportAndExport);
+            this.Controls.Add(this.gbUpdateUserDefinedVariable);
+            this.Controls.Add(this.gbUserDefinedVariables);
             this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
             this.Icon = global::WelsonJS.Launcher.Properties.Resources.favicon;
-            this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
             this.MaximizeBox = false;
             this.Name = "EnvForm";
             this.Text = "User-defined variables editor";
-            this.groupBox1.ResumeLayout(false);
-            this.groupBox2.ResumeLayout(false);
-            this.groupBox2.PerformLayout();
-            this.groupBox3.ResumeLayout(false);
+            this.gbUserDefinedVariables.ResumeLayout(false);
+            this.gbUpdateUserDefinedVariable.ResumeLayout(false);
+            this.gbUpdateUserDefinedVariable.PerformLayout();
+            this.gbImportAndExport.ResumeLayout(false);
             this.ResumeLayout(false);
 
         }
 
         #endregion
 
-        private System.Windows.Forms.GroupBox groupBox1;
-        private System.Windows.Forms.GroupBox groupBox2;
+        private System.Windows.Forms.GroupBox gbUserDefinedVariables;
+        private System.Windows.Forms.GroupBox gbUpdateUserDefinedVariable;
         private System.Windows.Forms.TextBox textSetValue;
         private System.Windows.Forms.TextBox textSetName;
         private System.Windows.Forms.Label labelSetValue;
@@ -269,10 +251,10 @@ private void InitializeComponent()
         private System.Windows.Forms.Button btnOpenFile;
         private System.Windows.Forms.Button btnOpenDirectory;
         private System.Windows.Forms.CheckBox checkDeleteVariable;
-        private System.Windows.Forms.ListView listView1;
+        private System.Windows.Forms.ListView lvUserDefinedVariables;
         private System.Windows.Forms.ColumnHeader columnHeader1;
         private System.Windows.Forms.ColumnHeader columnHeader2;
-        private System.Windows.Forms.GroupBox groupBox3;
+        private System.Windows.Forms.GroupBox gbImportAndExport;
         private System.Windows.Forms.Button btnImport;
         private System.Windows.Forms.Button btnExport;
     }
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/EnvForm.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/EnvForm.cs
index d2da27c0..6802a970 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/EnvForm.cs
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/EnvForm.cs
@@ -1,6 +1,7 @@
 ﻿using System;
 using System.Collections.Generic;
 using System.IO;
+using System.Text;
 using System.Windows.Forms;
 
 namespace WelsonJS.Launcher
@@ -9,6 +10,7 @@ public partial class EnvForm : Form
     {
         private Dictionary<string, string> userVariables = new Dictionary<string, string>();
         private string tempFilePath;
+        private readonly Encoding defaultEncoding = Encoding.UTF8;
 
         public EnvForm()
         {
@@ -24,11 +26,11 @@ public EnvForm()
         // Initialize ListView
         private void InitializeListView()
         {
-            listView1.View = View.Details;
-            listView1.FullRowSelect = true;
-            listView1.Columns[0].Width = 150;
-            listView1.Columns[1].Width = 220;
-            listView1.SelectedIndexChanged += ListView1_SelectedIndexChanged;
+            lvUserDefinedVariables.View = View.Details;
+            lvUserDefinedVariables.FullRowSelect = true;
+            lvUserDefinedVariables.Columns[0].Width = 150;
+            lvUserDefinedVariables.Columns[1].Width = 220;
+            lvUserDefinedVariables.SelectedIndexChanged += lvUserDefinedVariables_SelectedIndexChanged;
         }
 
         // Load user-defined variables from the temporary folder in .env format
@@ -86,21 +88,21 @@ private void LoadUserVariables()
         // Update ListView with current variables
         private void UpdateListView()
         {
-            listView1.Items.Clear();
+            lvUserDefinedVariables.Items.Clear();
             foreach (var variable in userVariables)
             {
                 var item = new ListViewItem(variable.Key);
                 item.SubItems.Add(variable.Value);
-                listView1.Items.Add(item);
+                lvUserDefinedVariables.Items.Add(item);
             }
         }
 
         // Handle ListView selection change
-        private void ListView1_SelectedIndexChanged(object sender, EventArgs e)
+        private void lvUserDefinedVariables_SelectedIndexChanged(object sender, EventArgs e)
         {
-            if (listView1.SelectedItems.Count > 0)
+            if (lvUserDefinedVariables.SelectedItems.Count > 0)
             {
-                var selectedItem = listView1.SelectedItems[0];
+                var selectedItem = lvUserDefinedVariables.SelectedItems[0];
                 textSetName.Text = selectedItem.Text;
                 textSetValue.Text = selectedItem.SubItems[1].Text;
                 checkDeleteVariable.Checked = false;
@@ -166,7 +168,7 @@ private void SaveUserVariables()
                 }
 
                 // Write lines to the file
-                File.WriteAllLines(tempFilePath, lines);
+                File.WriteAllLines(tempFilePath, lines, defaultEncoding);
             }
             catch (Exception ex)
             {
@@ -185,68 +187,74 @@ private void ClearInputFields()
         // Handle "Open Directory" button click
         private void btnOpenDirectory_Click(object sender, EventArgs e)
         {
-            var folderDialog = new FolderBrowserDialog();
-            if (folderDialog.ShowDialog() == DialogResult.OK)
+            using (var folderDialog = new FolderBrowserDialog())
             {
-                textSetValue.Text = folderDialog.SelectedPath;
+                if (folderDialog.ShowDialog() == DialogResult.OK)
+                {
+                    textSetValue.Text = folderDialog.SelectedPath;
+                }
             }
         }
 
         // Handle "Open File" button click
         private void btnOpenFile_Click(object sender, EventArgs e)
         {
-            var fileDialog = new OpenFileDialog();
-            if (fileDialog.ShowDialog() == DialogResult.OK)
+            using (var fileDialog = new OpenFileDialog())
             {
-                textSetName.Text = Path.GetFileName(fileDialog.FileName);
-                textSetValue.Text = fileDialog.FileName;
+                if (fileDialog.ShowDialog() == DialogResult.OK)
+                {
+                    textSetName.Text = Path.GetFileName(fileDialog.FileName);
+                    textSetValue.Text = fileDialog.FileName;
+                }
             }
         }
 
         private void btnImport_Click(object sender, EventArgs e)
         {
-            OpenFileDialog openFileDialog = new OpenFileDialog();
-            openFileDialog.Filter = "Env files (*.env)|*.env|All files (*.*)|*.*";
-            if (openFileDialog.ShowDialog() == DialogResult.OK)
+            using (var openFileDialog = new OpenFileDialog())
             {
-                try
+                openFileDialog.Filter = "Env files (*.env)|*.env|All files (*.*)|*.*";
+                if (openFileDialog.ShowDialog() == DialogResult.OK)
                 {
-                    // Load variables from the selected file
-                    string filePath = openFileDialog.FileName;
-                    string[] lines = File.ReadAllLines(filePath);
-
-                    foreach (string line in lines)
+                    try
                     {
-                        // Skip empty lines
-                        if (string.IsNullOrWhiteSpace(line)) continue;
+                        // Load variables from the selected file
+                        string filePath = openFileDialog.FileName;
+                        string[] lines = File.ReadAllLines(filePath, defaultEncoding);
 
-                        int indexOfEquals = line.IndexOf('=');
-                        if (indexOfEquals != -1)
+                        foreach (string line in lines)
                         {
-                            string key = line.Substring(0, indexOfEquals).Trim();
-                            string value = line.Substring(indexOfEquals + 1).Trim();
+                            // Skip empty lines
+                            if (string.IsNullOrWhiteSpace(line)) continue;
 
-                            // Remove surrounding quotes if present
-                            if (value.StartsWith("\"") && value.EndsWith("\""))
+                            int indexOfEquals = line.IndexOf('=');
+                            if (indexOfEquals != -1)
                             {
-                                value = value.Substring(1, value.Length - 2);
-                            }
+                                string key = line.Substring(0, indexOfEquals).Trim();
+                                string value = line.Substring(indexOfEquals + 1).Trim();
 
-                            // Unescape double quotes in the value
-                            value = value.Replace("\\\"", "\"");
+                                // Remove surrounding quotes if present
+                                if (value.StartsWith("\"") && value.EndsWith("\""))
+                                {
+                                    value = value.Substring(1, value.Length - 2);
+                                }
 
-                            // Update or add the key-value pair
-                            userVariables[key] = value;
+                                // Unescape double quotes in the value
+                                value = value.Replace("\\\"", "\"");
+
+                                // Update or add the key-value pair
+                                userVariables[key] = value;
+                            }
                         }
-                    }
 
-                    // Save the updated variables to the file
-                    SaveUserVariables();
-                    UpdateListView(); // Refresh the display
-                }
-                catch (Exception ex)
-                {
-                    MessageBox.Show($"Error importing variable file: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+                        // Save the updated variables to the file
+                        SaveUserVariables();
+                        UpdateListView(); // Refresh the display
+                    }
+                    catch (Exception ex)
+                    {
+                        MessageBox.Show($"Error importing variable file: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+                    }
                 }
             }
         }
@@ -275,7 +283,7 @@ private void btnExport_Click(object sender, EventArgs e)
 
                         lines.Add($"{variable.Key}={value}");
                     }
-                    File.WriteAllLines(filePath, lines);
+                    File.WriteAllLines(filePath, lines, defaultEncoding);
                 }
                 catch (Exception ex)
                 {
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/GlobalSettingsForm.Designer.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/GlobalSettingsForm.Designer.cs
index 80a5d39e..6137efa3 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/GlobalSettingsForm.Designer.cs
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/GlobalSettingsForm.Designer.cs
@@ -28,62 +28,62 @@ protected override void Dispose(bool disposing)
         /// </summary>
         private void InitializeComponent()
         {
-            this.groupBox1 = new System.Windows.Forms.GroupBox();
-            this.button1 = new System.Windows.Forms.Button();
-            this.textBox1 = new System.Windows.Forms.TextBox();
-            this.groupBox1.SuspendLayout();
+            this.gbMaxScriptStatements = new System.Windows.Forms.GroupBox();
+            this.btnOkMaxScriptStatements = new System.Windows.Forms.Button();
+            this.txtMaxScriptStatements = new System.Windows.Forms.TextBox();
+            this.gbMaxScriptStatements.SuspendLayout();
             this.SuspendLayout();
             // 
-            // groupBox1
+            // gbMaxScriptStatements
             // 
-            this.groupBox1.Controls.Add(this.button1);
-            this.groupBox1.Controls.Add(this.textBox1);
-            this.groupBox1.Location = new System.Drawing.Point(12, 12);
-            this.groupBox1.Name = "groupBox1";
-            this.groupBox1.Size = new System.Drawing.Size(290, 67);
-            this.groupBox1.TabIndex = 0;
-            this.groupBox1.TabStop = false;
-            this.groupBox1.Text = "MaxScriptStatements (GUI only)";
+            this.gbMaxScriptStatements.Controls.Add(this.btnOkMaxScriptStatements);
+            this.gbMaxScriptStatements.Controls.Add(this.txtMaxScriptStatements);
+            this.gbMaxScriptStatements.Location = new System.Drawing.Point(12, 12);
+            this.gbMaxScriptStatements.Name = "gbMaxScriptStatements";
+            this.gbMaxScriptStatements.Size = new System.Drawing.Size(290, 67);
+            this.gbMaxScriptStatements.TabIndex = 0;
+            this.gbMaxScriptStatements.TabStop = false;
+            this.gbMaxScriptStatements.Text = "MaxScriptStatements (GUI only)";
             // 
-            // button1
+            // btnOkMaxScriptStatements
             // 
-            this.button1.Location = new System.Drawing.Point(218, 30);
-            this.button1.Name = "button1";
-            this.button1.Size = new System.Drawing.Size(57, 21);
-            this.button1.TabIndex = 1;
-            this.button1.Text = "Ok";
-            this.button1.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
-            this.button1.UseVisualStyleBackColor = true;
-            this.button1.Click += new System.EventHandler(this.button1_Click);
+            this.btnOkMaxScriptStatements.Location = new System.Drawing.Point(218, 30);
+            this.btnOkMaxScriptStatements.Name = "btnOkMaxScriptStatements";
+            this.btnOkMaxScriptStatements.Size = new System.Drawing.Size(57, 21);
+            this.btnOkMaxScriptStatements.TabIndex = 1;
+            this.btnOkMaxScriptStatements.Text = "Ok";
+            this.btnOkMaxScriptStatements.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
+            this.btnOkMaxScriptStatements.UseVisualStyleBackColor = true;
+            this.btnOkMaxScriptStatements.Click += new System.EventHandler(this.btnOkMaxScriptStatements_Click);
             // 
-            // textBox1
+            // txtMaxScriptStatements
             // 
-            this.textBox1.Location = new System.Drawing.Point(15, 30);
-            this.textBox1.Name = "textBox1";
-            this.textBox1.Size = new System.Drawing.Size(197, 21);
-            this.textBox1.TabIndex = 1;
+            this.txtMaxScriptStatements.Location = new System.Drawing.Point(15, 30);
+            this.txtMaxScriptStatements.Name = "txtMaxScriptStatements";
+            this.txtMaxScriptStatements.Size = new System.Drawing.Size(197, 21);
+            this.txtMaxScriptStatements.TabIndex = 1;
             // 
             // GlobalSettingsForm
             // 
             this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
             this.ClientSize = new System.Drawing.Size(315, 92);
-            this.Controls.Add(this.groupBox1);
+            this.Controls.Add(this.gbMaxScriptStatements);
             this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
             this.Icon = global::WelsonJS.Launcher.Properties.Resources.favicon;
             this.MaximizeBox = false;
             this.Name = "GlobalSettingsForm";
             this.Text = "Global settings...";
-            this.groupBox1.ResumeLayout(false);
-            this.groupBox1.PerformLayout();
+            this.gbMaxScriptStatements.ResumeLayout(false);
+            this.gbMaxScriptStatements.PerformLayout();
             this.ResumeLayout(false);
 
         }
 
         #endregion
 
-        private System.Windows.Forms.GroupBox groupBox1;
-        private System.Windows.Forms.TextBox textBox1;
-        private System.Windows.Forms.Button button1;
+        private System.Windows.Forms.GroupBox gbMaxScriptStatements;
+        private System.Windows.Forms.TextBox txtMaxScriptStatements;
+        private System.Windows.Forms.Button btnOkMaxScriptStatements;
     }
 }
\ No newline at end of file
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/GlobalSettingsForm.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/GlobalSettingsForm.cs
index 2c493a58..cba9b137 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/GlobalSettingsForm.cs
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/GlobalSettingsForm.cs
@@ -21,28 +21,35 @@ private void LoadRegistryValue()
             {
                 if (key != null)
                 {
-                    object value = key.GetValue(RegistryKey);
-                    if (value != null && value is int maxStatements)
+                    string value = key.GetValue(RegistryKey)?.ToString();
+                    if (value != null && int.TryParse(value, out int maxStatements))
                     {
-                        textBox1.Text = maxStatements.ToString();
+                        txtMaxScriptStatements.Text = maxStatements.ToString();
                     }
                 }
             }
         }
 
-        private void button1_Click(object sender, EventArgs e)
+        private void btnOkMaxScriptStatements_Click(object sender, EventArgs e)
         {
-            if (uint.TryParse(textBox1.Text, out uint maxStatements))
+            try
             {
-                using (RegistryKey key = Registry.CurrentUser.CreateSubKey(RegistryPath))
+                if (int.TryParse(txtMaxScriptStatements.Text, out int maxStatements))
                 {
-                    key.SetValue(RegistryKey, (int)maxStatements, RegistryValueKind.DWord);
+                    using (RegistryKey key = Registry.CurrentUser.CreateSubKey(RegistryPath))
+                    {
+                        key.SetValue(RegistryKey, maxStatements, RegistryValueKind.DWord);
+                    }
+                    MessageBox.Show($"MaxScriptStatements setting has been changed to {maxStatements}.", "Confirmation", MessageBoxButtons.OK, MessageBoxIcon.Information);
                 }
-                MessageBox.Show($"MaxScriptStatements setting has been changed to {maxStatements}.", "Confirmation", MessageBoxButtons.OK, MessageBoxIcon.Information);
-            }
-            else
+                else
+                {
+                    MessageBox.Show("Please enter a valid number within the DWORD range.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+                }
+            } 
+            catch (Exception ex)
             {
-                MessageBox.Show("Please enter a valid number within the DWORD range.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+                MessageBox.Show($"An error occurred while trying to change the MaxScriptStatements setting: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
             }
         }
     }
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/InstancesForm.Designer.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/InstancesForm.Designer.cs
index 90e42ebb..042b0d00 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/InstancesForm.Designer.cs
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/InstancesForm.Designer.cs
@@ -28,46 +28,48 @@ protected override void Dispose(bool disposing)
         /// </summary>
         private void InitializeComponent()
         {
-            this.listView1 = new System.Windows.Forms.ListView();
-            this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
-            this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+            this.lvInstances = new System.Windows.Forms.ListView();
+            this.chInstanceId = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+            this.chFirstDeployTime = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
             this.btnDelete = new System.Windows.Forms.Button();
             this.btnOpenWithExplorer = new System.Windows.Forms.Button();
-            this.checkBox2 = new System.Windows.Forms.CheckBox();
-            this.textBox1 = new System.Windows.Forms.TextBox();
-            this.checkBox1 = new System.Windows.Forms.CheckBox();
+            this.cbInteractiveServiceApp = new System.Windows.Forms.CheckBox();
+            this.txtUseSpecificScript = new System.Windows.Forms.TextBox();
+            this.cbUseSpecificScript = new System.Windows.Forms.CheckBox();
             this.btnStart = new System.Windows.Forms.Button();
             this.SuspendLayout();
             // 
-            // listView1
+            // lvInstances
             // 
-            this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
-            this.columnHeader1,
-            this.columnHeader2});
-            this.listView1.HideSelection = false;
-            this.listView1.Location = new System.Drawing.Point(12, 12);
-            this.listView1.Name = "listView1";
-            this.listView1.Size = new System.Drawing.Size(547, 253);
-            this.listView1.TabIndex = 0;
-            this.listView1.UseCompatibleStateImageBehavior = false;
-            this.listView1.View = System.Windows.Forms.View.Details;
+            this.lvInstances.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+            this.chInstanceId,
+            this.chFirstDeployTime});
+            this.lvInstances.HideSelection = false;
+            this.lvInstances.Location = new System.Drawing.Point(8, 8);
+            this.lvInstances.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
+            this.lvInstances.Name = "lvInstances";
+            this.lvInstances.Size = new System.Drawing.Size(384, 170);
+            this.lvInstances.TabIndex = 0;
+            this.lvInstances.UseCompatibleStateImageBehavior = false;
+            this.lvInstances.View = System.Windows.Forms.View.Details;
             // 
-            // columnHeader1
+            // chInstanceId
             // 
-            this.columnHeader1.Text = "Instance ID";
-            this.columnHeader1.Width = 220;
+            this.chInstanceId.Text = "Instance ID";
+            this.chInstanceId.Width = 220;
             // 
-            // columnHeader2
+            // chFirstDeployTime
             // 
-            this.columnHeader2.Text = "First Deploy Time";
-            this.columnHeader2.Width = 160;
+            this.chFirstDeployTime.Text = "First Deploy Time";
+            this.chFirstDeployTime.Width = 160;
             // 
             // btnDelete
             // 
             this.btnDelete.Image = global::WelsonJS.Launcher.Properties.Resources.icon_delete_32;
-            this.btnDelete.Location = new System.Drawing.Point(171, 364);
+            this.btnDelete.Location = new System.Drawing.Point(120, 243);
+            this.btnDelete.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
             this.btnDelete.Name = "btnDelete";
-            this.btnDelete.Size = new System.Drawing.Size(150, 60);
+            this.btnDelete.Size = new System.Drawing.Size(105, 40);
             this.btnDelete.TabIndex = 2;
             this.btnDelete.Text = "Delete";
             this.btnDelete.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
@@ -77,53 +79,52 @@ private void InitializeComponent()
             // btnOpenWithExplorer
             // 
             this.btnOpenWithExplorer.Image = global::WelsonJS.Launcher.Properties.Resources.icon_directory_32;
-            this.btnOpenWithExplorer.Location = new System.Drawing.Point(327, 364);
+            this.btnOpenWithExplorer.Location = new System.Drawing.Point(229, 243);
+            this.btnOpenWithExplorer.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
             this.btnOpenWithExplorer.Name = "btnOpenWithExplorer";
-            this.btnOpenWithExplorer.Size = new System.Drawing.Size(232, 60);
+            this.btnOpenWithExplorer.Size = new System.Drawing.Size(162, 40);
             this.btnOpenWithExplorer.TabIndex = 3;
             this.btnOpenWithExplorer.Text = "Open with Explorer";
             this.btnOpenWithExplorer.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
             this.btnOpenWithExplorer.UseVisualStyleBackColor = true;
             this.btnOpenWithExplorer.Click += new System.EventHandler(this.btnOpenWithExplorer_Click);
             // 
-            // checkBox2
-            // 
-            this.checkBox2.AutoSize = true;
-            this.checkBox2.Location = new System.Drawing.Point(15, 322);
-            this.checkBox2.Margin = new System.Windows.Forms.Padding(4);
-            this.checkBox2.Name = "checkBox2";
-            this.checkBox2.Size = new System.Drawing.Size(352, 22);
-            this.checkBox2.TabIndex = 9;
-            this.checkBox2.Text = "This is an Interactive Service Application";
-            this.checkBox2.UseVisualStyleBackColor = true;
-            // 
-            // textBox1
-            // 
-            this.textBox1.Enabled = false;
-            this.textBox1.Location = new System.Drawing.Point(284, 283);
-            this.textBox1.Margin = new System.Windows.Forms.Padding(4);
-            this.textBox1.Name = "textBox1";
-            this.textBox1.Size = new System.Drawing.Size(155, 28);
-            this.textBox1.TabIndex = 8;
-            // 
-            // checkBox1
-            // 
-            this.checkBox1.AutoSize = true;
-            this.checkBox1.Location = new System.Drawing.Point(15, 288);
-            this.checkBox1.Margin = new System.Windows.Forms.Padding(4);
-            this.checkBox1.Name = "checkBox1";
-            this.checkBox1.Size = new System.Drawing.Size(256, 22);
-            this.checkBox1.TabIndex = 7;
-            this.checkBox1.Text = "I want to use specific script ";
-            this.checkBox1.UseVisualStyleBackColor = true;
-            this.checkBox1.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged);
+            // cbInteractiveServiceApp
+            // 
+            this.cbInteractiveServiceApp.AutoSize = true;
+            this.cbInteractiveServiceApp.Location = new System.Drawing.Point(10, 215);
+            this.cbInteractiveServiceApp.Name = "cbInteractiveServiceApp";
+            this.cbInteractiveServiceApp.Size = new System.Drawing.Size(254, 16);
+            this.cbInteractiveServiceApp.TabIndex = 9;
+            this.cbInteractiveServiceApp.Text = "This is an Interactive Service Application";
+            this.cbInteractiveServiceApp.UseVisualStyleBackColor = true;
+            // 
+            // txtUseSpecificScript
+            // 
+            this.txtUseSpecificScript.Enabled = false;
+            this.txtUseSpecificScript.Location = new System.Drawing.Point(199, 189);
+            this.txtUseSpecificScript.Name = "txtUseSpecificScript";
+            this.txtUseSpecificScript.Size = new System.Drawing.Size(110, 21);
+            this.txtUseSpecificScript.TabIndex = 8;
+            // 
+            // cbUseSpecificScript
+            // 
+            this.cbUseSpecificScript.AutoSize = true;
+            this.cbUseSpecificScript.Location = new System.Drawing.Point(10, 192);
+            this.cbUseSpecificScript.Name = "cbUseSpecificScript";
+            this.cbUseSpecificScript.Size = new System.Drawing.Size(184, 16);
+            this.cbUseSpecificScript.TabIndex = 7;
+            this.cbUseSpecificScript.Text = "I want to use specific script ";
+            this.cbUseSpecificScript.UseVisualStyleBackColor = true;
+            this.cbUseSpecificScript.CheckedChanged += new System.EventHandler(this.cbUseSpecificScript_CheckedChanged);
             // 
             // btnStart
             // 
             this.btnStart.Image = global::WelsonJS.Launcher.Properties.Resources.icon_start_32;
-            this.btnStart.Location = new System.Drawing.Point(15, 364);
+            this.btnStart.Location = new System.Drawing.Point(10, 243);
+            this.btnStart.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
             this.btnStart.Name = "btnStart";
-            this.btnStart.Size = new System.Drawing.Size(150, 60);
+            this.btnStart.Size = new System.Drawing.Size(105, 40);
             this.btnStart.TabIndex = 1;
             this.btnStart.Text = "Start";
             this.btnStart.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
@@ -132,18 +133,19 @@ private void InitializeComponent()
             // 
             // InstancesForm
             // 
-            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(573, 444);
+            this.ClientSize = new System.Drawing.Size(401, 296);
             this.Controls.Add(this.btnStart);
-            this.Controls.Add(this.listView1);
+            this.Controls.Add(this.lvInstances);
             this.Controls.Add(this.btnDelete);
-            this.Controls.Add(this.checkBox1);
-            this.Controls.Add(this.checkBox2);
+            this.Controls.Add(this.cbUseSpecificScript);
+            this.Controls.Add(this.cbInteractiveServiceApp);
             this.Controls.Add(this.btnOpenWithExplorer);
-            this.Controls.Add(this.textBox1);
+            this.Controls.Add(this.txtUseSpecificScript);
             this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
             this.Icon = global::WelsonJS.Launcher.Properties.Resources.favicon;
+            this.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
             this.MaximizeBox = false;
             this.Name = "InstancesForm";
             this.Text = "Instances";
@@ -155,14 +157,14 @@ private void InitializeComponent()
 
         #endregion
 
-        private System.Windows.Forms.ListView listView1;
+        private System.Windows.Forms.ListView lvInstances;
         private System.Windows.Forms.Button btnDelete;
         private System.Windows.Forms.Button btnOpenWithExplorer;
-        private System.Windows.Forms.CheckBox checkBox2;
-        private System.Windows.Forms.TextBox textBox1;
-        private System.Windows.Forms.CheckBox checkBox1;
-        private System.Windows.Forms.ColumnHeader columnHeader1;
-        private System.Windows.Forms.ColumnHeader columnHeader2;
+        private System.Windows.Forms.CheckBox cbInteractiveServiceApp;
+        private System.Windows.Forms.TextBox txtUseSpecificScript;
+        private System.Windows.Forms.CheckBox cbUseSpecificScript;
+        private System.Windows.Forms.ColumnHeader chInstanceId;
+        private System.Windows.Forms.ColumnHeader chFirstDeployTime;
         private System.Windows.Forms.Button btnStart;
     }
 }
\ No newline at end of file
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/InstancesForm.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/InstancesForm.cs
index 10052e9c..0ba95da0 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/InstancesForm.cs
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/InstancesForm.cs
@@ -20,7 +20,7 @@ public InstancesForm()
 
         private void InstancesForm_Load(object sender, EventArgs e)
         {
-            listView1.Items.Clear();
+            lvInstances.Items.Clear();
             LoadInstances(Program.GetAppDataPath());
             LoadInstances(Path.GetTempPath());
         }
@@ -48,7 +48,7 @@ private void LoadInstances(string instancesRoot)
 
                 if (firstDeployTime != null)
                 {
-                    listView1.Items.Add(new ListViewItem(new[]
+                    lvInstances.Items.Add(new ListViewItem(new[]
                     {
                         Path.GetFileName(dir),
                         firstDeployTime
@@ -62,11 +62,11 @@ private void LoadInstances(string instancesRoot)
 
         private void btnStart_Click(object sender, EventArgs e)
         {
-            if (listView1.SelectedItems.Count > 0)
+            if (lvInstances.SelectedItems.Count > 0)
             {
-                scriptName = textBox1.Text;
+                scriptName = txtUseSpecificScript.Text;
 
-                string instanceId = listView1.SelectedItems[0].Text;
+                string instanceId = lvInstances.SelectedItems[0].Text;
                 string workingDirectory = Program.GetWorkingDirectory(instanceId, true);
 
                 Task.Run(() =>
@@ -74,7 +74,7 @@ private void btnStart_Click(object sender, EventArgs e)
                     try
                     {
                         // Run the appliction
-                        Program.RunCommandPrompt(workingDirectory, entryFileName, scriptName, checkBox1.Checked, checkBox2.Checked);
+                        Program.RunCommandPrompt(workingDirectory, entryFileName, scriptName, cbUseSpecificScript.Checked, cbInteractiveServiceApp.Checked);
                     }
                     catch (Exception ex)
                     {
@@ -90,9 +90,9 @@ private void btnStart_Click(object sender, EventArgs e)
 
         private void btnDelete_Click(object sender, EventArgs e)
         {
-            if (listView1.SelectedItems.Count > 0)
+            if (lvInstances.SelectedItems.Count > 0)
             {
-                string instanceId = listView1.SelectedItems[0].Text;
+                string instanceId = lvInstances.SelectedItems[0].Text;
                 string workingDirectory = Program.GetWorkingDirectory(instanceId, false);
 
                 if (!Directory.Exists(workingDirectory))
@@ -104,7 +104,7 @@ private void btnDelete_Click(object sender, EventArgs e)
                 {
                     Directory.Delete(workingDirectory, true);
 
-                    listView1.Items.Clear();
+                    lvInstances.Items.Clear();
                     LoadInstances(Program.GetAppDataPath());
                     LoadInstances(Path.GetTempPath());
                 }
@@ -117,9 +117,9 @@ private void btnDelete_Click(object sender, EventArgs e)
 
         private void btnOpenWithExplorer_Click(object sender, EventArgs e)
         {
-            if (listView1.SelectedItems.Count > 0)
+            if (lvInstances.SelectedItems.Count > 0)
             {
-                string instanceId = listView1.SelectedItems[0].Text;
+                string instanceId = lvInstances.SelectedItems[0].Text;
                 string workingDirectory = Program.GetWorkingDirectory(instanceId, true);
 
                 if (Directory.Exists(workingDirectory))
@@ -133,9 +133,9 @@ private void btnOpenWithExplorer_Click(object sender, EventArgs e)
             }
         }
 
-        private void checkBox1_CheckedChanged(object sender, EventArgs e)
+        private void cbUseSpecificScript_CheckedChanged(object sender, EventArgs e)
         {
-            textBox1.Enabled = checkBox1.Checked;
+            txtUseSpecificScript.Enabled = cbUseSpecificScript.Checked;
         }
     }
 }
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.Designer.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.Designer.cs
index 1652233d..56d54bc5 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.Designer.cs
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.Designer.cs
@@ -29,13 +29,13 @@ protected override void Dispose(bool disposing)
         private void InitializeComponent()
         {
             this.components = new System.ComponentModel.Container();
-            this.button1 = new System.Windows.Forms.Button();
-            this.button2 = new System.Windows.Forms.Button();
+            this.btnRunFromZipFile = new System.Windows.Forms.Button();
+            this.btnRunFromExternalLink = new System.Windows.Forms.Button();
             this.label1 = new System.Windows.Forms.Label();
             this.linkLabel1 = new System.Windows.Forms.LinkLabel();
-            this.checkBox1 = new System.Windows.Forms.CheckBox();
-            this.textBox1 = new System.Windows.Forms.TextBox();
-            this.checkBox2 = new System.Windows.Forms.CheckBox();
+            this.cbUseSpecificScript = new System.Windows.Forms.CheckBox();
+            this.txtUseSpecificScript = new System.Windows.Forms.TextBox();
+            this.cbInteractiveServiceApp = new System.Windows.Forms.CheckBox();
             this.menuStrip1 = new System.Windows.Forms.MenuStrip();
             this.settingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.userdefinedVariablesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
@@ -43,7 +43,7 @@ private void InitializeComponent()
             this.runAsAdministratorToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.globalSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.startCodeEditorToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
-            this.openMicrosoftCopilotToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.openCopilotToolStripMenuItem = 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();
@@ -53,29 +53,29 @@ private void InitializeComponent()
             this.contextMenuStrip1.SuspendLayout();
             this.SuspendLayout();
             // 
-            // button1
-            // 
-            this.button1.Image = global::WelsonJS.Launcher.Properties.Resources.icon_zip_128;
-            this.button1.Location = new System.Drawing.Point(24, 67);
-            this.button1.Name = "button1";
-            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;
-            this.button1.UseVisualStyleBackColor = true;
-            this.button1.Click += new System.EventHandler(this.button1_Click);
-            // 
-            // button2
-            // 
-            this.button2.Image = global::WelsonJS.Launcher.Properties.Resources.icon_link_128;
-            this.button2.Location = new System.Drawing.Point(230, 67);
-            this.button2.Name = "button2";
-            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;
-            this.button2.UseVisualStyleBackColor = true;
-            this.button2.Click += new System.EventHandler(this.button2_Click);
+            // btnRunFromZipFile
+            // 
+            this.btnRunFromZipFile.Image = global::WelsonJS.Launcher.Properties.Resources.icon_zip_128;
+            this.btnRunFromZipFile.Location = new System.Drawing.Point(24, 67);
+            this.btnRunFromZipFile.Name = "btnRunFromZipFile";
+            this.btnRunFromZipFile.Size = new System.Drawing.Size(200, 200);
+            this.btnRunFromZipFile.TabIndex = 0;
+            this.btnRunFromZipFile.Text = "From ZIP file...";
+            this.btnRunFromZipFile.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
+            this.btnRunFromZipFile.UseVisualStyleBackColor = true;
+            this.btnRunFromZipFile.Click += new System.EventHandler(this.btnRunFromZipFile_Click);
+            // 
+            // btnRunFromExternalLink
+            // 
+            this.btnRunFromExternalLink.Image = global::WelsonJS.Launcher.Properties.Resources.icon_link_128;
+            this.btnRunFromExternalLink.Location = new System.Drawing.Point(230, 67);
+            this.btnRunFromExternalLink.Name = "btnRunFromExternalLink";
+            this.btnRunFromExternalLink.Size = new System.Drawing.Size(200, 200);
+            this.btnRunFromExternalLink.TabIndex = 1;
+            this.btnRunFromExternalLink.Text = "From external link...";
+            this.btnRunFromExternalLink.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
+            this.btnRunFromExternalLink.UseVisualStyleBackColor = true;
+            this.btnRunFromExternalLink.Click += new System.EventHandler(this.btnRunFromExternalLink_Click);
             // 
             // label1
             // 
@@ -97,34 +97,34 @@ private void InitializeComponent()
             this.linkLabel1.Text = "https://github.com/gnh1201/welsonjs";
             this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
             // 
-            // checkBox1
+            // cbUseSpecificScript
             // 
-            this.checkBox1.AutoSize = true;
-            this.checkBox1.Location = new System.Drawing.Point(26, 281);
-            this.checkBox1.Name = "checkBox1";
-            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;
-            this.checkBox1.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged);
+            this.cbUseSpecificScript.AutoSize = true;
+            this.cbUseSpecificScript.Location = new System.Drawing.Point(26, 281);
+            this.cbUseSpecificScript.Name = "cbUseSpecificScript";
+            this.cbUseSpecificScript.Size = new System.Drawing.Size(184, 16);
+            this.cbUseSpecificScript.TabIndex = 4;
+            this.cbUseSpecificScript.Text = "I want to use specific script ";
+            this.cbUseSpecificScript.UseVisualStyleBackColor = true;
+            this.cbUseSpecificScript.CheckedChanged += new System.EventHandler(this.cbUseSpecificScript_CheckedChanged);
             // 
-            // textBox1
+            // txtUseSpecificScript
             // 
-            this.textBox1.Enabled = false;
-            this.textBox1.Location = new System.Drawing.Point(214, 278);
-            this.textBox1.Name = "textBox1";
-            this.textBox1.Size = new System.Drawing.Size(110, 21);
-            this.textBox1.TabIndex = 5;
+            this.txtUseSpecificScript.Enabled = false;
+            this.txtUseSpecificScript.Location = new System.Drawing.Point(214, 278);
+            this.txtUseSpecificScript.Name = "txtUseSpecificScript";
+            this.txtUseSpecificScript.Size = new System.Drawing.Size(110, 21);
+            this.txtUseSpecificScript.TabIndex = 5;
             // 
-            // checkBox2
+            // cbInteractiveServiceApp
             // 
-            this.checkBox2.AutoSize = true;
-            this.checkBox2.Location = new System.Drawing.Point(26, 305);
-            this.checkBox2.Name = "checkBox2";
-            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;
+            this.cbInteractiveServiceApp.AutoSize = true;
+            this.cbInteractiveServiceApp.Location = new System.Drawing.Point(26, 305);
+            this.cbInteractiveServiceApp.Name = "cbInteractiveServiceApp";
+            this.cbInteractiveServiceApp.Size = new System.Drawing.Size(254, 16);
+            this.cbInteractiveServiceApp.TabIndex = 6;
+            this.cbInteractiveServiceApp.Text = "This is an Interactive Service Application";
+            this.cbInteractiveServiceApp.UseVisualStyleBackColor = true;
             // 
             // menuStrip1
             // 
@@ -144,7 +144,7 @@ private void InitializeComponent()
             this.runAsAdministratorToolStripMenuItem,
             this.globalSettingsToolStripMenuItem,
             this.startCodeEditorToolStripMenuItem,
-            this.openMicrosoftCopilotToolStripMenuItem});
+            this.openCopilotToolStripMenuItem});
             this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem";
             this.settingsToolStripMenuItem.Size = new System.Drawing.Size(62, 20);
             this.settingsToolStripMenuItem.Text = "Settings";
@@ -152,44 +152,44 @@ private void InitializeComponent()
             // userdefinedVariablesToolStripMenuItem
             // 
             this.userdefinedVariablesToolStripMenuItem.Name = "userdefinedVariablesToolStripMenuItem";
-            this.userdefinedVariablesToolStripMenuItem.Size = new System.Drawing.Size(210, 22);
+            this.userdefinedVariablesToolStripMenuItem.Size = new System.Drawing.Size(196, 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(210, 22);
+            this.instancesToolStripMenuItem.Size = new System.Drawing.Size(196, 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(210, 22);
+            this.runAsAdministratorToolStripMenuItem.Size = new System.Drawing.Size(196, 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(210, 22);
+            this.globalSettingsToolStripMenuItem.Size = new System.Drawing.Size(196, 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(210, 22);
+            this.startCodeEditorToolStripMenuItem.Size = new System.Drawing.Size(196, 22);
             this.startCodeEditorToolStripMenuItem.Text = "Start the code editor...";
             this.startCodeEditorToolStripMenuItem.Click += new System.EventHandler(this.startCodeEditorToolStripMenuItem_Click);
             // 
-            // openMicrosoftCopilotToolStripMenuItem
+            // openCopilotToolStripMenuItem
             // 
-            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);
+            this.openCopilotToolStripMenuItem.Name = "openCopilotToolStripMenuItem";
+            this.openCopilotToolStripMenuItem.Size = new System.Drawing.Size(196, 22);
+            this.openCopilotToolStripMenuItem.Text = "Open the Copilot...";
+            this.openCopilotToolStripMenuItem.Click += new System.EventHandler(this.openCopilotToolStripMenuItem_Click);
             // 
             // notifyIcon1
             // 
@@ -230,13 +230,13 @@ private void InitializeComponent()
             this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
             this.ClientSize = new System.Drawing.Size(461, 382);
-            this.Controls.Add(this.checkBox2);
-            this.Controls.Add(this.textBox1);
-            this.Controls.Add(this.checkBox1);
+            this.Controls.Add(this.cbInteractiveServiceApp);
+            this.Controls.Add(this.txtUseSpecificScript);
+            this.Controls.Add(this.cbUseSpecificScript);
             this.Controls.Add(this.linkLabel1);
             this.Controls.Add(this.label1);
-            this.Controls.Add(this.button2);
-            this.Controls.Add(this.button1);
+            this.Controls.Add(this.btnRunFromExternalLink);
+            this.Controls.Add(this.btnRunFromZipFile);
             this.Controls.Add(this.menuStrip1);
             this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
             this.Icon = global::WelsonJS.Launcher.Properties.Resources.favicon;
@@ -254,13 +254,13 @@ private void InitializeComponent()
 
         #endregion
 
-        private System.Windows.Forms.Button button1;
-        private System.Windows.Forms.Button button2;
+        private System.Windows.Forms.Button btnRunFromZipFile;
+        private System.Windows.Forms.Button btnRunFromExternalLink;
         private System.Windows.Forms.Label label1;
         private System.Windows.Forms.LinkLabel linkLabel1;
-        private System.Windows.Forms.CheckBox checkBox1;
-        private System.Windows.Forms.TextBox textBox1;
-        private System.Windows.Forms.CheckBox checkBox2;
+        private System.Windows.Forms.CheckBox cbUseSpecificScript;
+        private System.Windows.Forms.TextBox txtUseSpecificScript;
+        private System.Windows.Forms.CheckBox cbInteractiveServiceApp;
         private System.Windows.Forms.MenuStrip menuStrip1;
         private System.Windows.Forms.ToolStripMenuItem settingsToolStripMenuItem;
         private System.Windows.Forms.ToolStripMenuItem userdefinedVariablesToolStripMenuItem;
@@ -273,7 +273,7 @@ private void InitializeComponent()
         private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem;
         private System.Windows.Forms.ToolStripMenuItem openCodeEditorToolStripMenuItem;
         private System.Windows.Forms.ToolStripMenuItem openLauncherToolStripMenuItem;
-        private System.Windows.Forms.ToolStripMenuItem openMicrosoftCopilotToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem openCopilotToolStripMenuItem;
     }
 }
 
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs
index 148c966c..bd94471f 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs
@@ -62,43 +62,54 @@ private void OnExit(object sender, EventArgs e)
         private void EnableUI()
         {
             label1.Text = "Choose the location of WelsonJS application package.";
-            button1.Enabled = true;
-            button2.Enabled = true;
-            checkBox1.Enabled = true;
-            checkBox2.Enabled = true;
-            if (checkBox1.Checked)
+            btnRunFromZipFile.Enabled = true;
+            btnRunFromExternalLink.Enabled = true;
+            cbUseSpecificScript.Enabled = true;
+            cbInteractiveServiceApp.Enabled = true;
+            if (cbUseSpecificScript.Checked)
             {
-                textBox1.Enabled = true;
+                txtUseSpecificScript.Enabled = true;
             }
         }
 
         private void DisableUI()
         {
             label1.Text = "Please wait...";
-            button1.Enabled = false;
-            button2.Enabled = false;
-            checkBox1.Enabled = false;
-            checkBox2.Enabled = false;
-            textBox1.Enabled = false;
+            btnRunFromZipFile.Enabled = false;
+            btnRunFromExternalLink.Enabled = false;
+            cbUseSpecificScript.Enabled = false;
+            cbInteractiveServiceApp.Enabled = false;
+            txtUseSpecificScript.Enabled = false;
         }
 
-        private void button2_Click(object sender, EventArgs e)
+        private void SafeInvoke(Action action)
         {
-            MessageBox.Show("Comming soon...!");
+            if (InvokeRequired)
+            {
+                Invoke(action);
+            }
+            else
+            {
+                action();
+            }
         }
 
-        private void button1_Click(object sender, EventArgs e)
+        private void btnRunFromExternalLink_Click(object sender, EventArgs e)
         {
-            string filePath = OpenFileDialog();
-            if (filePath != null)
+            MessageBox.Show("Coming soon...!");
+        }
+
+        private void btnRunFromZipFile_Click(object sender, EventArgs e)
+        {
+            using (var openFileDialog = new OpenFileDialog())
             {
-                string fileExtension = Path.GetExtension(filePath);
-                if (fileExtension != ".zip")
-                {
-                    MessageBox.Show("It doesn't seems to a ZIP file.");
-                }
-                else
+                openFileDialog.Filter = "zip files (*.zip)|*.zip|All files (*.*)|*.*";
+                openFileDialog.FilterIndex = 2;
+                openFileDialog.RestoreDirectory = true;
+
+                if (openFileDialog.ShowDialog() == DialogResult.OK)
                 {
+                    string filePath = openFileDialog.FileName;
                     ExtractAndRun(filePath);
                 }
             }
@@ -108,7 +119,7 @@ private void ExtractAndRun(string filePath)
         {
             instanceId = Guid.NewGuid().ToString();
             workingDirectory = Program.GetWorkingDirectory(instanceId);
-            scriptName = textBox1.Text;
+            scriptName = txtUseSpecificScript.Text;
 
             Task.Run(() =>
             {
@@ -130,15 +141,18 @@ private void ExtractAndRun(string filePath)
                     workingDirectory = Program.GetWorkingDirectory(instanceId, true);
 
                     // Run the appliction
-                    Program.RunCommandPrompt(workingDirectory, entryFileName, scriptName, checkBox1.Checked, checkBox2.Checked);
+                    Program.RunCommandPrompt(workingDirectory, entryFileName, scriptName, cbUseSpecificScript.Checked, cbInteractiveServiceApp.Checked);
                 }
                 catch (Exception ex)
                 {
-                    MessageBox.Show(ex.Message);
+                    SafeInvoke(() =>
+                    {
+                        MessageBox.Show("Error: " + ex.Message);
+                    });
                 }
 
                 // Enable UI
-                label1.Invoke((MethodInvoker)delegate {
+                SafeInvoke(() => {
                     EnableUI();
                 });
             });
@@ -161,22 +175,6 @@ private void RecordFirstDeployTime(string directory)
             }
         }
 
-        private string OpenFileDialog()
-        {
-            string filePath = null;
-
-            using (OpenFileDialog fileDialog = new OpenFileDialog())
-            {
-                if (fileDialog.ShowDialog() == DialogResult.OK)
-                {
-                    // Get the path of specified file
-                    filePath = fileDialog.FileName;
-                }
-            }
-
-            return filePath;
-        }
-
         private bool IsInAdministrator()
         {
             try
@@ -190,14 +188,14 @@ private bool IsInAdministrator()
             }
         }
 
-        private void checkBox1_CheckedChanged(object sender, EventArgs e)
+        private void cbUseSpecificScript_CheckedChanged(object sender, EventArgs e)
         {
-            textBox1.Enabled = checkBox1.Checked;
+            txtUseSpecificScript.Enabled = cbUseSpecificScript.Checked;
         }
 
         private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
         {
-            Process.Start("https://github.com/gnh1201/welsonjs");
+            Program.OpenWebBrowser(Properties.Resources.RepositoryUrl);
         }
 
         private void userdefinedVariablesToolStripMenuItem_Click(object sender, EventArgs e)
@@ -247,7 +245,7 @@ private void startCodeEditorToolStripMenuItem_Click(object sender, EventArgs e)
         {
             if (Program.resourceServer == null)
             {
-                Program.resourceServer = new ResourceServer("http://localhost:3000/", "editor.html");
+                Program.resourceServer = new ResourceServer(Properties.Resources.ResourceServerPrefix, "editor.html");
             }
 
             if (!Program.resourceServer.IsRunning())
@@ -273,9 +271,9 @@ private void openCodeEditorToolStripMenuItem_Click(object sender, EventArgs e)
             }
         }
 
-        private void openMicrosoftCopilotToolStripMenuItem_Click(object sender, EventArgs e)
+        private void openCopilotToolStripMenuItem_Click(object sender, EventArgs e)
         {
-            Program.OpenWebBrowser("https://copilot.microsoft.com/");
+            Program.OpenWebBrowser(Properties.Resources.CopilotUrl);
         }
     }
 }
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/Properties/Resources.Designer.cs b/WelsonJS.Toolkit/WelsonJS.Launcher/Properties/Resources.Designer.cs
index 6a41cd21..c4f5ce7c 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/Properties/Resources.Designer.cs
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/Properties/Resources.Designer.cs
@@ -60,6 +60,15 @@ internal Resources() {
             }
         }
         
+        /// <summary>
+        ///   https://copilot.microsoft.com/과(와) 유사한 지역화된 문자열을 찾습니다.
+        /// </summary>
+        internal static string CopilotUrl {
+            get {
+                return ResourceManager.GetString("CopilotUrl", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   (아이콘)과(와) 유사한 System.Drawing.Icon 형식의 지역화된 리소스를 찾습니다.
         /// </summary>
@@ -159,5 +168,23 @@ internal static System.Drawing.Bitmap icon_zip_128 {
                 return ((System.Drawing.Bitmap)(obj));
             }
         }
+        
+        /// <summary>
+        ///   https://github.com/gnh1201/welsonjs과(와) 유사한 지역화된 문자열을 찾습니다.
+        /// </summary>
+        internal static string RepositoryUrl {
+            get {
+                return ResourceManager.GetString("RepositoryUrl", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   http://localhost:3000/과(와) 유사한 지역화된 문자열을 찾습니다.
+        /// </summary>
+        internal static string ResourceServerPrefix {
+            get {
+                return ResourceManager.GetString("ResourceServerPrefix", resourceCulture);
+            }
+        }
     }
 }
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/Properties/Resources.resx b/WelsonJS.Toolkit/WelsonJS.Launcher/Properties/Resources.resx
index 2167f665..a947a72b 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/Properties/Resources.resx
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/Properties/Resources.resx
@@ -148,4 +148,13 @@
   <data name="icon_start_32" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\Resources\icon_start_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
+  <data name="CopilotUrl" xml:space="preserve">
+    <value>https://copilot.microsoft.com/</value>
+  </data>
+  <data name="RepositoryUrl" xml:space="preserve">
+    <value>https://github.com/gnh1201/welsonjs</value>
+  </data>
+  <data name="ResourceServerPrefix" xml:space="preserve">
+    <value>http://localhost:3000/</value>
+  </data>
 </root>
\ No newline at end of file
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/app.config b/WelsonJS.Toolkit/WelsonJS.Launcher/app.config
index 312bb3f2..2a2d4499 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/app.config
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/app.config
@@ -1,3 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <configuration>
-<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/></startup></configuration>
+  <startup>
+    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
+  </startup>
+</configuration>
diff --git a/WelsonJS.Toolkit/WelsonJS.Launcher/editor.html b/WelsonJS.Toolkit/WelsonJS.Launcher/editor.html
index 18ccf902..c6be876e 100644
--- a/WelsonJS.Toolkit/WelsonJS.Launcher/editor.html
+++ b/WelsonJS.Toolkit/WelsonJS.Launcher/editor.html
@@ -3,9 +3,9 @@
 <head>
     <title>WelsonJS Editor</title>
     <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
-    <link rel="stylesheet" href="https://cdn.metroui.org.ua/dev/metro.css">
-    <link rel="stylesheet" href="https://cdn.metroui.org.ua/dev/icons.css">
-    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.52.2/min/vs/editor/editor.main.css">
+    <link rel="stylesheet" href="https://catswords.blob.core.windows.net/welsonjs/ajax/libs/metroui/dev/lib/metro.css" integrity="sha384-4XgOiXH2ZMaWt5s5B35yKi7EAOabhZvx7wO8Jr71q2vZ+uONdRza/6CsK2kpyocd" crossorigin="anonymous">
+    <link rel="stylesheet" href="https://catswords.blob.core.windows.net/welsonjs/ajax/libs/metroui/dev/lib/icons.css" integrity="sha384-FuLND994etg+RtnpPSPMyNBvL+fEz+xGhbN61WUWuDEeZ+wJzcQ8SGqAMuI5hWrt" crossorigin="anonymous">
+    <link rel="stylesheet" href="https://catswords.blob.core.windows.net/welsonjs/ajax/libs/monaco-editor/0.52.2/min/vs/editor/editor.main.css" integrity="sha384-06yHXpYRlHEPaR4AS0fB/W+lMN09Zh5e1XMtfkNQdHV38OlhfkOEW5M+pCj3QskC" crossorigin="anonymous">
     <style>
         html, body {
             margin: 0;
@@ -85,16 +85,16 @@
     <script>
         var require = {
             paths: {
-                vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.52.2/min/vs'
+                vs: 'https://catswords.blob.core.windows.net/welsonjs/ajax/libs/monaco-editor/0.52.2/min/vs'
             }
         };
     </script>
-    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/fast-xml-parser/4.5.1/fxparser.min.js"></script>
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.2.4/purify.min.js"></script>
-    <script src="https://cdn.metroui.org.ua/dev/metro.js"></script>
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.52.2/min/vs/loader.min.js"></script>
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.52.2/min/vs/editor/editor.main.js"></script>
+    <script src="https://catswords.blob.core.windows.net/welsonjs/ajax/libs/axios/1.8.4/axios.min.js" integrity="sha384-06w+raHvkSL3+E7mbQ2X6DZwI5A3veU8Ba+NLrAPxxRGw4Xy78sihHDHQMustMM4" crossorigin="anonymous"></script>
+    <script src="https://catswords.blob.core.windows.net/welsonjs/ajax/libs/fast-xml-parser/4.5.1/fxparser.min.js" integrity="sha384-ae/HepOQ8hiJ/VA6yGwPMGXQXOkT/lJpjlcQ7EUgibUcfnBltuozgNj4IgOZ9QLc" crossorigin="anonymous"></script>
+    <script src="https://catswords.blob.core.windows.net/welsonjs/ajax/libs/dompurify/3.2.4/purify.min.js" integrity="sha384-eEu5CTj3qGvu9PdJuS+YlkNi7d2XxQROAFYOr59zgObtlcux1ae1Il3u7jvdCSWu" crossorigin="anonymous"></script>
+    <script src="https://catswords.blob.core.windows.net/welsonjs/ajax/libs/metroui/dev/lib/metro.js" integrity="sha384-grz4KlnFmdCd5ELenGIdPkUL/l+44UC4SniSke/OZQyRYXaQ1EDlGigacn6z4hGB" crossorigin="anonymous"></script>
+    <script src="https://catswords.blob.core.windows.net/welsonjs/ajax/libs/monaco-editor/0.52.2/min/vs/loader.js" integrity="sha384-pHG02SG8pId94Np3AbPmBEJ1yPqaH0IkJGLSNGXYmuGhkazT8Lr/57WYpbkGjJtu" crossorigin="anonymous"></script>
+    <script src="https://catswords.blob.core.windows.net/welsonjs/ajax/libs/monaco-editor/0.52.2/min/vs/editor/editor.main.js" integrity="sha384-fj9z+NUc93I3woCCy5IRQfrQ8Amu1E27tllwgb5gz3d9Vr1ymS13xcF6two3e4KH" crossorigin="anonymous"></script>
     <script>
         var editor;
         var currentFileName = "sayhello.js";
diff --git a/bootstrap.bat b/bootstrap.bat
index 78c012d3..6cc5f768 100644
--- a/bootstrap.bat
+++ b/bootstrap.bat
@@ -5,8 +5,7 @@ REM Source code available: https://github.com/gnh1201/welsonjs
 pushd %~dp0
 
 :: Define variables
-set BLOB_SAS_TOKEN=sp=r^&st=2025-03-27T07:49:26Z^&se=2035-03-27T15:49:26Z^&spr=https^&sv=2024-11-04^&sr=b^&sig=iQBsKk7lXwwdi0g2rY1KOD%%2Fi5zuG7PBlfGwmWaCJEBs%%3D
-set TOOLKIT_URL="https://catswords.blob.core.windows.net/welsonjs/welsonjs_toolkit_latest.cab?%BLOB_SAS_TOKEN%"
+set TOOLKIT_URL=https://catswords.blob.core.windows.net/welsonjs/welsonjs_toolkit_latest.cab
 set TOOLKIT_PATH=%APPDATA%\welsonjs\welsonjs_toolkit_latest.cab
 set TOOLKIT_EXTRACT_PATH=%APPDATA%\welsonjs
 set REGASM_PATH=%WINDIR%\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe


Reviews:
user: login: sourcery-ai[bot]
body: Hey @gnh1201 - I've reviewed your changes - here's some feedback:

**Overall Comments**:
- The renaming of UI elements is good for clarity and maintainability.
- Consider using a consistent naming convention for UI elements (e.g., prefixes like `btn`, `txt`, `lv`, `cb`, `gb`).

<details>
<summary>Here's what I looked at during the review</summary>

- 🟡 **General issues**: 1 issue found
- 🟢 **Security**: all looks good
- 🟢 **Testing**: all looks good
- 🟢 **Complexity**: all looks good
- 🟢 **Documentation**: all looks good
</details>

***

<details>
<summary>Sourcery is free for open source - if you like our reviews please consider sharing them ✨</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https://sourcery.ai)
- [Facebook](https://www.facebook.com/sharer/sharer.php?u=https://sourcery.ai)

</details>

<sub>
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
</sub>
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-31T05:29:56Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 2**

<details>
<summary>🧹 Nitpick comments (5)</summary><blockquote>

<details>
<summary>WelsonJS.Toolkit/WelsonJS.Launcher/editor.html (2)</summary><blockquote>

`6-8`: **CDN Link Elements Updated with SRI and CORS**  
The updated `<link>` tags now point to the new Azure Blob Storage CDN and include both integrity and crossorigin attributes. This improves resource security by ensuring that the downloaded stylesheets are not tampered with.  
Please verify that the SRI hashes are correct for the actual content served from the CDN and consider externalizing these URLs and hash values if they are used throughout the project to simplify future updates.

---

`92-97`: **Script Tags Enhanced with SRI and CORS Attributes**  
Script tags for external libraries (Axios, Fast XML Parser, DOMPurify, Metro UI, Monaco Editor loader, and main script) have been updated to include integrity and crossorigin attributes. This change not only improves security by validating the scripts’ content at load time but also ensures compliance with modern web security practices.  
Please ensure that the integrity hash values are up-to-date with the actual file contents from the CDN. Also, as a good-to-have improvement, consider centralizing these external resource definitions (URLs and integrity values) in a configuration file to streamline updates in the future.

</blockquote></details>
<details>
<summary>WelsonJS.Toolkit/WelsonJS.Launcher/app.config (2)</summary><blockquote>

`3-7`: **Review the use of HTTP for ResourceServerPrefix.**

The configuration now properly centralizes URLs, but using HTTP instead of HTTPS for the ResourceServerPrefix could pose security risks in production environments. While this may be acceptable for local development (localhost), consider using HTTPS in production.



Also, the repository and Copilot URLs look good with HTTPS and appropriate endpoints.

---

`8-10`: **Ensure consistent indentation in XML configuration.**

The `<startup>` element has different indentation than the `<appSettings>` element. While this doesn't affect functionality, consistent indentation improves readability.

Apply this diff to fix the indentation:

```diff
  <appSettings>
    <add key="ResourceServerPrefix" value="http://localhost:3000"/>
    <add key="RepositoryUrl" value="https://github.com/gnh1201/welsonjs"/>
    <add key="CopilotUrl" value="https://copilot.microsoft.com/"/>
  </appSettings>
-<startup>
-  <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
-</startup>
+  <startup>
+    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
+  </startup>
```

</blockquote></details>
<details>
<summary>WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs (1)</summary><blockquote>

`98-101`: **Typo in message**

There's a spelling error in the message dialog.

```diff
-    MessageBox.Show("Comming soon...!");
+    MessageBox.Show("Coming soon...!");
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 7e9054fb8fddd417b12e4c0b9bb8b661914816ef and 4f319d474fd7a8adbbf51ab906af7603fdc720d2.

</details>

<details>
<summary>📒 Files selected for processing (11)</summary>

* `WelsonJS.Toolkit/WelsonJS.Launcher/EnvForm.Designer.cs` (8 hunks)
* `WelsonJS.Toolkit/WelsonJS.Launcher/EnvForm.cs` (7 hunks)
* `WelsonJS.Toolkit/WelsonJS.Launcher/GlobalSettingsForm.Designer.cs` (1 hunks)
* `WelsonJS.Toolkit/WelsonJS.Launcher/GlobalSettingsForm.cs` (1 hunks)
* `WelsonJS.Toolkit/WelsonJS.Launcher/InstancesForm.Designer.cs` (4 hunks)
* `WelsonJS.Toolkit/WelsonJS.Launcher/InstancesForm.cs` (7 hunks)
* `WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.Designer.cs` (7 hunks)
* `WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs` (7 hunks)
* `WelsonJS.Toolkit/WelsonJS.Launcher/WelsonJS.Launcher.csproj` (1 hunks)
* `WelsonJS.Toolkit/WelsonJS.Launcher/app.config` (1 hunks)
* `WelsonJS.Toolkit/WelsonJS.Launcher/editor.html` (2 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Definitions (2)</summary>

<details>
<summary>WelsonJS.Toolkit/WelsonJS.Launcher/GlobalSettingsForm.Designer.cs (1)</summary><blockquote>

<details>
<summary>WelsonJS.Toolkit/WelsonJS.Launcher/GlobalSettingsForm.cs (1)</summary>

* `btnOkMaxScriptStatements_Click` (33-47)

</details>

</blockquote></details>
<details>
<summary>WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs (2)</summary><blockquote>

<details>
<summary>WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs (3)</summary>

* `Program` (11-159)
* `RunCommandPrompt` (34-92)
* `OpenWebBrowser` (141-158)

</details>
<details>
<summary>WelsonJS.Toolkit/WelsonJS.Launcher/Tools/ResourceServer.cs (2)</summary>

* `ResourceServer` (16-366)
* `ResourceServer` (26-33)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Analyze (javascript)

</details>

<details>
<summary>🔇 Additional comments (44)</summary><blockquote>

<details>
<summary>WelsonJS.Toolkit/WelsonJS.Launcher/editor.html (1)</summary>

`88-88`: **Monaco Editor Path Update in Require Config**  
The require configuration for Monaco Editor (line 88) has been updated to reflect the new CDN URL. This is an important change for ensuring the editor loads correctly from the new source.  
Double-check that the editor still resolves all its dependencies correctly with this new path setting.

</details>
<details>
<summary>WelsonJS.Toolkit/WelsonJS.Launcher/InstancesForm.Designer.cs (3)</summary>

`31-33`: **Good work renaming controls for better readability.**

Renaming the ListView and its ColumnHeaders from generic names (listView1, columnHeader1, columnHeader2) to descriptive names (lvInstances, chInstanceId, chFirstDeployTime) improves code readability and maintainability.

---

`36-38`: **Good addition of well-named UI controls.**

The addition of these controls with descriptive names (cbInteractiveServiceApp, txtUseSpecificScript, cbUseSpecificScript) improves the UI functionality and code clarity.

---

`160-168`: **Good private field renaming for consistency.**

Renaming the private fields to match the UI control names enhances code readability and maintainability throughout the codebase.

</details>
<details>
<summary>WelsonJS.Toolkit/WelsonJS.Launcher/WelsonJS.Launcher.csproj (1)</summary>

`60-60`: **Good addition of System.Configuration reference.**

Adding the System.Configuration reference is necessary to support reading the newly added application settings from app.config.

</details>
<details>
<summary>WelsonJS.Toolkit/WelsonJS.Launcher/EnvForm.cs (4)</summary>

`4-4`: **Good practice specifying default encoding.**

Adding a specific encoding (UTF-8) for file operations is a good practice that ensures consistent text handling, especially for internationalization support.



Also applies to: 13-13

---

`29-33`: **Improved control naming in InitializeListView.**

Renaming `listView1` to `lvUserDefinedVariables` provides much better clarity about the control's purpose throughout the code.

---

`171-171`: **Consistent use of defaultEncoding for file operations.**

The consistent application of the defaultEncoding across all file read/write operations is a good practice that ensures encoding consistency throughout the application.



Also applies to: 223-223, 286-286

---

`190-196`: **Improved using statement with braces for disposable resources.**

The code now properly implements using statements with braces for disposable resources like dialogs, which ensures proper resource cleanup.



Also applies to: 202-209, 214-258

</details>
<details>
<summary>WelsonJS.Toolkit/WelsonJS.Launcher/GlobalSettingsForm.cs (3)</summary>

`24-27`: **Improved registry value handling.**

The new implementation properly retrieves registry values as strings and uses `int.TryParse` for safe conversion, which is more robust than the previous approach.

---

`33-33`: **Better method naming convention.**

Renaming from `button1_Click` to `btnOkMaxScriptStatements_Click` improves code readability by clearly indicating which control triggers this event.

---

`35-40`: **Improved type handling and registry value setting.**

Using `int.TryParse` with the out parameter pattern provides cleaner code and eliminates the need for additional type casting when setting the registry value.

</details>
<details>
<summary>WelsonJS.Toolkit/WelsonJS.Launcher/InstancesForm.cs (7)</summary>

`23-23`: **Improved control naming convention.**

Renaming `listView1` to `lvInstances` follows better naming conventions and improves code readability.

---

`51-59`: **Consistent control naming in item addition.**

The renamed ListView control is consistently used when adding items, maintaining code clarity.

---

`65-70`: **Better variable and control naming.**

Using descriptive control names (`lvInstances`, `txtUseSpecificScript`) instead of generic names improves code readability and maintainability.

---

`77-77`: **Improved parameter naming in method call.**

Using clearly named checkbox variables (`cbUseSpecificScript`, `cbInteractiveServiceApp`) makes the method call more self-documenting.

---

`93-107`: **Consistent ListView naming in deletion logic.**

The renamed control is used consistently throughout the delete operation, maintaining naming standards.

---

`120-123`: **Consistent control naming in explorer operation.**

Continuing the consistent naming convention improves maintainability.

---

`138-138`: **More descriptive control references in event handler.**

Using `txtUseSpecificScript.Enabled = cbUseSpecificScript.Checked` provides better clarity than the previous generic control names.

</details>
<details>
<summary>WelsonJS.Toolkit/WelsonJS.Launcher/GlobalSettingsForm.Designer.cs (6)</summary>

`31-34`: **Improved UI component naming.**

Renaming UI components with appropriate prefixes (`gb` for GroupBox, `btn` for Button, `txt` for TextBox) follows standard naming conventions and improves code maintainability.

---

`37-46`: **Consistent GroupBox property updates.**

All references to the GroupBox have been updated to use the new more descriptive name, maintaining consistency.

---

`48-57`: **Updated Button properties and event handler.**

The button's properties and event handler have been properly renamed to follow the new naming convention, ensuring consistent behavior.

---

`59-64`: **Consistent TextBox property updates.**

TextBox properties have been updated to use the more descriptive name, following the same naming pattern.

---

`71-78`: **Updated form Controls collection and layout methods.**

The form's Controls collection and layout methods have been updated to reference the renamed components.

---

`85-87`: **Updated control declarations.**

The private field declarations have been updated to use the more descriptive names, completing the refactoring.

</details>
<details>
<summary>WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.Designer.cs (11)</summary>

`32-38`: **Improved UI component naming throughout.**

Renaming UI components with appropriate prefixes (`btn` for Buttons, `cb` for CheckBoxes, `txt` for TextBoxes) significantly improves code readability and follows standard naming conventions.

---

`46-46`: **Updated Copilot menu item naming.**

Renaming from `openMicrosoftCopilotToolStripMenuItem` to `openCopilotToolStripMenuItem` removes the Microsoft reference.

---

`56-66`: **Consistent Button property and event handler updates.**

The first button's properties and event handler have been updated to use the more descriptive name (`btnRunFromZipFile`), improving code clarity.

---

`68-78`: **Consistent second Button property updates.**

The second button's properties and event handler have been updated with the descriptive name (`btnRunFromExternalLink`), maintaining naming consistency.

---

`100-109`: **Updated CheckBox properties.**

CheckBox properties have been updated with descriptive names that clearly indicate their purpose.

---

`111-117`: **Improved TextBox property naming.**

TextBox properties now use the descriptive name `txtUseSpecificScript` instead of the generic `textBox1`.

---

`119-127`: **Clear naming for interactive service checkbox.**

The checkbox for interactive service applications now uses a descriptive name that clearly indicates its purpose.

---

`147-147`: **Updated menu item sizes and properties.**

Menu item sizes have been adjusted for better layout, and properties have been updated consistently with the new naming scheme.



Also applies to: 155-156, 162-163, 169-170, 176-177, 183-184

---

`187-192`: **Updated Copilot menu item properties.**

The Copilot menu item properties now use the new name consistently throughout the code.

---

`233-239`: **Updated Controls collection with renamed components.**

The form's Controls collection has been updated to use the renamed components, maintaining consistency.

---

`257-263`: **Updated private field declarations.**

Private field declarations have been updated to use descriptive names, completing the refactoring.



Also applies to: 276-276

</details>
<details>
<summary>WelsonJS.Toolkit/WelsonJS.Launcher/EnvForm.Designer.cs (3)</summary>

`31-32`: **Good improvement in control naming!**

Renaming from generic names like `groupBox1` to more descriptive names (`gbUserDefinedVariables`) with appropriate prefixes improves code readability and maintainability.



Also applies to: 54-60

---

`223-225`: **Appropriate form size adjustment**

The form dimensions have been reduced from 639x794 to 447x529, creating a more compact and focused UI, which improves user experience.

---

`244-245`: **Consistent declaration updates**

Field declarations correctly updated to match the new control names, maintaining consistency throughout the code.



Also applies to: 254-254, 257-257

</details>
<details>
<summary>WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs (5)</summary>

`2-2`: **Good addition of Configuration namespace**

Adding the System.Configuration namespace is appropriate for accessing AppSettings values from the config file.

---

`86-96`: **Excellent addition of SafeInvoke method**

Adding a SafeInvoke method improves thread safety when updating UI elements from background threads. This is a best practice for Windows Forms applications.

---

`103-117`: **Better file dialog implementation**

Improved implementation with:
1. Proper resource management using a `using` statement
2. Appropriate filter settings for ZIP files
3. Better method naming that describes its purpose

---

`149-152`: **Improved error handling with thread safety**

Using SafeInvoke for MessageBox display ensures that UI operations occur on the UI thread, preventing cross-thread exceptions.

---

`199-199`: <details>
<summary>❓ Verification inconclusive</summary>

**Good use of configuration values**

Moving hardcoded URLs and prefixes to configuration settings improves maintainability and flexibility. This allows changing these values without recompiling the application.





Also applies to: 249-249, 277-277

---

🏁 Script executed:

```shell
#!/bin/bash
# Check if app.config exists and contains the required settings

# Find app.config or similar configuration files
fd -e config -e xml App.config app.config --exec cat {} | grep -E "RepositoryUrl|CopilotUrl|ResourceServerPrefix"
```

Length of output: 215

---



</details>

**Configuration Settings in Place – Please Manually Verify Configuration Files**

The update to use configuration values (e.g.,  
`ConfigurationManager.AppSettings["RepositoryUrl"]` at line 199, and similarly at lines 249 and 277) is a solid step toward enhanced maintainability. However, our automated search for configuration keys returned path errors (e.g., “app.config is not a directory”), so it couldn’t confirm that keys like `RepositoryUrl`, `CopilotUrl`, and `ResourceServerPrefix` are indeed present in the appropriate configuration file. Please verify manually that these keys exist (for example, in `App.config`) to ensure the runtime configuration is complete.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-31T05:32:48Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (2)</summary><blockquote>

<details>
<summary>WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs (2)</summary><blockquote>

`98-101`: **Method renamed with descriptive name, but implementation is incomplete**

Renaming button1_Click to btnRunFromExternalLink_Click improves code readability. However, the method only shows a "Coming soon...!" message and lacks actual implementation.

Consider adding a TODO comment to track this incomplete feature or implementing the actual functionality:

```diff
private void btnRunFromExternalLink_Click(object sender, EventArgs e)
{
-    MessageBox.Show("Coming soon...!");
+    // TODO: Implement external link functionality
+    MessageBox.Show("Coming soon...!", "Feature Not Implemented", 
+                   MessageBoxButtons.OK, MessageBoxIcon.Information);
}
```

---

`1-280`: **Consider implementing error handling for configuration values**

While using ConfigurationManager.AppSettings is a good practice, there's no error handling for missing or invalid configuration values.

Consider adding defensive checks for configuration values:

```diff
// Example implementation for line 199
private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
-    Program.OpenWebBrowser(ConfigurationManager.AppSettings["RepositoryUrl"]);
+    string repositoryUrl = ConfigurationManager.AppSettings["RepositoryUrl"];
+    if (string.IsNullOrEmpty(repositoryUrl))
+    {
+        MessageBox.Show("Repository URL is not configured in application settings.", 
+                       "Configuration Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+        return;
+    }
+    Program.OpenWebBrowser(repositoryUrl);
}

// Similar pattern can be applied to other ConfigurationManager.AppSettings usages
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 9a8ee4d7f957043d24e5f5aa4ce45a07c7983c2f and 40b0b704e39223c00072f9d697fc9b08d3a08e3d.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs` (7 hunks)
* `WelsonJS.Toolkit/WelsonJS.Launcher/app.config` (1 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* WelsonJS.Toolkit/WelsonJS.Launcher/app.config

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Analyze (javascript)

</details>

<details>
<summary>🔇 Additional comments (13)</summary><blockquote>

<details>
<summary>WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs (13)</summary>

`2-2`: **Good addition of ConfigurationManager reference**

Adding the System.Configuration namespace is necessary for accessing the AppSettings values later in the code. This change supports the migration from hardcoded values to configuration-based settings.

---

`66-73`: **Improved control naming for better code readability**

Renaming controls from generic names (button1, button2, etc.) to descriptive names (btnRunFromZipFile, btnRunFromExternalLink, etc.) significantly improves code readability and maintainability. The conditional check for enabling txtUseSpecificScript is also correctly implemented.

---

`79-83`: **Consistent control naming in DisableUI method**

The DisableUI method has been properly updated to match the renamed controls, maintaining consistency with the EnableUI method. This helps ensure proper UI state management.

---

`86-96`: **Good implementation of thread-safe UI updates**

The SafeInvoke method is a valuable addition that properly handles cross-thread UI operations, checking InvokeRequired before calling Invoke. This pattern helps prevent InvalidOperationExceptions when updating UI elements from background threads.

---

`103-117`: **Improved file dialog implementation with proper resource management**

The refactored btnRunFromZipFile_Click method now properly uses a using statement for the OpenFileDialog, ensuring resources are disposed properly. The filter setup with zip files as the default option is also a good practice.

---

`123-123`: **Updated reference to renamed control**

The code now correctly references txtUseSpecificScript.Text instead of the generic textBox1.Text, maintaining consistency with the renamed controls.

---

`145-145`: **Updated method call with renamed controls**

The call to Program.RunCommandPrompt has been updated to use the renamed controls, ensuring consistency throughout the codebase.

---

`149-153`: **Improved error handling with thread-safe UI updates**

Using SafeInvoke for displaying error messages ensures that UI operations are performed on the correct thread, preventing potential InvalidOperationExceptions.

---

`156-158`: **Thread-safe UI enabling using SafeInvoke**

The EnableUI method is now called using SafeInvoke, ensuring that UI updates occur on the UI thread. This is a good practice for thread safety.

---

`192-195`: **Updated event handler name and implementation**

The event handler has been renamed from checkBox1_CheckedChanged to cbUseSpecificScript_CheckedChanged, improving readability. The implementation correctly enables/disables the txtUseSpecificScript control based on the checkbox state.

---

`199-199`: **Replaced hardcoded URL with configuration setting**

Using ConfigurationManager.AppSettings["RepositoryUrl"] instead of a hardcoded URL improves maintainability and allows for configuration changes without recompiling the application.

---

`249-249`: **Using configuration for resource server prefix**

The code now initializes the resourceServer with the ResourceServerPrefix from configuration settings, which is more maintainable than using hardcoded values.

---

`275-278`: **Updated method name and URL source**

The method has been renamed to openCopilotToolStripMenuItem_Click (removing "Microsoft" from the name), and the URL is now loaded from ConfigurationManager.AppSettings["CopilotUrl"] instead of being hardcoded. These changes improve maintainability.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-31T06:10:02Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs (1)</summary><blockquote>

`97-100`: **User experience improvement needed for "Coming soon" feature.**

While the method name is now more descriptive, displaying just a "Coming soon" message isn't very informative. Consider adding more details about what feature is coming and when, or disable the button with an appropriate tooltip if the feature isn't ready.

```diff
-            MessageBox.Show("Coming soon...!");
+            MessageBox.Show("The ability to run WelsonJS from an external link will be available in a future update.", 
+                            "Feature Coming Soon", MessageBoxButtons.OK, MessageBoxIcon.Information);
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 40b0b704e39223c00072f9d697fc9b08d3a08e3d and 4372bdb09d3b1aee5fbc58a2f4bddd7fe315a7fa.

</details>

<details>
<summary>📒 Files selected for processing (5)</summary>

* `WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs` (6 hunks)
* `WelsonJS.Toolkit/WelsonJS.Launcher/Properties/Resources.Designer.cs` (2 hunks)
* `WelsonJS.Toolkit/WelsonJS.Launcher/Properties/Resources.resx` (1 hunks)
* `WelsonJS.Toolkit/WelsonJS.Launcher/app.config` (1 hunks)
* `bootstrap.bat` (1 hunks)

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (1)</summary>

* WelsonJS.Toolkit/WelsonJS.Launcher/app.config

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Analyze (javascript)

</details>

<details>
<summary>🔇 Additional comments (11)</summary><blockquote>

<details>
<summary>WelsonJS.Toolkit/WelsonJS.Launcher/Properties/Resources.resx (1)</summary>

`151-159`: <details>
<summary>❓ Verification inconclusive</summary>

**Good addition of configurable URLs as resources!**

Moving these URLs to resource strings improves maintainability and configuration flexibility. However, note that `ResourceServerPrefix` uses HTTP rather than HTTPS. While this may be acceptable for local development, consider using HTTPS for production environments to ensure secure communication.


---

🏁 Script executed:

```shell
#!/bin/bash
# Check if the ResourceServerPrefix URL is used in production contexts
rg -A 3 "ResourceServerPrefix" --type cs
```

Length of output: 1019

---



</details>

**Attention: Verify Production URL Security Configuration**

Great work on externalizing the URLs into resource files for better maintainability! The grep results confirm that `ResourceServerPrefix`—currently set to `http://localhost:3000`—is used in the production code (see usage in `MainForm.cs`). While this might be acceptable for local testing, please verify whether this HTTP URL is intentional for production or if it should be switched to HTTPS to ensure secure communication.

</details>
<details>
<summary>WelsonJS.Toolkit/WelsonJS.Launcher/Properties/Resources.Designer.cs (1)</summary>

`63-70`: **Properties correctly generated for the new resource strings.**

The auto-generated properties match the resources added to the .resx file, enabling strongly-typed access to these URLs throughout the application.



Also applies to: 172-188

</details>
<details>
<summary>bootstrap.bat (1)</summary>

`8-8`: <details>
<summary>✅ Verification successful</summary>

**Security improvement: SAS token removed from URL.**

Removing the SAS token from the TOOLKIT_URL is a security improvement since it prevents potentially sensitive credentials from being exposed in the script. However, verify that the blob storage resource is now publicly accessible or that authentication is handled differently.


---

🏁 Script executed:

```shell
#!/bin/bash
# Test if the toolkit URL is accessible without the SAS token
curl -sI "https://catswords.blob.core.windows.net/welsonjs/welsonjs_toolkit_latest.cab" | head -1
```

Length of output: 113

---



</details>

**Verified: Blob Storage is Publicly Accessible Without SAS Token**

- The execution of the verification script returned `HTTP/1.1 200 OK`, confirming that the TOOLKIT_URL is accessible without the SAS token.
- Removing the SAS token is indeed a security improvement as it prevents exposure of sensitive credentials.
- No further changes are required.

</details>
<details>
<summary>WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs (8)</summary>

`65-72`: **Improved control naming in UI management methods.**

Replacing generic control names (like button1) with descriptive names (like btnRunFromZipFile) significantly improves code readability and maintainability. This change aligns with standard naming conventions for UI controls.



Also applies to: 78-83

---

`85-95`: **Excellent addition of SafeInvoke method for thread-safe UI updates.**

This helper method properly encapsulates the thread-safety pattern for UI updates, reducing code duplication and potential threading bugs. The method ensures UI operations are performed on the UI thread by checking InvokeRequired first.

---

`102-116`: **Improved file dialog implementation with proper resource management.**

The updated method uses a `using` statement for proper resource disposal and adds appropriate filter settings for the dialog. This is a good practice that ensures resources are released even if exceptions occur.

---

`122-122`: **Control references updated to match renamed controls.**

The references to the controls have been properly updated throughout the code to match the renamed controls, ensuring consistency.



Also applies to: 144-144

---

`148-152`: **Enhanced error handling with thread-safe UI updates.**

Using SafeInvoke for displaying error messages ensures thread-safety when showing error dialogs. This prevents potential cross-thread operation exceptions.

---

`155-157`: **Consistent use of SafeInvoke for UI updates.**

The EnableUI call is now properly wrapped in SafeInvoke, ensuring consistent thread-safe behavior throughout the application.

---

`191-194`: **Method name updated to match control name.**

The event handler name has been updated to match the renamed checkbox control, improving code readability and maintainability.

---

`198-198`: **Hardcoded URLs replaced with resource strings.**

URLs are now retrieved from resources rather than being hardcoded, improving maintainability and allowing for easier configuration changes. This is a significant improvement in code organization.



Also applies to: 248-249, 276-276

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-31T08:05:42Z

Review comments:
diff_hunk: @@ -147,26 +149,26 @@
~        {
~            try
~            {
~                List<string> lines = new List<string>();
~
~                foreach (var variable in userVariables)
~                {
~                    // Escape double quotes in the value
~                    string value = variable.Value.Replace("\"", "\\\"");
~
~                    // Enclose the value in double quotes if it contains spaces
~                    if (value.Contains(" "))
~                    {
~                        value = $"\"{value}\"";
~                    }
~
~                    // Create the line in the format: KEY=VALUE
~                    string line = $"{variable.Key}={value}";
~                    lines.Add(line);
                 }
 
                 // Write lines to the file
-                File.WriteAllLines(tempFilePath, lines);
+                File.WriteAllLines(tempFilePath, lines, defaultEncoding);
path: WelsonJS.Toolkit/WelsonJS.Launcher/EnvForm.cs
user: login: sourcery-ai[bot]
body: **suggestion:** Explicitly specifying the encoding improves file handling consistency.

Using the defaultEncoding parameter for writing ensures consistency with file reading; it might help to audit similar file I/O calls elsewhere to maintain this approach uniformly.

Suggested implementation:

```csharp
File.ReadAllLines(tempFilePath, defaultEncoding)

```

Review the entire file (and potentially others) for similar File I/O operations.
For each occurrence, ensure that both writing and reading operations explicitly specify the same encoding (defaultEncoding) to maintain consistency.
created_at: 2025-03-31T05:29:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -77,53 +79,52 @@
             // btnOpenWithExplorer
             // 
             this.btnOpenWithExplorer.Image = global::WelsonJS.Launcher.Properties.Resources.icon_directory_32;
-            this.btnOpenWithExplorer.Location = new System.Drawing.Point(327, 364);
+            this.btnOpenWithExplorer.Location = new System.Drawing.Point(229, 243);
+            this.btnOpenWithExplorer.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
             this.btnOpenWithExplorer.Name = "btnOpenWithExplorer";
-            this.btnOpenWithExplorer.Size = new System.Drawing.Size(232, 60);
+            this.btnOpenWithExplorer.Size = new System.Drawing.Size(162, 40);
             this.btnOpenWithExplorer.TabIndex = 3;
             this.btnOpenWithExplorer.Text = "Open with Explorer";
             this.btnOpenWithExplorer.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
             this.btnOpenWithExplorer.UseVisualStyleBackColor = true;
             this.btnOpenWithExplorer.Click += new System.EventHandler(this.btnOpenWithExplorer_Click);
             // 
-            // checkBox2
-            // 
-            this.checkBox2.AutoSize = true;
-            this.checkBox2.Location = new System.Drawing.Point(15, 322);
-            this.checkBox2.Margin = new System.Windows.Forms.Padding(4);
-            this.checkBox2.Name = "checkBox2";
-            this.checkBox2.Size = new System.Drawing.Size(352, 22);
-            this.checkBox2.TabIndex = 9;
-            this.checkBox2.Text = "This is an Interactive Service Application";
-            this.checkBox2.UseVisualStyleBackColor = true;
-            // 
-            // textBox1
-            // 
-            this.textBox1.Enabled = false;
-            this.textBox1.Location = new System.Drawing.Point(284, 283);
-            this.textBox1.Margin = new System.Windows.Forms.Padding(4);
-            this.textBox1.Name = "textBox1";
-            this.textBox1.Size = new System.Drawing.Size(155, 28);
-            this.textBox1.TabIndex = 8;
-            // 
-            // checkBox1
-            // 
-            this.checkBox1.AutoSize = true;
-            this.checkBox1.Location = new System.Drawing.Point(15, 288);
-            this.checkBox1.Margin = new System.Windows.Forms.Padding(4);
-            this.checkBox1.Name = "checkBox1";
-            this.checkBox1.Size = new System.Drawing.Size(256, 22);
-            this.checkBox1.TabIndex = 7;
-            this.checkBox1.Text = "I want to use specific script ";
-            this.checkBox1.UseVisualStyleBackColor = true;
-            this.checkBox1.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged);
+            // cbInteractiveServiceApp
+            // 
+            this.cbInteractiveServiceApp.AutoSize = true;
+            this.cbInteractiveServiceApp.Location = new System.Drawing.Point(10, 215);
+            this.cbInteractiveServiceApp.Name = "cbInteractiveServiceApp";
+            this.cbInteractiveServiceApp.Size = new System.Drawing.Size(254, 16);
+            this.cbInteractiveServiceApp.TabIndex = 9;
+            this.cbInteractiveServiceApp.Text = "This is an Interactive Service Application";
+            this.cbInteractiveServiceApp.UseVisualStyleBackColor = true;
+            // 
+            // txtUseSpecificScript
+            // 
+            this.txtUseSpecificScript.Enabled = false;
+            this.txtUseSpecificScript.Location = new System.Drawing.Point(199, 189);
+            this.txtUseSpecificScript.Name = "txtUseSpecificScript";
+            this.txtUseSpecificScript.Size = new System.Drawing.Size(110, 21);
+            this.txtUseSpecificScript.TabIndex = 8;
+            // 
+            // cbUseSpecificScript
+            // 
+            this.cbUseSpecificScript.AutoSize = true;
+            this.cbUseSpecificScript.Location = new System.Drawing.Point(10, 192);
+            this.cbUseSpecificScript.Name = "cbUseSpecificScript";
+            this.cbUseSpecificScript.Size = new System.Drawing.Size(184, 16);
+            this.cbUseSpecificScript.TabIndex = 7;
+            this.cbUseSpecificScript.Text = "I want to use specific script ";
+            this.cbUseSpecificScript.UseVisualStyleBackColor = true;
+            this.cbUseSpecificScript.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged);
path: WelsonJS.Toolkit/WelsonJS.Launcher/InstancesForm.Designer.cs
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Event handler name doesn't match the control name.**

The event handler `checkBox1_CheckedChanged` still uses the old control naming convention while the control has been renamed to `cbUseSpecificScript`.

Apply this diff to update the event handler name for consistency:

```diff
-this.cbUseSpecificScript.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged);
+this.cbUseSpecificScript.CheckedChanged += new System.EventHandler(this.cbUseSpecificScript_CheckedChanged);
```

Don't forget to also rename the method implementation in the corresponding .cs file.


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
            this.cbUseSpecificScript.CheckedChanged += new System.EventHandler(this.cbUseSpecificScript_CheckedChanged);
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->

✅ Addressed in commit 9a8ee4d
created_at: 2025-03-31T05:32:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -41,39 +41,36 @@
             this.textSetName = new System.Windows.Forms.TextBox();
             this.labelSetValue = new System.Windows.Forms.Label();
             this.labelSetName = new System.Windows.Forms.Label();
-            this.groupBox3 = new System.Windows.Forms.GroupBox();
+            this.gbImportAndExport = new System.Windows.Forms.GroupBox();
             this.btnExport = new System.Windows.Forms.Button();
             this.btnImport = new System.Windows.Forms.Button();
-            this.groupBox1.SuspendLayout();
-            this.groupBox2.SuspendLayout();
-            this.groupBox3.SuspendLayout();
+            this.gbUserDefinedVariables.SuspendLayout();
+            this.gbUpdateUserDefinedVariable.SuspendLayout();
+            this.gbImportAndExport.SuspendLayout();
             this.SuspendLayout();
             // 
-            // groupBox1
+            // gbUserDefinedVariables
             // 
-            this.groupBox1.Controls.Add(this.listView1);
-            this.groupBox1.Location = new System.Drawing.Point(17, 18);
-            this.groupBox1.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
-            this.groupBox1.Name = "groupBox1";
-            this.groupBox1.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4);
-            this.groupBox1.Size = new System.Drawing.Size(599, 255);
-            this.groupBox1.TabIndex = 0;
-            this.groupBox1.TabStop = false;
-            this.groupBox1.Text = "User-defined variables";
+            this.gbUserDefinedVariables.Controls.Add(this.lvUserDefinedVariables);
+            this.gbUserDefinedVariables.Location = new System.Drawing.Point(12, 12);
+            this.gbUserDefinedVariables.Name = "gbUserDefinedVariables";
+            this.gbUserDefinedVariables.Size = new System.Drawing.Size(419, 170);
+            this.gbUserDefinedVariables.TabIndex = 0;
+            this.gbUserDefinedVariables.TabStop = false;
+            this.gbUserDefinedVariables.Text = "User-defined variables";
             // 
-            // listView1
+            // lvUserDefinedVariables
             // 
-            this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+            this.lvUserDefinedVariables.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
             this.columnHeader1,
             this.columnHeader2});
-            this.listView1.HideSelection = false;
-            this.listView1.Location = new System.Drawing.Point(23, 39);
-            this.listView1.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
-            this.listView1.Name = "listView1";
-            this.listView1.Size = new System.Drawing.Size(550, 192);
-            this.listView1.TabIndex = 0;
-            this.listView1.UseCompatibleStateImageBehavior = false;
-            this.listView1.SelectedIndexChanged += new System.EventHandler(this.ListView1_SelectedIndexChanged);
+            this.lvUserDefinedVariables.HideSelection = false;
+            this.lvUserDefinedVariables.Location = new System.Drawing.Point(16, 26);
+            this.lvUserDefinedVariables.Name = "lvUserDefinedVariables";
+            this.lvUserDefinedVariables.Size = new System.Drawing.Size(386, 129);
+            this.lvUserDefinedVariables.TabIndex = 0;
+            this.lvUserDefinedVariables.UseCompatibleStateImageBehavior = false;
+            this.lvUserDefinedVariables.SelectedIndexChanged += new System.EventHandler(this.ListView1_SelectedIndexChanged);
path: WelsonJS.Toolkit/WelsonJS.Launcher/EnvForm.Designer.cs
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Update event handler name to match control name**

The event handler name `ListView1_SelectedIndexChanged` still uses the old control name, while the control has been renamed to `lvUserDefinedVariables`.

```diff
-this.lvUserDefinedVariables.SelectedIndexChanged += new System.EventHandler(this.ListView1_SelectedIndexChanged);
+this.lvUserDefinedVariables.SelectedIndexChanged += new System.EventHandler(this.lvUserDefinedVariables_SelectedIndexChanged);
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
            this.lvUserDefinedVariables.SelectedIndexChanged += new System.EventHandler(this.lvUserDefinedVariables_SelectedIndexChanged);
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->

✅ Addressed in commit 9a8ee4d
created_at: 2025-03-31T05:32:46Z
author_association: CONTRIBUTOR

PR comments:
user: login: sourcery-ai[bot]
created_at: 2025-03-31T05:28:38Z
body: <!-- Generated by sourcery-ai[bot]: start review_guide -->

## Reviewer's Guide by Sourcery

This pull request focuses on improving the codebase by renaming UI elements for better clarity, updating UI dependencies to use a local Azure Blob Storage location with SRI hashes for enhanced security, and adding configuration settings for repository and copilot URLs.

#### Updated class diagram for InstancesForm

```mermaid
classDiagram
    class InstancesForm {
        -string entryFileName
        -string scriptName
        +InstancesForm()
        -void InitializeComponent()
        -void InstancesForm_Load(object sender, EventArgs e)
        -void LoadInstances(string instancesRoot)
        -void btnStart_Click(object sender, EventArgs e)
        -void btnDelete_Click(object sender, EventArgs e)
        -void btnOpenWithExplorer_Click(object sender, EventArgs e)
        -void checkBox1_CheckedChanged(object sender, EventArgs e)
    }
```

#### Updated class diagram for GlobalSettingsForm

```mermaid
classDiagram
    class GlobalSettingsForm {
        -string RegistryPath
        -string RegistryKey
        +GlobalSettingsForm()
        -void InitializeComponent()
        -void GlobalSettingsForm_Load(object sender, EventArgs e)
        -void LoadRegistryValue()
        -void btnOkMaxScriptStatements_Click(object sender, EventArgs e)
    }
```

### File-Level Changes

| Change | Details | Files |
| ------ | ------- | ----- |
| Renamed and reorganized UI elements in EnvForm for better clarity and consistency. | <ul><li>Renamed `groupBox1` to `gbUserDefinedVariables`.</li><li>Renamed `listView1` to `lvUserDefinedVariables`.</li><li>Renamed `groupBox2` to `gbUpdateUserDefinedVariable`.</li><li>Renamed `groupBox3` to `gbImportAndExport`.</li><li>Adjusted the layout and sizes of the UI elements to fit the new naming and structure.</li><li>Updated the padding and margin values for better visual appearance.</li></ul> | `WelsonJS.Toolkit/WelsonJS.Launcher/EnvForm.Designer.cs`<br/>`WelsonJS.Toolkit/WelsonJS.Launcher/EnvForm.cs` |
| Updated UI elements in MainForm for clarity and consistency. | <ul><li>Renamed `button1` to `btnRunFromZipFile`.</li><li>Renamed `button2` to `btnRunFromExternalLink`.</li><li>Renamed `checkBox1` to `cbUseSpecificScript`.</li><li>Renamed `textBox1` to `txtUseSpecificScript`.</li><li>Renamed `checkBox2` to `cbInteractiveServiceApp`.</li><li>Renamed `openMicrosoftCopilotToolStripMenuItem` to `openCopilotToolStripMenuItem`.</li><li>Updated event handlers to reflect the new naming.</li><li>Added `SafeInvoke` method to handle cross-thread UI updates safely.</li><li>Replaced hardcoded repository and copilot URLs with values from `app.config`.</li></ul> | `WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.Designer.cs`<br/>`WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.cs` |
| Updated UI elements in InstancesForm for clarity and consistency. | <ul><li>Renamed `listView1` to `lvInstances`.</li><li>Renamed `columnHeader1` to `chInstanceId`.</li><li>Renamed `columnHeader2` to `chFirstDeployTime`.</li><li>Renamed `checkBox1` to `cbUseSpecificScript`.</li><li>Renamed `textBox1` to `txtUseSpecificScript`.</li><li>Renamed `checkBox2` to `cbInteractiveServiceApp`.</li><li>Updated event handlers to reflect the new naming.</li></ul> | `WelsonJS.Toolkit/WelsonJS.Launcher/InstancesForm.Designer.cs`<br/>`WelsonJS.Toolkit/WelsonJS.Launcher/InstancesForm.cs` |
| Updated UI elements in GlobalSettingsForm for clarity and consistency. | <ul><li>Renamed `groupBox1` to `gbMaxScriptStatements`.</li><li>Renamed `textBox1` to `txtMaxScriptStatements`.</li><li>Renamed `button1` to `btnOkMaxScriptStatements`.</li><li>Updated event handlers to reflect the new naming.</li></ul> | `WelsonJS.Toolkit/WelsonJS.Launcher/GlobalSettingsForm.Designer.cs`<br/>`WelsonJS.Toolkit/WelsonJS.Launcher/GlobalSettingsForm.cs` |
| Updated Monaco Editor and Metro UI CSS/JS links to use a local Azure Blob Storage location with SRI hashes. | <ul><li>Updated Monaco Editor CSS link to use Azure Blob Storage with SRI hash.</li><li>Updated Metro UI CSS link to use Azure Blob Storage with SRI hash.</li><li>Updated Axios JS link to use Azure Blob Storage with SRI hash.</li><li>Updated fast-xml-parser JS link to use Azure Blob Storage with SRI hash.</li><li>Updated dompurify JS link to use Azure Blob Storage with SRI hash.</li><li>Updated Metro UI JS link to use Azure Blob Storage with SRI hash.</li><li>Updated Monaco Editor loader JS link to use Azure Blob Storage with SRI hash.</li><li>Updated Monaco Editor main JS link to use Azure Blob Storage with SRI hash.</li></ul> | `WelsonJS.Toolkit/WelsonJS.Launcher/editor.html` |
| Added configuration settings for repository and copilot URLs. | <ul><li>Added `RepositoryUrl` setting.</li><li>Added `CopilotUrl` setting.</li></ul> | `WelsonJS.Toolkit/WelsonJS.Launcher/app.config` |

---

<details>
<summary>Tips and commands</summary>

#### Interacting with Sourcery

- **Trigger a new review:** Comment `@sourcery-ai review` on the pull request.
- **Continue discussions:** Reply directly to Sourcery's review comments.
- **Generate a GitHub issue from a review comment:** Ask Sourcery to create an
  issue from a review comment by replying to it. You can also reply to a
  review comment with `@sourcery-ai issue` to create an issue from it.
- **Generate a pull request title:** Write `@sourcery-ai` anywhere in the pull
  request title to generate a title at any time. You can also comment
  `@sourcery-ai title` on the pull request to (re-)generate the title at any time.
- **Generate a pull request summary:** Write `@sourcery-ai summary` anywhere in
  the pull request body to generate a PR summary at any time exactly where you
  want it. You can also comment `@sourcery-ai summary` on the pull request to
  (re-)generate the summary at any time.
- **Generate reviewer's guide:** Comment `@sourcery-ai guide` on the pull
  request to (re-)generate the reviewer's guide at any time.
- **Resolve all Sourcery comments:** Comment `@sourcery-ai resolve` on the
  pull request to resolve all Sourcery comments. Useful if you've already
  addressed all the comments and don't want to see them anymore.
- **Dismiss all Sourcery reviews:** Comment `@sourcery-ai dismiss` on the pull
  request to dismiss all existing Sourcery reviews. Especially useful if you
  want to start fresh with a new review - don't forget to comment
  `@sourcery-ai review` to trigger a new review!
- **Generate a plan of action for an issue:** Comment `@sourcery-ai plan` on
  an issue to generate a plan of action for it.

#### Customizing Your Experience

Access your [dashboard](https://app.sourcery.ai) to:
- Enable or disable review features such as the Sourcery-generated pull request
  summary, the reviewer's guide, and others.
- Change the review language.
- Add, remove or edit custom review instructions.
- Adjust other review settings.

#### Getting Help

- [Contact our support team](mailto:support@sourcery.ai) for questions or feedback.
- Visit our [documentation](https://docs.sourcery.ai) for detailed guides and information.
- Keep in touch with the Sourcery team by following us on [X/Twitter](https://x.com/SourceryAI), [LinkedIn](https://www.linkedin.com/company/sourcery-ai/) or [GitHub](https://github.com/sourcery-ai).

</details>

<!-- Generated by sourcery-ai[bot]: end review_guide -->
author_association: CONTRIBUTOR
user: login: coderabbitai[bot]
created_at: 2025-03-31T05:28:44Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough
The pull request implements extensive UI refactoring and code clarifications across multiple forms. Several controls in designer files have been renamed for improved clarity while their layout properties have been adjusted, resulting in compact forms. In the code files, references to renamed UI elements are updated, and new fields—such as a default file encoding in file operations—are introduced. Additional improvements include enhanced registry value parsing, the introduction of a thread-safe UI update method (SafeInvoke), updated external resource URLs with integrity attributes, and a simplified bootstrap script that no longer relies on a SAS token.

## Changes

| Files | Change Summaries |
| --- | --- |
| EnvForm.Designer.cs, EnvForm.cs | Renamed UI controls (e.g., `groupBox1`→`gbUserDefinedVariables`, `listView1`→`lvUserDefinedVariables`), adjusted layout properties and client size, and introduced a new `defaultEncoding` field for file operations. |
| GlobalSettingsForm.Designer.cs, GlobalSettingsForm.cs | Renamed controls (e.g., `groupBox1`→`gbMaxScriptStatements`, `textBox1`→`txtMaxScriptStatements`, `button1`→`btnOkMaxScriptStatements`), updated event handler naming, and improved registry value parsing with enhanced error handling. |
| InstancesForm.Designer.cs, InstancesForm.cs | Renamed UI elements (e.g., `listView1`→`lvInstances`, column headers to `chInstanceId` and `chFirstDeployTime`), removed obsolete controls, added new checkboxes and textbox controls, and updated event handler names consistent with the new UI. |
| MainForm.Designer.cs, MainForm.cs | Renamed buttons, checkboxes, textboxes, and menu items; introduced the `SafeInvoke` method for thread-safe UI updates; overhauled file dialog integration and error handling; and updated URLs from configuration settings. |
| app.config, editor.html | Modified XML formatting for clarity and updated external resource URLs to use a new CDN with Subresource Integrity and crossorigin attributes. |
| Resources.Designer.cs, Resources.resx | Added new internal resource properties and corresponding data entries for `CopilotUrl`, `RepositoryUrl`, and `ResourceServerPrefix`. |
| bootstrap.bat | Removed the SAS token variable and simplified the `TOOLKIT_URL` definition by eliminating the query parameter for authentication. |

## Sequence Diagram(s)
```mermaid
sequenceDiagram
    participant U as User
    participant MF as MainForm
    participant UI as UI Thread

    U->>MF: Click btnRunFromExternalLink
    MF->>MF: Check InvokeRequired
    alt Invocation needed
        MF->>UI: SafeInvoke(Action)
        UI-->>MF: Action executed
    else No invocation needed
        MF->>MF: Execute action directly
    end
    MF->>U: Display "coming soon" message
```

## Possibly related PRs
- **gnh1201/welsonjs#150**: Introduces a new `EnvForm` class and updates its UI components, which is directly related to the renaming and reorganizing changes in the current PR.

## Poem
> I'm a busy rabbit, hopping through the code,  
> Renaming boxes and lists along my winding road.  
> With SafeInvoke, my UI runs smooth and bright,  
> New labels and layouts make everything just right.  
> Cheers from my soft paws—code blooms with delight! 🐰

<!-- walkthrough_end -->


---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 4372bdb09d3b1aee5fbc58a2f4bddd7fe315a7fa and 56ee12741cfaf184f7b046e2e9c1e42419c91f97.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `WelsonJS.Toolkit/WelsonJS.Launcher/Properties/Resources.Designer.cs` (2 hunks)
* `WelsonJS.Toolkit/WelsonJS.Launcher/Properties/Resources.resx` (1 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (2)</summary>

* WelsonJS.Toolkit/WelsonJS.Launcher/Properties/Resources.resx
* WelsonJS.Toolkit/WelsonJS.Launcher/Properties/Resources.Designer.cs

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (1)</summary>

* GitHub Check: Analyze (javascript)

</details>

</details>
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=gnh1201/welsonjs&utm_content=213):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai plan` to trigger planning for file edits and PR creation.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR
user: login: gnh1201
created_at: 2025-03-31T06:12:58Z
body: Fix #204 #206 #207 #208 #209 #210 #211 #212
Improve #185
author_association: OWNER
user: login: sonarqubecloud[bot]
created_at: 2025-03-31T08:14:02Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=gnh1201_welsonjs&pullRequest=213) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=gnh1201_welsonjs&pullRequest=213&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=gnh1201_welsonjs&pullRequest=213&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=gnh1201_welsonjs&pullRequest=213&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=gnh1201_welsonjs&pullRequest=213&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=gnh1201_welsonjs&pullRequest=213&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=gnh1201_welsonjs&pullRequest=213)


author_association: NONE