diff --git a/Netch/Forms/MainForm.Designer.cs b/Netch/Forms/MainForm.Designer.cs
index 952c9bc6..77b6a3c5 100644
--- a/Netch/Forms/MainForm.Designer.cs
+++ b/Netch/Forms/MainForm.Designer.cs
@@ -35,6 +35,7 @@
this.ImportServersFromClipboardToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.CreateProcessModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.CreateRouteTableRuleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ReloadModesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.SubscribeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ManageSubscribeLinksToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
@@ -49,6 +50,7 @@
this.UninstallServiceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.UninstallTapDriverToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.removeNetchFirewallRulesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.AttachConsoleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.HelpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.CheckForUpdatesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.fAQToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
@@ -90,7 +92,6 @@
this.ProfileTable = new System.Windows.Forms.TableLayoutPanel();
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
this.ButtomControlContainerControl = new System.Windows.Forms.ContainerControl();
- this.AttachConsoleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.MenuStrip.SuspendLayout();
this.ConfigurationGroupBox.SuspendLayout();
this.configLayoutPanel.SuspendLayout();
@@ -142,7 +143,7 @@
//
// ModeToolStripMenuItem
//
- this.ModeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {this.CreateProcessModeToolStripMenuItem, this.ReloadModesToolStripMenuItem});
+ this.ModeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {this.CreateProcessModeToolStripMenuItem, this.CreateRouteTableRuleToolStripMenuItem, this.ReloadModesToolStripMenuItem});
this.ModeToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
this.ModeToolStripMenuItem.Name = "ModeToolStripMenuItem";
this.ModeToolStripMenuItem.Size = new System.Drawing.Size(55, 21);
@@ -151,14 +152,21 @@
// CreateProcessModeToolStripMenuItem
//
this.CreateProcessModeToolStripMenuItem.Name = "CreateProcessModeToolStripMenuItem";
- this.CreateProcessModeToolStripMenuItem.Size = new System.Drawing.Size(202, 22);
+ this.CreateProcessModeToolStripMenuItem.Size = new System.Drawing.Size(217, 22);
this.CreateProcessModeToolStripMenuItem.Text = "Create Process Mode";
this.CreateProcessModeToolStripMenuItem.Click += new System.EventHandler(this.CreateProcessModeToolStripButton_Click);
//
+ // CreateRouteTableRuleToolStripMenuItem
+ //
+ this.CreateRouteTableRuleToolStripMenuItem.Name = "CreateRouteTableRuleToolStripMenuItem";
+ this.CreateRouteTableRuleToolStripMenuItem.Size = new System.Drawing.Size(217, 22);
+ this.CreateRouteTableRuleToolStripMenuItem.Text = "Create Route Table Rule";
+ this.CreateRouteTableRuleToolStripMenuItem.Click += new System.EventHandler(this.createRouteTableModeToolStripMenuItem_Click);
+ //
// ReloadModesToolStripMenuItem
//
this.ReloadModesToolStripMenuItem.Name = "ReloadModesToolStripMenuItem";
- this.ReloadModesToolStripMenuItem.Size = new System.Drawing.Size(202, 22);
+ this.ReloadModesToolStripMenuItem.Size = new System.Drawing.Size(217, 22);
this.ReloadModesToolStripMenuItem.Text = "Reload Modes";
this.ReloadModesToolStripMenuItem.Click += new System.EventHandler(this.ReloadModesToolStripMenuItem_Click);
//
@@ -260,6 +268,13 @@
this.removeNetchFirewallRulesToolStripMenuItem.Text = "Remove Netch Firewall Rules";
this.removeNetchFirewallRulesToolStripMenuItem.Click += new System.EventHandler(this.RemoveNetchFirewallRulesToolStripMenuItem_Click);
//
+ // AttachConsoleToolStripMenuItem
+ //
+ this.AttachConsoleToolStripMenuItem.Name = "AttachConsoleToolStripMenuItem";
+ this.AttachConsoleToolStripMenuItem.Size = new System.Drawing.Size(243, 22);
+ this.AttachConsoleToolStripMenuItem.Text = "Attach Console";
+ this.AttachConsoleToolStripMenuItem.Click += new System.EventHandler(this.AttachConsoleToolStripMenuItem_Click);
+ //
// HelpToolStripMenuItem
//
this.HelpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {this.CheckForUpdatesToolStripMenuItem, this.fAQToolStripMenuItem});
@@ -701,13 +716,6 @@
this.ButtomControlContainerControl.TabStop = false;
this.ButtomControlContainerControl.Text = "groupBox1";
//
- // AttachConsoleToolStripMenuItem
- //
- this.AttachConsoleToolStripMenuItem.Name = "AttachConsoleToolStripMenuItem";
- this.AttachConsoleToolStripMenuItem.Size = new System.Drawing.Size(243, 22);
- this.AttachConsoleToolStripMenuItem.Text = "Attach Console";
- this.AttachConsoleToolStripMenuItem.Click += new System.EventHandler(this.AttachConsoleToolStripMenuItem_Click);
- //
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
@@ -753,6 +761,8 @@
this.PerformLayout();
}
+ private System.Windows.Forms.ToolStripMenuItem CreateRouteTableRuleToolStripMenuItem;
+
private System.Windows.Forms.ToolStripMenuItem AttachConsoleToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem removeNetchFirewallRulesToolStripMenuItem;
diff --git a/Netch/Forms/MainForm.cs b/Netch/Forms/MainForm.cs
index 88d87f24..cc152e94 100644
--- a/Netch/Forms/MainForm.cs
+++ b/Netch/Forms/MainForm.cs
@@ -862,6 +862,12 @@ namespace Netch.Forms
new Process(mode).ShowDialog();
Show();
break;
+ case 1:
+ case 2:
+ Hide();
+ new Route(mode).ShowDialog();
+ Show();
+ break;
default:
Utils.Utils.Open(ModeHelper.GetFullPath(mode.RelativePath));
break;
@@ -1581,5 +1587,12 @@ namespace Netch.Forms
if (!NativeMethods.AttachConsole(-1))
NativeMethods.AllocConsole();
}
+
+ private void createRouteTableModeToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ Hide();
+ new Route().ShowDialog();
+ Show();
+ }
}
}
\ No newline at end of file
diff --git a/Netch/Forms/Mode/ModeEditorUtils.cs b/Netch/Forms/Mode/ModeEditorUtils.cs
new file mode 100644
index 00000000..a6cced32
--- /dev/null
+++ b/Netch/Forms/Mode/ModeEditorUtils.cs
@@ -0,0 +1,17 @@
+using System.IO;
+using System.Text;
+
+namespace Netch.Forms.Mode
+{
+ public static class ModeEditorUtils
+ {
+ public static string ToSafeFileName(string text)
+ {
+ var fileName = new StringBuilder(text);
+ foreach (var c in Path.GetInvalidFileNameChars())
+ fileName.Replace(c, '_');
+
+ return fileName.ToString();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Netch/Forms/Mode/Process.Designer.cs b/Netch/Forms/Mode/Process.Designer.cs
index bd19387e..55f87d44 100644
--- a/Netch/Forms/Mode/Process.Designer.cs
+++ b/Netch/Forms/Mode/Process.Designer.cs
@@ -80,7 +80,6 @@ namespace Netch.Forms.Mode
this.UseCustomFilenameBox.TabIndex = 9;
this.UseCustomFilenameBox.Text = "Use Custom Filename";
this.UseCustomFilenameBox.UseVisualStyleBackColor = true;
- this.UseCustomFilenameBox.CheckedChanged += new System.EventHandler(this.UseCustomFilenameBox_CheckedChanged);
//
// FilenameLabel
//
@@ -97,6 +96,7 @@ namespace Netch.Forms.Mode
this.FilenameTextBox.Name = "FilenameTextBox";
this.FilenameTextBox.Size = new System.Drawing.Size(250, 23);
this.FilenameTextBox.TabIndex = 5;
+ this.FilenameTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this.UseCustomFilenameBox, "Checked", true));;
//
// ScanButton
//
diff --git a/Netch/Forms/Mode/Process.cs b/Netch/Forms/Mode/Process.cs
index d41cb325..785aa566 100644
--- a/Netch/Forms/Mode/Process.cs
+++ b/Netch/Forms/Mode/Process.cs
@@ -6,6 +6,7 @@ using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.WindowsAPICodePack.Dialogs;
using Netch.Controllers;
+using Netch.Properties;
using Netch.Utils;
namespace Netch.Forms.Mode
@@ -21,35 +22,26 @@ namespace Netch.Forms.Mode
/// 编辑模式
///
/// 模式
- public Process(Models.Mode mode)
+ public Process(Models.Mode mode = null)
{
- if (mode.Type != 0)
- throw new Exception("请传入进程模式");
+ if ((mode?.Type ?? 0) is not 0)
+ throw new ArgumentOutOfRangeException();
InitializeComponent();
CheckForIllegalCrossThreadCalls = false;
- Text = "Edit Process Mode";
_mode = mode;
- RuleListBox.Items.AddRange(mode.Rule.ToArray());
+ if (mode != null)
+ {
+ Text = "Edit Process Mode";
- #region 禁用文件名更改
+ RemarkTextBox.TextChanged -= RemarkTextBox_TextChanged;
+ FilenameTextBox.Enabled = UseCustomFilenameBox.Enabled = false;
- RemarkTextBox.TextChanged -= RemarkTextBox_TextChanged;
- FilenameTextBox.Enabled = UseCustomFilenameBox.Enabled = false;
-
- #endregion
-
- FilenameTextBox.Text = mode.RelativePath;
- RemarkTextBox.Text = mode.Remark;
- }
-
- public Process()
- {
- InitializeComponent();
- CheckForIllegalCrossThreadCalls = false;
-
- FilenameTextBox.Enabled = false;
+ RemarkTextBox.Text = mode.Remark;
+ FilenameTextBox.Text = mode.RelativePath;
+ RuleListBox.Items.AddRange(mode.Rule.ToArray());
+ }
}
///
@@ -213,19 +205,9 @@ namespace Netch.Forms.Mode
{
if (!UseCustomFilenameBox.Checked)
{
- var invalidFileChars = Path.GetInvalidFileNameChars();
- var fileName = new StringBuilder(RemarkTextBox.Text);
- foreach (var c in invalidFileChars)
- fileName.Replace(c, '_');
-
- FilenameTextBox.Text = fileName.ToString();
+ FilenameTextBox.Text = ModeEditorUtils.ToSafeFileName(RemarkTextBox.Text);
}
});
}
-
- private void UseCustomFilenameBox_CheckedChanged(object sender, EventArgs e)
- {
- FilenameTextBox.Enabled = UseCustomFilenameBox.Checked;
- }
}
}
\ No newline at end of file
diff --git a/Netch/Forms/Mode/Route.cs b/Netch/Forms/Mode/Route.cs
new file mode 100644
index 00000000..3be2f30f
--- /dev/null
+++ b/Netch/Forms/Mode/Route.cs
@@ -0,0 +1,128 @@
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using Netch.Properties;
+using Netch.Utils;
+
+namespace Netch.Forms.Mode
+{
+ public partial class Route : Form
+ {
+ class Item
+ {
+ private string _text;
+
+ public Item(int value, string text)
+ {
+ Text = text;
+ Value = value;
+ }
+
+ public string Text
+ {
+ get => i18N.Translate(_text);
+ set => _text = value;
+ }
+
+ public int Value { get; set; }
+ }
+
+ private Item[] _items = {new(1, "Proxy Rule IPs"), new(2, "Bypass Rule IPs")};
+
+ private readonly Models.Mode _mode;
+
+ public Route(Models.Mode mode = null)
+ {
+ if ((mode?.Type ?? 1) is not (1 or 2))
+ throw new ArgumentOutOfRangeException();
+
+ _mode = mode;
+
+ InitializeComponent();
+ comboBox1.DataSource = _items;
+ comboBox1.ValueMember = "Value";
+ comboBox1.DisplayMember = "Text";
+
+ i18N.TranslateForm(this);
+ }
+
+ private void Route_Load(object sender, EventArgs e)
+ {
+ if (_mode != null)
+ {
+ Text = "Edit Route Table Rule";
+
+ RemarkTextBox.TextChanged -= RemarkTextBox_TextChanged;
+ FilenameTextBox.Enabled = UseCustomFilenameBox.Enabled = false;
+
+ RemarkTextBox.Text = _mode.Remark;
+ comboBox1.SelectedValue = _mode.Type; // ComboBox SelectedValue worked after ctor
+ FilenameTextBox.Text = _mode.RelativePath;
+ richTextBox1.Lines = _mode.Rule.ToArray();
+ }
+ }
+
+ private void ControlButton_Click(object sender, EventArgs e)
+ {
+ if (string.IsNullOrWhiteSpace(RemarkTextBox.Text))
+ {
+ MessageBoxX.Show(i18N.Translate("Please enter a mode remark"));
+ return;
+ }
+
+ if (string.IsNullOrWhiteSpace(FilenameTextBox.Text))
+ {
+ MessageBoxX.Show(i18N.Translate("Please enter a mode filename"));
+ return;
+ }
+
+ if (_mode != null)
+ {
+ _mode.Remark = RemarkTextBox.Text;
+ _mode.Rule.Clear();
+ _mode.Rule.AddRange(richTextBox1.Lines);
+ _mode.Type = (int) comboBox1.SelectedValue;
+
+ _mode.WriteFile();
+ Global.MainForm.LoadModes();
+ MessageBoxX.Show(i18N.Translate("Mode updated successfully"));
+ }
+ else
+ {
+ var relativePath = $"Custom\\{FilenameTextBox.Text}.txt";
+ var fullName = ModeHelper.GetFullPath(relativePath);
+ if (File.Exists(fullName))
+ {
+ MessageBoxX.Show(i18N.Translate("File already exists.\n Please Change the filename"));
+ return;
+ }
+
+ var mode = new Models.Mode(fullName)
+ {
+ Type = (int) comboBox1.SelectedValue,
+ Remark = RemarkTextBox.Text
+ };
+
+ mode.Rule.AddRange(richTextBox1.Lines);
+
+ mode.WriteFile();
+ ModeHelper.Add(mode);
+ MessageBoxX.Show(i18N.Translate("Mode added successfully"));
+ }
+
+ Close();
+ }
+
+ private async void RemarkTextBox_TextChanged(object sender, EventArgs e)
+ {
+ await Task.Run(() =>
+ {
+ if (!UseCustomFilenameBox.Checked)
+ {
+ FilenameTextBox.Text = ModeEditorUtils.ToSafeFileName(RemarkTextBox.Text);
+ }
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/Netch/Netch.csproj b/Netch/Netch.csproj
index 649709bc..e16f5b04 100644
--- a/Netch/Netch.csproj
+++ b/Netch/Netch.csproj
@@ -90,6 +90,9 @@
True
Settings.settings
+
+ Form
+
diff --git a/Netch/Resources/zh-CN b/Netch/Resources/zh-CN
index a9332306..c533ea78 100644
--- a/Netch/Resources/zh-CN
+++ b/Netch/Resources/zh-CN
@@ -41,6 +41,8 @@
"Download update failed": "下载更新错误",
"Create Process Mode": "创建进程模式",
"Edit Process Mode": "修改进程模式",
+ "Create Route Table Rule": "创建路由表规则",
+ "Edit Route Table Rule": "修改路由表规则",
"Address": "地址",
"Username": "用户名",
@@ -140,6 +142,10 @@
"Please enter a mode remark": "请输入模式的备注",
"File already exists.\n Please Change the filename": "文件名已存在,请修改文件名",
"Please enter a mode filename": "请输入模式的文件名",
+
+ "Proxy Rule IPs": "代理规则 IP",
+ "Bypass Rule IPs": "绕过规则 IP",
+
"Link": "链接",
"Use Selected Server To Update Subscription": "使用选中的服务器更新订阅",