Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
33a0d9e7c2 | ||
|
|
939d600be1 | ||
|
|
a1e511915e | ||
|
|
94796110d5 | ||
|
|
5c3e2ab207 | ||
|
|
e66eb9759a | ||
|
|
b27ccfab17 | ||
|
|
87b3867095 | ||
|
|
3d1538264a | ||
|
|
0bffbbfb62 | ||
|
|
6ccbcae31f | ||
|
|
5a9d6e145d | ||
|
|
1b7eb6f6de | ||
|
|
62bfa25870 | ||
|
|
a1d481ba05 | ||
|
|
39abcb7d79 | ||
|
|
7c1df3786e | ||
|
|
fe11ee56ba | ||
|
|
4f38de4ee9 | ||
|
|
1aa32eaf3a | ||
|
|
4b3d6fb3bf | ||
|
|
12559d8192 | ||
|
|
bd71452206 | ||
|
|
10ba299f4d | ||
|
|
1ff9d1ec9d | ||
|
|
9cbb88c886 | ||
|
|
7e65ae0b6b | ||
|
|
41491f8c20 | ||
|
|
84b412bc8c | ||
|
|
7fef3dfe5c | ||
|
|
c139a82bdf | ||
|
|
97f6d601fb | ||
|
|
1ea0bb4096 | ||
|
|
7265bd2922 | ||
|
|
f316e13ada |
3
.github/dependabot.yml
vendored
@@ -26,8 +26,7 @@ updates:
|
||||
- package-ecosystem: "gitsubmodule"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
day: "monday"
|
||||
interval: "daily"
|
||||
time: "07:15"
|
||||
timezone: "Asia/Shanghai"
|
||||
labels:
|
||||
|
||||
@@ -166,6 +166,7 @@ namespace Netch.Controllers
|
||||
return;
|
||||
case State.Stopped:
|
||||
Stop();
|
||||
CloseLogFile();
|
||||
OnKeywordStopped();
|
||||
throw new MessageException($"{Name} 控制器启动失败");
|
||||
}
|
||||
@@ -180,6 +181,9 @@ namespace Netch.Controllers
|
||||
|
||||
private void OpenLogFile()
|
||||
{
|
||||
if (!RedirectToFile)
|
||||
return;
|
||||
|
||||
_logFileStream = File.Open(LogPath, FileMode.Create, FileAccess.ReadWrite, FileShare.Read);
|
||||
_logStreamWriter = new StreamWriter(_logFileStream);
|
||||
|
||||
@@ -201,8 +205,8 @@ namespace Netch.Controllers
|
||||
return;
|
||||
|
||||
_flushFileStreamTimer.Enabled = false;
|
||||
_logStreamWriter!.Close();
|
||||
_logFileStream!.Close();
|
||||
_logStreamWriter?.Close();
|
||||
_logFileStream?.Close();
|
||||
_logStreamWriter = _logStreamWriter = null;
|
||||
}
|
||||
|
||||
@@ -234,8 +238,8 @@ namespace Netch.Controllers
|
||||
string? line;
|
||||
while ((line = reader.ReadLine()) != null)
|
||||
{
|
||||
OnReadNewLine(line);
|
||||
WriteLog(line);
|
||||
OnReadNewLine(line);
|
||||
|
||||
// State == State.Started if !StartedKeywords.Any()
|
||||
if (State == State.Starting)
|
||||
@@ -247,8 +251,8 @@ namespace Netch.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
State = State.Stopped;
|
||||
CloseLogFile();
|
||||
State = State.Stopped;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Netch.Controllers
|
||||
Global.Settings.Pac_Port = PortHelper.GetAvailablePort();
|
||||
}
|
||||
|
||||
pacUrl = PACServerHandle.InitPACServer("127.0.0.1");
|
||||
pacUrl = PACServerHandle.InitPACServer();
|
||||
}
|
||||
|
||||
if (mode.Type is 3)
|
||||
@@ -76,7 +76,14 @@ namespace Netch.Controllers
|
||||
if (_oldState != null)
|
||||
{
|
||||
using var service = new ProxyService();
|
||||
service.Set(_oldState!);
|
||||
if (_oldState.IsProxy && _oldState.ProxyServer == service.Query().ProxyServer ||
|
||||
_oldState.IsAutoProxyUrl && _oldState.AutoConfigUrl!.StartsWith(PACServerHandle.PacPrefix))
|
||||
{
|
||||
service.Direct();
|
||||
return;
|
||||
}
|
||||
|
||||
service.Set(_oldState);
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
@@ -49,7 +49,12 @@ namespace Netch.Controllers
|
||||
/// <param name="mode">模式</param>
|
||||
/// <returns>是否启动成功</returns>
|
||||
/// <exception cref="MessageException"></exception>
|
||||
public static async Task Start(Server server, Mode mode)
|
||||
public static async Task StartAsync(Server server, Mode mode)
|
||||
{
|
||||
await Task.Run(() => Start(server, mode));
|
||||
}
|
||||
|
||||
public static void Start(Server server, Mode mode)
|
||||
{
|
||||
Logging.Info($"启动主控制器: {server.Type} [{mode.Type}]{mode.Remark}");
|
||||
Server = server;
|
||||
@@ -71,23 +76,15 @@ namespace Netch.Controllers
|
||||
{
|
||||
if (!ModeHelper.SkipServerController(server, mode))
|
||||
{
|
||||
await Task.Run(() => StartServer(server, mode, out _serverController));
|
||||
|
||||
StartServer(server, mode, out _serverController);
|
||||
StatusPortInfoText.UpdateShareLan();
|
||||
}
|
||||
|
||||
await Task.Run(() => StartMode(mode));
|
||||
StartMode(mode);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Stop();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
Stop();
|
||||
|
||||
switch (e)
|
||||
{
|
||||
@@ -151,10 +148,15 @@ namespace Netch.Controllers
|
||||
Global.Job.AddProcess(guard.Instance!);
|
||||
}
|
||||
|
||||
public static async Task StopAsync()
|
||||
{
|
||||
await Task.Run(Stop);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止
|
||||
/// </summary>
|
||||
public static async Task Stop()
|
||||
public static void Stop()
|
||||
{
|
||||
if (_serverController == null && ModeController == null)
|
||||
return;
|
||||
@@ -169,7 +171,16 @@ namespace Netch.Controllers
|
||||
Task.Run(() => ModeController?.Stop())
|
||||
};
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
try
|
||||
{
|
||||
Task.WaitAll(tasks);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Error(e.ToString());
|
||||
Utils.Utils.Open(Logging.LogFile);
|
||||
}
|
||||
|
||||
ModeController = null;
|
||||
ServerController = null;
|
||||
}
|
||||
|
||||
@@ -20,24 +20,17 @@ namespace Netch.Controllers
|
||||
private static readonly string BinDriver;
|
||||
private static readonly string SystemDriver = $"{Environment.SystemDirectory}\\drivers\\netfilter2.sys";
|
||||
|
||||
private static string? _sysDns;
|
||||
private OutboundAdapter? _outbound;
|
||||
|
||||
static NFController()
|
||||
{
|
||||
string fileName;
|
||||
switch ($"{Environment.OSVersion.Version.Major}.{Environment.OSVersion.Version.Minor}")
|
||||
{
|
||||
case "10.0":
|
||||
fileName = "Win-10.sys";
|
||||
break;
|
||||
case "6.3":
|
||||
case "6.2":
|
||||
fileName = "Win-8.sys";
|
||||
break;
|
||||
case "6.1":
|
||||
case "6.0":
|
||||
fileName = "Win-7.sys";
|
||||
fileName = "nfdriver.sys";
|
||||
break;
|
||||
default:
|
||||
throw new MessageException($"不支持的系统版本:{Environment.OSVersion.Version}");
|
||||
@@ -54,11 +47,11 @@ namespace Netch.Controllers
|
||||
|
||||
#region aio_dial
|
||||
|
||||
aio_dial((int) NameList.TYPE_FILTERLOOPBACK, "false");
|
||||
aio_dial((int) NameList.TYPE_TCPLISN, Global.Settings.RedirectorTCPPort.ToString());
|
||||
aio_dial((int)NameList.TYPE_FILTERLOOPBACK, "false");
|
||||
aio_dial((int)NameList.TYPE_TCPLISN, Global.Settings.RedirectorTCPPort.ToString());
|
||||
|
||||
aio_dial((int) NameList.TYPE_FILTERUDP, (Global.Settings.ProcessProxyProtocol != PortType.TCP).ToString().ToLower());
|
||||
aio_dial((int) NameList.TYPE_FILTERTCP, (Global.Settings.ProcessProxyProtocol != PortType.UDP).ToString().ToLower());
|
||||
aio_dial((int)NameList.TYPE_FILTERUDP, (Global.Settings.ProcessProxyProtocol != PortType.TCP).ToString().ToLower());
|
||||
aio_dial((int)NameList.TYPE_FILTERTCP, (Global.Settings.ProcessProxyProtocol != PortType.UDP).ToString().ToLower());
|
||||
SetServer(Global.Settings.ProcessProxyProtocol);
|
||||
|
||||
if (!CheckRule(mode.FullRule, out var list))
|
||||
@@ -68,16 +61,13 @@ namespace Netch.Controllers
|
||||
|
||||
#endregion
|
||||
|
||||
if (Global.Settings.ModifySystemDNS)
|
||||
{
|
||||
_outbound = new OutboundAdapter();
|
||||
// 备份并替换系统 DNS
|
||||
_sysDns = _outbound.DNS;
|
||||
if (string.IsNullOrWhiteSpace(Global.Settings.ModifiedDNS))
|
||||
Global.Settings.ModifiedDNS = "1.1.1.1,8.8.8.8";
|
||||
if (Global.Settings.RedirectDNS)
|
||||
aio_dial((int)NameList.TYPE_REDIRCTOR_DNS, Global.Settings.RedirectDNSAddr.ToString());
|
||||
|
||||
_outbound.DNS = Global.Settings.ModifiedDNS;
|
||||
}
|
||||
if (Global.Settings.RedirectICMP)
|
||||
aio_dial((int)NameList.TYPE_REDIRCTOR_ICMP, Global.Settings.RedirectICMPAddr.ToString());
|
||||
|
||||
aio_dial((int)NameList.TYPE_FILTERCHILDPROC, Global.Settings.ChildProcessHandle.ToString());
|
||||
|
||||
if (!aio_init())
|
||||
throw new MessageException("Redirector Start failed, run Netch with \"-console\" argument");
|
||||
@@ -85,13 +75,6 @@ namespace Netch.Controllers
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
if (Global.Settings.ModifySystemDNS)
|
||||
//恢复系统DNS
|
||||
_outbound!.DNS = _sysDns!;
|
||||
});
|
||||
|
||||
aio_free();
|
||||
}
|
||||
|
||||
@@ -103,7 +86,7 @@ namespace Netch.Controllers
|
||||
public static bool CheckRule(IEnumerable<string> rules, out IEnumerable<string> incompatibleRule)
|
||||
{
|
||||
incompatibleRule = rules.Where(r => !CheckCppRegex(r, false));
|
||||
aio_dial((int) NameList.TYPE_CLRNAME, "");
|
||||
aio_dial((int)NameList.TYPE_CLRNAME, "");
|
||||
return !incompatibleRule.Any();
|
||||
}
|
||||
|
||||
@@ -117,14 +100,14 @@ namespace Netch.Controllers
|
||||
try
|
||||
{
|
||||
if (r.StartsWith("!"))
|
||||
return aio_dial((int) NameList.TYPE_ADDNAME, r.Substring(1));
|
||||
return aio_dial((int)NameList.TYPE_ADDNAME, r.Substring(1));
|
||||
|
||||
return aio_dial((int) NameList.TYPE_ADDNAME, r);
|
||||
return aio_dial((int)NameList.TYPE_ADDNAME, r);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (clear)
|
||||
aio_dial((int) NameList.TYPE_CLRNAME, "");
|
||||
aio_dial((int)NameList.TYPE_CLRNAME, "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,50 +177,50 @@ namespace Netch.Controllers
|
||||
|
||||
if (server is Socks5 socks5)
|
||||
{
|
||||
aio_dial((int) NameList.TYPE_TCPTYPE + offset, "Socks5");
|
||||
aio_dial((int) NameList.TYPE_TCPHOST + offset, $"{socks5.AutoResolveHostname()}:{socks5.Port}");
|
||||
aio_dial((int) NameList.TYPE_TCPUSER + offset, socks5.Username ?? string.Empty);
|
||||
aio_dial((int) NameList.TYPE_TCPPASS + offset, socks5.Password ?? string.Empty);
|
||||
aio_dial((int) NameList.TYPE_TCPMETH + offset, string.Empty);
|
||||
aio_dial((int)NameList.TYPE_TCPTYPE + offset, "Socks5");
|
||||
aio_dial((int)NameList.TYPE_TCPHOST + offset, $"{socks5.AutoResolveHostname()}:{socks5.Port}");
|
||||
aio_dial((int)NameList.TYPE_TCPUSER + offset, socks5.Username ?? string.Empty);
|
||||
aio_dial((int)NameList.TYPE_TCPPASS + offset, socks5.Password ?? string.Empty);
|
||||
aio_dial((int)NameList.TYPE_TCPMETH + offset, string.Empty);
|
||||
}
|
||||
else if (server is Shadowsocks shadowsocks && !shadowsocks.HasPlugin() && Global.Settings.RedirectorSS)
|
||||
{
|
||||
aio_dial((int) NameList.TYPE_TCPTYPE + offset, "Shadowsocks");
|
||||
aio_dial((int) NameList.TYPE_TCPHOST + offset, $"{shadowsocks.AutoResolveHostname()}:{shadowsocks.Port}");
|
||||
aio_dial((int) NameList.TYPE_TCPMETH + offset, shadowsocks.EncryptMethod ?? string.Empty);
|
||||
aio_dial((int) NameList.TYPE_TCPPASS + offset, shadowsocks.Password ?? string.Empty);
|
||||
aio_dial((int)NameList.TYPE_TCPTYPE + offset, "Shadowsocks");
|
||||
aio_dial((int)NameList.TYPE_TCPHOST + offset, $"{shadowsocks.AutoResolveHostname()}:{shadowsocks.Port}");
|
||||
aio_dial((int)NameList.TYPE_TCPMETH + offset, shadowsocks.EncryptMethod ?? string.Empty);
|
||||
aio_dial((int)NameList.TYPE_TCPPASS + offset, shadowsocks.Password ?? string.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
aio_dial((int) NameList.TYPE_TCPTYPE + offset, "Socks5");
|
||||
aio_dial((int) NameList.TYPE_TCPHOST + offset, $"127.0.0.1:{controller.Socks5LocalPort()}");
|
||||
aio_dial((int) NameList.TYPE_TCPUSER + offset, string.Empty);
|
||||
aio_dial((int) NameList.TYPE_TCPPASS + offset, string.Empty);
|
||||
aio_dial((int) NameList.TYPE_TCPMETH + offset, string.Empty);
|
||||
aio_dial((int)NameList.TYPE_TCPTYPE + offset, "Socks5");
|
||||
aio_dial((int)NameList.TYPE_TCPHOST + offset, $"127.0.0.1:{controller.Socks5LocalPort()}");
|
||||
aio_dial((int)NameList.TYPE_TCPUSER + offset, string.Empty);
|
||||
aio_dial((int)NameList.TYPE_TCPPASS + offset, string.Empty);
|
||||
aio_dial((int)NameList.TYPE_TCPMETH + offset, string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetName(Mode mode)
|
||||
{
|
||||
aio_dial((int) NameList.TYPE_CLRNAME, "");
|
||||
aio_dial((int)NameList.TYPE_CLRNAME, "");
|
||||
foreach (var rule in mode.FullRule)
|
||||
{
|
||||
if (rule.StartsWith("!"))
|
||||
{
|
||||
aio_dial((int) NameList.TYPE_BYPNAME, rule.Substring(1));
|
||||
aio_dial((int)NameList.TYPE_BYPNAME, rule.Substring(1));
|
||||
continue;
|
||||
}
|
||||
|
||||
aio_dial((int) NameList.TYPE_ADDNAME, rule);
|
||||
aio_dial((int)NameList.TYPE_ADDNAME, rule);
|
||||
}
|
||||
|
||||
aio_dial((int) NameList.TYPE_ADDNAME, @"NTT\.exe");
|
||||
aio_dial((int) NameList.TYPE_BYPNAME, "^" + Global.NetchDir.ToRegexString() + @"((?!NTT\.exe).)*$");
|
||||
aio_dial((int)NameList.TYPE_ADDNAME, @"NTT\.exe");
|
||||
aio_dial((int)NameList.TYPE_BYPNAME, "^" + Global.NetchDir.ToRegexString() + @"((?!NTT\.exe).)*$");
|
||||
}
|
||||
|
||||
#region NativeMethods
|
||||
|
||||
private const int UdpNameListOffset = (int) NameList.TYPE_UDPTYPE - (int) NameList.TYPE_TCPTYPE;
|
||||
private const int UdpNameListOffset = (int)NameList.TYPE_UDPTYPE - (int)NameList.TYPE_TCPTYPE;
|
||||
|
||||
[DllImport("Redirector.bin", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern bool aio_dial(int name, [MarshalAs(UnmanagedType.LPWStr)] string value);
|
||||
@@ -256,23 +239,37 @@ namespace Netch.Controllers
|
||||
|
||||
public enum NameList
|
||||
{
|
||||
//bool
|
||||
TYPE_FILTERLOOPBACK,
|
||||
TYPE_FILTERTCP,
|
||||
TYPE_FILTERUDP,
|
||||
TYPE_FILTERIP,
|
||||
TYPE_FILTERCHILDPROC,//子进程捕获
|
||||
|
||||
TYPE_TCPLISN,
|
||||
TYPE_TCPTYPE,
|
||||
TYPE_TCPHOST,
|
||||
TYPE_TCPUSER,
|
||||
TYPE_TCPPASS,
|
||||
TYPE_TCPMETH,
|
||||
|
||||
TYPE_UDPTYPE,
|
||||
TYPE_UDPHOST,
|
||||
TYPE_UDPUSER,
|
||||
TYPE_UDPPASS,
|
||||
TYPE_UDPMETH,
|
||||
|
||||
TYPE_ADDNAME,
|
||||
TYPE_ADDFIP,
|
||||
|
||||
TYPE_BYPNAME,
|
||||
TYPE_CLRNAME
|
||||
|
||||
TYPE_CLRNAME,
|
||||
TYPE_CLRFIP,
|
||||
|
||||
//str addr x.x.x.x only ipv4
|
||||
TYPE_REDIRCTOR_DNS,
|
||||
TYPE_REDIRCTOR_ICMP
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Forms;
|
||||
using Netch.Models;
|
||||
using Netch.Servers.Socks5;
|
||||
|
||||
namespace Netch.Controllers
|
||||
{
|
||||
@@ -22,31 +23,37 @@ namespace Netch.Controllers
|
||||
|
||||
protected override Encoding? InstanceOutputEncoding { get; } = Encoding.UTF8;
|
||||
|
||||
public PcapController()
|
||||
{
|
||||
RedirectToFile = false;
|
||||
}
|
||||
|
||||
private LogForm? _form;
|
||||
|
||||
public void Start(in Mode mode)
|
||||
{
|
||||
Global.MainForm.BeginInvoke(new Action(() =>
|
||||
{
|
||||
_form = new LogForm(Global.MainForm);
|
||||
_form.Show();
|
||||
}));
|
||||
var server = MainController.Server!;
|
||||
|
||||
StartInstanceAuto($@"-i \Device\NPF_{_outbound.NetworkInterface.Id} {mode.FullRule.FirstOrDefault() ?? "-P n"}");
|
||||
_form = new LogForm(Global.MainForm);
|
||||
_form.CreateControl();
|
||||
|
||||
var argument = new StringBuilder($@"-i \Device\NPF_{_outbound.NetworkInterface.Id}");
|
||||
if (server is Socks5 socks5 && !socks5.Auth())
|
||||
argument.Append($" --destination {server.AutoResolveHostname()}:{server.Port}");
|
||||
else
|
||||
argument.Append($" --destination 127.0.0.1:{Global.Settings.Socks5LocalPort}");
|
||||
|
||||
argument.Append($" {mode.FullRule.FirstOrDefault() ?? "-P n"}");
|
||||
StartInstanceAuto(argument.ToString());
|
||||
}
|
||||
|
||||
protected override void OnReadNewLine(string line)
|
||||
{
|
||||
Global.MainForm.BeginInvoke(new Action(() => { _form!.richTextBox1.AppendText(line + "\n"); }));
|
||||
Global.MainForm.BeginInvoke(new Action(() =>
|
||||
{
|
||||
if (!_form!.IsDisposed)
|
||||
_form!.richTextBox1.AppendText(line + "\n");
|
||||
}));
|
||||
}
|
||||
|
||||
protected override void OnKeywordStarted()
|
||||
{
|
||||
Global.MainForm.BeginInvoke(new Action(() => { _form!.Show(); }));
|
||||
}
|
||||
|
||||
protected override void OnKeywordStopped()
|
||||
@@ -67,8 +74,7 @@ namespace Netch.Controllers
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
Global.MainForm.Invoke(new Action(() => { _form!.Close(); }));
|
||||
|
||||
_form!.Close();
|
||||
StopInstance();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Netch.Controllers
|
||||
public const string Name = @"Netch";
|
||||
public const string Copyright = @"Copyright © 2019 - 2021";
|
||||
|
||||
public const string AssemblyVersion = @"1.8.0";
|
||||
public const string AssemblyVersion = @"1.8.2";
|
||||
private const string Suffix = @"";
|
||||
|
||||
public static readonly string Version = $"{AssemblyVersion}{(string.IsNullOrEmpty(Suffix) ? "" : $"-{Suffix}")}";
|
||||
@@ -69,31 +69,25 @@ namespace Netch.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
public static bool GetFileNameAndHashFromMarkdownForm(in string text, out string fileName, out string sha256, string? keyword = null)
|
||||
public static void GetLatestUpdateFileNameAndHash(out string fileName, out string sha256, string? keyword = null)
|
||||
{
|
||||
IEnumerable<Match> matches;
|
||||
try
|
||||
{
|
||||
matches = Regex.Matches(text, @"^\| (?<filename>.*) \| (?<sha256>.*) \|\r?$", RegexOptions.Multiline).Cast<Match>().Skip(2);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Error(e.ToString());
|
||||
throw new Exception(i18N.Translate("Find update filename and hash failed"));
|
||||
}
|
||||
fileName = string.Empty;
|
||||
sha256 = string.Empty;
|
||||
|
||||
var matches = Regex.Matches(LatestRelease.body, @"^\| (?<filename>.*) \| (?<sha256>.*) \|\r?$", RegexOptions.Multiline)
|
||||
.Cast<Match>()
|
||||
.Skip(2);
|
||||
/*
|
||||
Skip(2)
|
||||
|
||||
| 文件名 | SHA256 |
|
||||
| :- | :- |
|
||||
*/
|
||||
|
||||
Match match = keyword == null ? matches.First() : matches.First(m => m.Groups["filename"].Value.Contains(keyword));
|
||||
|
||||
if (match != null)
|
||||
{
|
||||
fileName = match.Groups["filename"].Value;
|
||||
sha256 = match.Groups["sha256"].Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
fileName = string.Empty;
|
||||
sha256 = string.Empty;
|
||||
return false;
|
||||
fileName = match.Groups["filename"].Value;
|
||||
sha256 = match.Groups["sha256"].Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,9 +16,9 @@ namespace Netch.Forms
|
||||
_parent = parent;
|
||||
}
|
||||
|
||||
protected override void OnShown(EventArgs e)
|
||||
protected override void OnLoad(EventArgs e)
|
||||
{
|
||||
base.OnShown(e);
|
||||
base.OnLoad(e);
|
||||
Parent_Move(null!, null!);
|
||||
}
|
||||
|
||||
|
||||
@@ -85,8 +85,6 @@ namespace Netch.Forms
|
||||
|
||||
private void MainForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
OnlyInstance.Called += OnCalled;
|
||||
|
||||
// 计算 ComboBox绘制 目标宽度
|
||||
RecordSize();
|
||||
|
||||
@@ -106,10 +104,6 @@ namespace Netch.Forms
|
||||
// 加载快速配置
|
||||
LoadProfiles();
|
||||
|
||||
// 打开软件时启动加速,产生开始按钮点击事件
|
||||
if (Global.Settings.StartWhenOpened)
|
||||
ControlButton_Click(null, null);
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
// 检查更新
|
||||
@@ -117,11 +111,15 @@ namespace Netch.Forms
|
||||
CheckUpdate();
|
||||
});
|
||||
|
||||
Task.Run(async () =>
|
||||
Task.Run(() =>
|
||||
{
|
||||
// 检查订阅更新
|
||||
if (Global.Settings.UpdateServersWhenOpened)
|
||||
await UpdateServersFromSubscribe(Global.Settings.UseProxyToUpdateSubscription);
|
||||
UpdateServersFromSubscribe(Global.Settings.UseProxyToUpdateSubscription).Wait();
|
||||
|
||||
// 打开软件时启动加速,产生开始按钮点击事件
|
||||
if (Global.Settings.StartWhenOpened)
|
||||
ControlButton_Click(null, null);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -345,7 +343,7 @@ namespace Netch.Forms
|
||||
Type = 5
|
||||
};
|
||||
|
||||
await MainController.Start(server!, mode);
|
||||
await MainController.StartAsync(server!, mode);
|
||||
proxyServer = $"http://127.0.0.1:{Global.Settings.HTTPLocalPort}";
|
||||
}
|
||||
|
||||
@@ -363,14 +361,7 @@ namespace Netch.Forms
|
||||
finally
|
||||
{
|
||||
if (useProxy)
|
||||
try
|
||||
{
|
||||
await MainController.Stop();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
await MainController.StopAsync();
|
||||
|
||||
DisableItems(true);
|
||||
}
|
||||
@@ -386,19 +377,25 @@ namespace Netch.Forms
|
||||
{
|
||||
void OnNewVersionNotFound(object o, EventArgs args)
|
||||
{
|
||||
UpdateChecker.NewVersionNotFound -= OnNewVersionNotFound;
|
||||
NotifyTip(i18N.Translate("Already latest version"));
|
||||
}
|
||||
|
||||
void OnNewVersionFoundFailed(object o, EventArgs args)
|
||||
{
|
||||
UpdateChecker.NewVersionFoundFailed -= OnNewVersionFoundFailed;
|
||||
NotifyTip(i18N.Translate("New version found failed"), info: false);
|
||||
}
|
||||
|
||||
UpdateChecker.NewVersionNotFound += OnNewVersionNotFound;
|
||||
UpdateChecker.NewVersionFoundFailed += OnNewVersionFoundFailed;
|
||||
CheckUpdate();
|
||||
try
|
||||
{
|
||||
UpdateChecker.NewVersionNotFound += OnNewVersionNotFound;
|
||||
UpdateChecker.NewVersionFoundFailed += OnNewVersionFoundFailed;
|
||||
CheckUpdate();
|
||||
}
|
||||
finally
|
||||
{
|
||||
UpdateChecker.NewVersionNotFound -= OnNewVersionNotFound;
|
||||
UpdateChecker.NewVersionFoundFailed -= OnNewVersionFoundFailed;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -460,7 +457,7 @@ namespace Netch.Forms
|
||||
Type = 5
|
||||
};
|
||||
|
||||
await MainController.Start(server, mode);
|
||||
await MainController.StartAsync(server, mode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -479,7 +476,7 @@ namespace Netch.Forms
|
||||
finally
|
||||
{
|
||||
if (useProxy)
|
||||
await MainController.Stop();
|
||||
await MainController.StopAsync();
|
||||
|
||||
StatusText();
|
||||
Enabled = true;
|
||||
@@ -572,6 +569,47 @@ namespace Netch.Forms
|
||||
Utils.Utils.Open($"https://github.com/{UpdateChecker.Owner}/{UpdateChecker.Repo}/releases");
|
||||
}
|
||||
|
||||
private async void NewVersionLabel_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (ModifierKeys == Keys.Control || !UpdateChecker.LatestRelease!.assets.Any())
|
||||
{
|
||||
Utils.Utils.Open(UpdateChecker.LatestVersionUrl!);
|
||||
return;
|
||||
}
|
||||
|
||||
if (MessageBoxX.Show(i18N.Translate("Download and install now?"), confirm: true) != DialogResult.OK)
|
||||
return;
|
||||
|
||||
NotifyTip(i18N.Translate("Start downloading new version"));
|
||||
NewVersionLabel.Enabled = false;
|
||||
NewVersionLabel.Text = "...";
|
||||
|
||||
try
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
Updater.Updater.DownloadAndUpdate(Path.Combine(Global.NetchDir, "data"),
|
||||
Global.NetchDir,
|
||||
(_, args) => BeginInvoke(new Action(() => NewVersionLabel.Text = $"{args.ProgressPercentage}%")));
|
||||
});
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
if (exception is not MessageException)
|
||||
{
|
||||
Logging.Error($"更新失败: {exception}");
|
||||
Utils.Utils.Open(Logging.LogFile);
|
||||
}
|
||||
|
||||
NotifyTip(exception.Message, info: false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
NewVersionLabel.Visible = false;
|
||||
NewVersionLabel.Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void AboutToolStripButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
Hide();
|
||||
@@ -594,7 +632,7 @@ namespace Netch.Forms
|
||||
{
|
||||
// 停止
|
||||
State = State.Stopping;
|
||||
await MainController.Stop();
|
||||
await MainController.StopAsync();
|
||||
State = State.Stopped;
|
||||
return;
|
||||
}
|
||||
@@ -621,13 +659,13 @@ namespace Netch.Forms
|
||||
|
||||
try
|
||||
{
|
||||
await MainController.Start(server, mode);
|
||||
await MainController.StartAsync(server, mode);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
State = State.Stopped;
|
||||
StatusText(i18N.Translate("Start failed"));
|
||||
MessageBoxX.Show(exception.Message);
|
||||
MessageBoxX.Show(exception.Message, LogLevel.ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1362,27 +1400,12 @@ namespace Netch.Forms
|
||||
File.Delete(file);
|
||||
|
||||
if (!IsWaiting())
|
||||
await MainController.Stop();
|
||||
await MainController.StopAsync();
|
||||
|
||||
Dispose();
|
||||
Environment.Exit(Environment.ExitCode);
|
||||
}
|
||||
|
||||
private void OnCalled(object sender, OnlyInstance.Commands e)
|
||||
{
|
||||
switch (e)
|
||||
{
|
||||
case OnlyInstance.Commands.Show:
|
||||
NotifyIcon_MouseDoubleClick(null, null);
|
||||
break;
|
||||
case OnlyInstance.Commands.Exit:
|
||||
Exit(true);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(e), e, null);
|
||||
}
|
||||
}
|
||||
|
||||
#region FormClosingButton
|
||||
|
||||
private bool _isFirstCloseWindow = true;
|
||||
@@ -1409,43 +1432,22 @@ namespace Netch.Forms
|
||||
|
||||
private void CheckUpdate()
|
||||
{
|
||||
UpdateChecker.NewVersionFound += (_, _) =>
|
||||
{
|
||||
NotifyTip($"{i18N.Translate(@"New version available", ": ")}{UpdateChecker.LatestVersionNumber}");
|
||||
NewVersionLabel.Visible = true;
|
||||
};
|
||||
|
||||
UpdateChecker.Check(Global.Settings.CheckBetaUpdate).Wait();
|
||||
}
|
||||
|
||||
private async void NewVersionLabel_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (ModifierKeys == Keys.Control || !UpdateChecker.LatestRelease!.assets.Any())
|
||||
{
|
||||
Utils.Utils.Open(UpdateChecker.LatestVersionUrl!);
|
||||
return;
|
||||
}
|
||||
|
||||
if (MessageBoxX.Show(i18N.Translate("Download and install now?"), confirm: true) != DialogResult.OK)
|
||||
return;
|
||||
|
||||
NotifyTip(i18N.Translate("Start downloading new version"));
|
||||
|
||||
NewVersionLabel.Enabled = false;
|
||||
NewVersionLabel.Text = "...";
|
||||
try
|
||||
{
|
||||
void OnDownloadProgressChanged(object o1, DownloadProgressChangedEventArgs args)
|
||||
{
|
||||
BeginInvoke(new Action(() => { NewVersionLabel.Text = $"{args.ProgressPercentage}%"; }));
|
||||
}
|
||||
|
||||
await Updater.Updater.DownloadAndUpdate(Path.Combine(Global.NetchDir, "data"), Global.NetchDir, OnDownloadProgressChanged);
|
||||
UpdateChecker.NewVersionFound += OnUpdateCheckerOnNewVersionFound;
|
||||
UpdateChecker.Check(Global.Settings.CheckBetaUpdate).Wait();
|
||||
}
|
||||
catch (Exception exception)
|
||||
finally
|
||||
{
|
||||
Logging.Error(exception.Message);
|
||||
NotifyTip(exception.Message);
|
||||
UpdateChecker.NewVersionFound -= OnUpdateCheckerOnNewVersionFound;
|
||||
}
|
||||
|
||||
void OnUpdateCheckerOnNewVersionFound(object o, EventArgs eventArgs)
|
||||
{
|
||||
NotifyTip($"{i18N.Translate(@"New version available", ": ")}{UpdateChecker.LatestVersionNumber}");
|
||||
NewVersionLabel.Text = i18N.Translate("New version available");
|
||||
NewVersionLabel.Enabled = true;
|
||||
NewVersionLabel.Visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,5 +13,15 @@ namespace Netch.Forms.Mode
|
||||
|
||||
return fileName.ToString();
|
||||
}
|
||||
|
||||
public static string GetCustomModeRelativePath(string name)
|
||||
{
|
||||
if (name == string.Empty)
|
||||
return string.Empty;
|
||||
|
||||
var safeFileName = ToSafeFileName(name);
|
||||
var relativePath = $"Custom\\{safeFileName}.txt";
|
||||
return relativePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
183
Netch/Forms/Mode/Process.Designer.cs
generated
@@ -32,54 +32,58 @@ namespace Netch.Forms.Mode
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Process));
|
||||
this.ConfigurationGroupBox = new System.Windows.Forms.GroupBox();
|
||||
this.UseCustomFilenameBox = new System.Windows.Forms.CheckBox();
|
||||
this.RemarkLabel = new System.Windows.Forms.Label();
|
||||
this.RemarkTextBox = new System.Windows.Forms.TextBox();
|
||||
this.FilenameLabel = new System.Windows.Forms.Label();
|
||||
this.FilenameTextBox = new System.Windows.Forms.TextBox();
|
||||
this.ScanButton = new System.Windows.Forms.Button();
|
||||
this.ProcessGroupBox = new System.Windows.Forms.GroupBox();
|
||||
this.AddButton = new System.Windows.Forms.Button();
|
||||
this.ProcessNameTextBox = new System.Windows.Forms.TextBox();
|
||||
this.RuleListBox = new System.Windows.Forms.ListBox();
|
||||
this.RemarkTextBox = new System.Windows.Forms.TextBox();
|
||||
this.RemarkLabel = new System.Windows.Forms.Label();
|
||||
this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
this.ControlButton = new System.Windows.Forms.Button();
|
||||
this.DeleteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.containerControl1 = new System.Windows.Forms.ContainerControl();
|
||||
this.RuleListBox = new System.Windows.Forms.ListBox();
|
||||
this.ProcessGroupBox = new System.Windows.Forms.GroupBox();
|
||||
this.ProcessNameTextBox = new System.Windows.Forms.TextBox();
|
||||
this.AddButton = new System.Windows.Forms.Button();
|
||||
this.SelectButton = new System.Windows.Forms.Button();
|
||||
this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
this.DeleteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.ControlButton = new System.Windows.Forms.Button();
|
||||
this.ConfigurationGroupBox.SuspendLayout();
|
||||
this.containerControl1.SuspendLayout();
|
||||
this.ProcessGroupBox.SuspendLayout();
|
||||
this.contextMenuStrip.SuspendLayout();
|
||||
this.containerControl1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// ConfigurationGroupBox
|
||||
//
|
||||
this.ConfigurationGroupBox.Controls.Add(this.containerControl1);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.UseCustomFilenameBox);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.RemarkLabel);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.RemarkTextBox);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.FilenameLabel);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.FilenameTextBox);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.ScanButton);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.containerControl1);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.ProcessGroupBox);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.RemarkTextBox);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.RemarkLabel);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.SelectButton);
|
||||
this.ConfigurationGroupBox.Location = new System.Drawing.Point(12, 12);
|
||||
this.ConfigurationGroupBox.Name = "ConfigurationGroupBox";
|
||||
this.ConfigurationGroupBox.Size = new System.Drawing.Size(340, 344);
|
||||
this.ConfigurationGroupBox.TabIndex = 0;
|
||||
this.ConfigurationGroupBox.TabIndex = 1;
|
||||
this.ConfigurationGroupBox.TabStop = false;
|
||||
this.ConfigurationGroupBox.Text = "Configuration";
|
||||
//
|
||||
// UseCustomFilenameBox
|
||||
// RemarkLabel
|
||||
//
|
||||
this.UseCustomFilenameBox.AutoSize = true;
|
||||
this.UseCustomFilenameBox.Location = new System.Drawing.Point(84, 76);
|
||||
this.UseCustomFilenameBox.Name = "UseCustomFilenameBox";
|
||||
this.UseCustomFilenameBox.Size = new System.Drawing.Size(152, 21);
|
||||
this.UseCustomFilenameBox.TabIndex = 9;
|
||||
this.UseCustomFilenameBox.Text = "Use Custom Filename";
|
||||
this.UseCustomFilenameBox.UseVisualStyleBackColor = true;
|
||||
this.RemarkLabel.AutoSize = true;
|
||||
this.RemarkLabel.Location = new System.Drawing.Point(12, 25);
|
||||
this.RemarkLabel.Name = "RemarkLabel";
|
||||
this.RemarkLabel.Size = new System.Drawing.Size(53, 17);
|
||||
this.RemarkLabel.TabIndex = 0;
|
||||
this.RemarkLabel.Text = "Remark";
|
||||
//
|
||||
// RemarkTextBox
|
||||
//
|
||||
this.RemarkTextBox.Location = new System.Drawing.Point(84, 22);
|
||||
this.RemarkTextBox.Name = "RemarkTextBox";
|
||||
this.RemarkTextBox.Size = new System.Drawing.Size(250, 23);
|
||||
this.RemarkTextBox.TabIndex = 1;
|
||||
this.RemarkTextBox.TextChanged += new System.EventHandler(this.RemarkTextBox_TextChanged);
|
||||
//
|
||||
// FilenameLabel
|
||||
//
|
||||
@@ -87,37 +91,54 @@ namespace Netch.Forms.Mode
|
||||
this.FilenameLabel.Location = new System.Drawing.Point(12, 55);
|
||||
this.FilenameLabel.Name = "FilenameLabel";
|
||||
this.FilenameLabel.Size = new System.Drawing.Size(59, 17);
|
||||
this.FilenameLabel.TabIndex = 6;
|
||||
this.FilenameLabel.TabIndex = 2;
|
||||
this.FilenameLabel.Text = "Filename";
|
||||
//
|
||||
// FilenameTextBox
|
||||
//
|
||||
this.FilenameTextBox.Location = new System.Drawing.Point(84, 52);
|
||||
this.FilenameTextBox.Name = "FilenameTextBox";
|
||||
this.FilenameTextBox.ReadOnly = true;
|
||||
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));;
|
||||
this.FilenameTextBox.TabIndex = 3;
|
||||
//
|
||||
// ScanButton
|
||||
// containerControl1
|
||||
//
|
||||
this.ScanButton.Location = new System.Drawing.Point(6, 315);
|
||||
this.ScanButton.Name = "ScanButton";
|
||||
this.ScanButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.ScanButton.TabIndex = 4;
|
||||
this.ScanButton.Text = "Scan";
|
||||
this.ScanButton.UseVisualStyleBackColor = true;
|
||||
this.ScanButton.Click += new System.EventHandler(this.ScanButton_Click);
|
||||
this.containerControl1.Controls.Add(this.RuleListBox);
|
||||
this.containerControl1.Location = new System.Drawing.Point(6, 81);
|
||||
this.containerControl1.Name = "containerControl1";
|
||||
this.containerControl1.Size = new System.Drawing.Size(328, 176);
|
||||
this.containerControl1.TabIndex = 5;
|
||||
this.containerControl1.Text = "containerControl1";
|
||||
//
|
||||
// RuleListBox
|
||||
//
|
||||
this.RuleListBox.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.RuleListBox.FormattingEnabled = true;
|
||||
this.RuleListBox.ItemHeight = 17;
|
||||
this.RuleListBox.Location = new System.Drawing.Point(0, 0);
|
||||
this.RuleListBox.Name = "RuleListBox";
|
||||
this.RuleListBox.Size = new System.Drawing.Size(328, 176);
|
||||
this.RuleListBox.TabIndex = 0;
|
||||
this.RuleListBox.MouseUp += new System.Windows.Forms.MouseEventHandler(this.RuleListBox_MouseUp);
|
||||
//
|
||||
// ProcessGroupBox
|
||||
//
|
||||
this.ProcessGroupBox.Controls.Add(this.AddButton);
|
||||
this.ProcessGroupBox.Controls.Add(this.ProcessNameTextBox);
|
||||
this.ProcessGroupBox.Controls.Add(this.AddButton);
|
||||
this.ProcessGroupBox.Location = new System.Drawing.Point(6, 263);
|
||||
this.ProcessGroupBox.Name = "ProcessGroupBox";
|
||||
this.ProcessGroupBox.Size = new System.Drawing.Size(328, 46);
|
||||
this.ProcessGroupBox.TabIndex = 3;
|
||||
this.ProcessGroupBox.TabIndex = 6;
|
||||
this.ProcessGroupBox.TabStop = false;
|
||||
//
|
||||
// ProcessNameTextBox
|
||||
//
|
||||
this.ProcessNameTextBox.Location = new System.Drawing.Point(6, 15);
|
||||
this.ProcessNameTextBox.Name = "ProcessNameTextBox";
|
||||
this.ProcessNameTextBox.Size = new System.Drawing.Size(222, 23);
|
||||
this.ProcessNameTextBox.TabIndex = 0;
|
||||
//
|
||||
// AddButton
|
||||
//
|
||||
this.AddButton.Location = new System.Drawing.Point(247, 15);
|
||||
@@ -128,82 +149,48 @@ namespace Netch.Forms.Mode
|
||||
this.AddButton.UseVisualStyleBackColor = true;
|
||||
this.AddButton.Click += new System.EventHandler(this.AddButton_Click);
|
||||
//
|
||||
// ProcessNameTextBox
|
||||
// SelectButton
|
||||
//
|
||||
this.ProcessNameTextBox.Location = new System.Drawing.Point(6, 15);
|
||||
this.ProcessNameTextBox.Name = "ProcessNameTextBox";
|
||||
this.ProcessNameTextBox.Size = new System.Drawing.Size(222, 23);
|
||||
this.ProcessNameTextBox.TabIndex = 0;
|
||||
//
|
||||
// RuleListBox
|
||||
//
|
||||
this.RuleListBox.FormattingEnabled = true;
|
||||
this.RuleListBox.Dock = DockStyle.Fill;
|
||||
this.RuleListBox.ItemHeight = 17;
|
||||
this.RuleListBox.Location = new System.Drawing.Point(0, 0);
|
||||
this.RuleListBox.Name = "RuleListBox";
|
||||
this.RuleListBox.Size = new System.Drawing.Size(328, 157);
|
||||
this.RuleListBox.TabIndex = 2;
|
||||
this.RuleListBox.MouseUp += new System.Windows.Forms.MouseEventHandler(this.RuleListBox_MouseUp);
|
||||
//
|
||||
// RemarkTextBox
|
||||
//
|
||||
this.RemarkTextBox.Location = new System.Drawing.Point(84, 22);
|
||||
this.RemarkTextBox.Name = "RemarkTextBox";
|
||||
this.RemarkTextBox.Size = new System.Drawing.Size(250, 23);
|
||||
this.RemarkTextBox.TabIndex = 1;
|
||||
this.RemarkTextBox.TextChanged += new System.EventHandler(this.RemarkTextBox_TextChanged);
|
||||
//
|
||||
// RemarkLabel
|
||||
//
|
||||
this.RemarkLabel.AutoSize = true;
|
||||
this.RemarkLabel.Location = new System.Drawing.Point(12, 25);
|
||||
this.RemarkLabel.Name = "RemarkLabel";
|
||||
this.RemarkLabel.Size = new System.Drawing.Size(53, 17);
|
||||
this.RemarkLabel.TabIndex = 0;
|
||||
this.RemarkLabel.Text = "Remark";
|
||||
this.SelectButton.Location = new System.Drawing.Point(6, 315);
|
||||
this.SelectButton.Name = "SelectButton";
|
||||
this.SelectButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.SelectButton.TabIndex = 7;
|
||||
this.SelectButton.Text = "Select";
|
||||
this.SelectButton.UseVisualStyleBackColor = true;
|
||||
this.SelectButton.Click += new System.EventHandler(this.SelectButton_Click);
|
||||
//
|
||||
// contextMenuStrip
|
||||
//
|
||||
this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {this.DeleteToolStripMenuItem});
|
||||
this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.DeleteToolStripMenuItem});
|
||||
this.contextMenuStrip.Name = "contextMenuStrip";
|
||||
this.contextMenuStrip.Size = new System.Drawing.Size(153, 48);
|
||||
this.contextMenuStrip.Size = new System.Drawing.Size(114, 26);
|
||||
//
|
||||
// DeleteToolStripMenuItem
|
||||
//
|
||||
this.DeleteToolStripMenuItem.Name = "DeleteToolStripMenuItem";
|
||||
this.DeleteToolStripMenuItem.Size = new System.Drawing.Size(113, 22);
|
||||
this.DeleteToolStripMenuItem.Text = "Delete";
|
||||
this.DeleteToolStripMenuItem.Click += new System.EventHandler(this.deleteRule_Click);
|
||||
//
|
||||
// ControlButton
|
||||
//
|
||||
this.ControlButton.Location = new System.Drawing.Point(277, 362);
|
||||
this.ControlButton.Name = "ControlButton";
|
||||
this.ControlButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.ControlButton.TabIndex = 1;
|
||||
this.ControlButton.TabIndex = 2;
|
||||
this.ControlButton.Text = "Save";
|
||||
this.ControlButton.UseVisualStyleBackColor = true;
|
||||
this.ControlButton.Click += new System.EventHandler(this.ControlButton_Click);
|
||||
//
|
||||
// DeleteToolStripMenuItem
|
||||
//
|
||||
this.DeleteToolStripMenuItem.Name = "DeleteToolStripMenuItem";
|
||||
this.DeleteToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
|
||||
this.DeleteToolStripMenuItem.Text = "Delete";
|
||||
this.DeleteToolStripMenuItem.Click += new System.EventHandler(this.deleteRule_Click);
|
||||
//
|
||||
// containerControl1
|
||||
//
|
||||
this.containerControl1.Controls.Add(this.RuleListBox);
|
||||
this.containerControl1.Location = new System.Drawing.Point(6, 100);
|
||||
this.containerControl1.Name = "containerControl1";
|
||||
this.containerControl1.Size = new System.Drawing.Size(328, 157);
|
||||
this.containerControl1.TabIndex = 10;
|
||||
this.containerControl1.Padding = new Padding(0);
|
||||
this.containerControl1.Text = "containerControl1";
|
||||
//
|
||||
// Process
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
|
||||
this.ClientSize = new System.Drawing.Size(364, 397);
|
||||
this.Controls.Add(this.ControlButton);
|
||||
this.Controls.Add(this.ConfigurationGroupBox);
|
||||
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (134)));
|
||||
this.Controls.Add(this.ControlButton);
|
||||
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.MaximizeBox = false;
|
||||
@@ -213,11 +200,12 @@ namespace Netch.Forms.Mode
|
||||
this.Load += new System.EventHandler(this.ModeForm_Load);
|
||||
this.ConfigurationGroupBox.ResumeLayout(false);
|
||||
this.ConfigurationGroupBox.PerformLayout();
|
||||
this.containerControl1.ResumeLayout(false);
|
||||
this.ProcessGroupBox.ResumeLayout(false);
|
||||
this.ProcessGroupBox.PerformLayout();
|
||||
this.contextMenuStrip.ResumeLayout(false);
|
||||
this.containerControl1.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -232,10 +220,9 @@ namespace Netch.Forms.Mode
|
||||
private System.Windows.Forms.TextBox RemarkTextBox;
|
||||
private System.Windows.Forms.TextBox ProcessNameTextBox;
|
||||
private System.Windows.Forms.Button AddButton;
|
||||
private System.Windows.Forms.Button ScanButton;
|
||||
private System.Windows.Forms.Button SelectButton;
|
||||
public System.Windows.Forms.Button ControlButton;
|
||||
private System.Windows.Forms.Label FilenameLabel;
|
||||
private System.Windows.Forms.TextBox FilenameTextBox;
|
||||
private System.Windows.Forms.CheckBox UseCustomFilenameBox;
|
||||
}
|
||||
}
|
||||
@@ -31,17 +31,6 @@ namespace Netch.Forms.Mode
|
||||
CheckForIllegalCrossThreadCalls = false;
|
||||
|
||||
_mode = mode;
|
||||
if (mode != null)
|
||||
{
|
||||
Text = "Edit Process Mode";
|
||||
|
||||
RemarkTextBox.TextChanged -= RemarkTextBox_TextChanged;
|
||||
FilenameTextBox.Enabled = UseCustomFilenameBox.Enabled = false;
|
||||
|
||||
RemarkTextBox.Text = mode.Remark;
|
||||
FilenameTextBox.Text = mode.RelativePath;
|
||||
RuleListBox.Items.AddRange(mode.Rule.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -49,26 +38,18 @@ namespace Netch.Forms.Mode
|
||||
/// </summary>
|
||||
public bool Edited { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 扫描目录
|
||||
/// </summary>
|
||||
/// <param name="DirName">路径</param>
|
||||
public void ScanDirectory(string DirName)
|
||||
{
|
||||
try
|
||||
{
|
||||
RuleListBox.Items.AddRange(Directory.GetFiles(DirName, "*.exe", SearchOption.AllDirectories)
|
||||
.Select(f => Path.GetFileName(f))
|
||||
.ToArray());
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
public void ModeForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
if (_mode != null)
|
||||
{
|
||||
Text = "Edit Process Mode";
|
||||
|
||||
RemarkTextBox.TextChanged -= RemarkTextBox_TextChanged;
|
||||
RemarkTextBox.Text = _mode.Remark;
|
||||
FilenameTextBox.Text = _mode.RelativePath;
|
||||
RuleListBox.Items.AddRange(_mode.Rule.Cast<object>().ToArray());
|
||||
}
|
||||
|
||||
i18N.TranslateForm(this);
|
||||
i18N.Translate(contextMenuStrip);
|
||||
}
|
||||
@@ -101,7 +82,7 @@ namespace Netch.Forms.Mode
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(ProcessNameTextBox.Text))
|
||||
{
|
||||
MessageBoxX.Show(i18N.Translate("Please enter an process name (xxx.exe)"));
|
||||
MessageBoxX.Show(i18N.Translate("rule can not be empty"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -122,7 +103,7 @@ namespace Netch.Forms.Mode
|
||||
});
|
||||
}
|
||||
|
||||
private void ScanButton_Click(object sender, EventArgs e)
|
||||
private void SelectButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
var dialog = new CommonOpenFileDialog
|
||||
{
|
||||
@@ -136,8 +117,11 @@ namespace Netch.Forms.Mode
|
||||
|
||||
if (dialog.ShowDialog(Handle) == CommonFileDialogResult.Ok)
|
||||
{
|
||||
ScanDirectory(dialog.FileName);
|
||||
MessageBoxX.Show(i18N.Translate("Scan completed"));
|
||||
var path = dialog.FileName;
|
||||
if (!path.EndsWith(@"\"))
|
||||
path += @"\";
|
||||
|
||||
RuleListBox.Items.Add(path.ToRegexString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +158,7 @@ namespace Netch.Forms.Mode
|
||||
}
|
||||
else
|
||||
{
|
||||
var relativePath = $"Custom\\{FilenameTextBox.Text}.txt";
|
||||
var relativePath = FilenameTextBox.Text;
|
||||
var fullName = ModeHelper.GetFullPath(relativePath);
|
||||
if (File.Exists(fullName))
|
||||
{
|
||||
@@ -199,15 +183,12 @@ namespace Netch.Forms.Mode
|
||||
Close();
|
||||
}
|
||||
|
||||
private async void RemarkTextBox_TextChanged(object sender, EventArgs e)
|
||||
private void RemarkTextBox_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
await Task.Run(() =>
|
||||
BeginInvoke(new Action(() =>
|
||||
{
|
||||
if (!UseCustomFilenameBox.Checked)
|
||||
{
|
||||
FilenameTextBox.Text = ModeEditorUtils.ToSafeFileName(RemarkTextBox.Text);
|
||||
}
|
||||
});
|
||||
FilenameTextBox.Text = FilenameTextBox.Text = ModeEditorUtils.GetCustomModeRelativePath(RemarkTextBox.Text);
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
25
Netch/Forms/Mode/Route.Designer.cs
generated
@@ -35,7 +35,6 @@ namespace Netch.Forms.Mode
|
||||
this.components = new System.ComponentModel.Container();
|
||||
this.ConfigurationGroupBox = new System.Windows.Forms.GroupBox();
|
||||
this.comboBox1 = new System.Windows.Forms.ComboBox();
|
||||
this.UseCustomFilenameBox = new System.Windows.Forms.CheckBox();
|
||||
this.FilenameLabel = new System.Windows.Forms.Label();
|
||||
this.FilenameTextBox = new System.Windows.Forms.TextBox();
|
||||
this.ActionLabel = new System.Windows.Forms.Label();
|
||||
@@ -54,7 +53,6 @@ namespace Netch.Forms.Mode
|
||||
// ConfigurationGroupBox
|
||||
//
|
||||
this.ConfigurationGroupBox.Controls.Add(this.comboBox1);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.UseCustomFilenameBox);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.FilenameLabel);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.FilenameTextBox);
|
||||
this.ConfigurationGroupBox.Controls.Add(this.ActionLabel);
|
||||
@@ -77,16 +75,6 @@ namespace Netch.Forms.Mode
|
||||
this.comboBox1.Size = new System.Drawing.Size(138, 20);
|
||||
this.comboBox1.TabIndex = 11;
|
||||
//
|
||||
// UseCustomFilenameBox
|
||||
//
|
||||
this.UseCustomFilenameBox.AutoSize = true;
|
||||
this.UseCustomFilenameBox.Location = new System.Drawing.Point(84, 100);
|
||||
this.UseCustomFilenameBox.Name = "UseCustomFilenameBox";
|
||||
this.UseCustomFilenameBox.Size = new System.Drawing.Size(138, 16);
|
||||
this.UseCustomFilenameBox.TabIndex = 9;
|
||||
this.UseCustomFilenameBox.Text = "Use Custom Filename";
|
||||
this.UseCustomFilenameBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// FilenameLabel
|
||||
//
|
||||
this.FilenameLabel.AutoSize = true;
|
||||
@@ -98,9 +86,9 @@ namespace Netch.Forms.Mode
|
||||
//
|
||||
// FilenameTextBox
|
||||
//
|
||||
this.FilenameTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this.UseCustomFilenameBox, "Checked", true));
|
||||
this.FilenameTextBox.Location = new System.Drawing.Point(84, 76);
|
||||
this.FilenameTextBox.Name = "FilenameTextBox";
|
||||
this.FilenameTextBox.ReadOnly = true;
|
||||
this.FilenameTextBox.Size = new System.Drawing.Size(250, 21);
|
||||
this.FilenameTextBox.TabIndex = 5;
|
||||
//
|
||||
@@ -133,9 +121,9 @@ namespace Netch.Forms.Mode
|
||||
// containerControl1
|
||||
//
|
||||
this.containerControl1.Controls.Add(this.richTextBox1);
|
||||
this.containerControl1.Location = new System.Drawing.Point(6, 125);
|
||||
this.containerControl1.Location = new System.Drawing.Point(6, 103);
|
||||
this.containerControl1.Name = "containerControl1";
|
||||
this.containerControl1.Size = new System.Drawing.Size(328, 224);
|
||||
this.containerControl1.Size = new System.Drawing.Size(328, 246);
|
||||
this.containerControl1.TabIndex = 10;
|
||||
this.containerControl1.Text = "containerControl1";
|
||||
//
|
||||
@@ -144,13 +132,14 @@ namespace Netch.Forms.Mode
|
||||
this.richTextBox1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.richTextBox1.Location = new System.Drawing.Point(0, 0);
|
||||
this.richTextBox1.Name = "richTextBox1";
|
||||
this.richTextBox1.Size = new System.Drawing.Size(328, 224);
|
||||
this.richTextBox1.Size = new System.Drawing.Size(328, 246);
|
||||
this.richTextBox1.TabIndex = 0;
|
||||
this.richTextBox1.Text = "";
|
||||
//
|
||||
// contextMenuStrip
|
||||
//
|
||||
this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {this.DeleteToolStripMenuItem});
|
||||
this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.DeleteToolStripMenuItem});
|
||||
this.contextMenuStrip.Name = "contextMenuStrip";
|
||||
this.contextMenuStrip.Size = new System.Drawing.Size(114, 26);
|
||||
//
|
||||
@@ -186,6 +175,7 @@ namespace Netch.Forms.Mode
|
||||
this.containerControl1.ResumeLayout(false);
|
||||
this.contextMenuStrip.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
public System.Windows.Forms.GroupBox ConfigurationGroupBox;
|
||||
@@ -198,7 +188,6 @@ namespace Netch.Forms.Mode
|
||||
private System.Windows.Forms.Label RemarkLabel;
|
||||
private System.Windows.Forms.TextBox RemarkTextBox;
|
||||
private System.Windows.Forms.RichTextBox richTextBox1;
|
||||
private System.Windows.Forms.CheckBox UseCustomFilenameBox;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Properties;
|
||||
using Netch.Utils;
|
||||
@@ -44,8 +43,6 @@ namespace Netch.Forms.Mode
|
||||
comboBox1.DataSource = _items;
|
||||
comboBox1.ValueMember = "Value";
|
||||
comboBox1.DisplayMember = "Text";
|
||||
|
||||
i18N.TranslateForm(this);
|
||||
}
|
||||
|
||||
private void Route_Load(object sender, EventArgs e)
|
||||
@@ -55,13 +52,13 @@ namespace Netch.Forms.Mode
|
||||
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();
|
||||
}
|
||||
|
||||
i18N.TranslateForm(this);
|
||||
}
|
||||
|
||||
private void ControlButton_Click(object sender, EventArgs e)
|
||||
@@ -91,7 +88,7 @@ namespace Netch.Forms.Mode
|
||||
}
|
||||
else
|
||||
{
|
||||
var relativePath = $"Custom\\{FilenameTextBox.Text}.txt";
|
||||
var relativePath = FilenameTextBox.Text;
|
||||
var fullName = ModeHelper.GetFullPath(relativePath);
|
||||
if (File.Exists(fullName))
|
||||
{
|
||||
@@ -115,15 +112,12 @@ namespace Netch.Forms.Mode
|
||||
Close();
|
||||
}
|
||||
|
||||
private async void RemarkTextBox_TextChanged(object sender, EventArgs e)
|
||||
private void RemarkTextBox_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
await Task.Run(() =>
|
||||
BeginInvoke(new Action(() =>
|
||||
{
|
||||
if (!UseCustomFilenameBox.Checked)
|
||||
{
|
||||
FilenameTextBox.Text = ModeEditorUtils.ToSafeFileName(RemarkTextBox.Text);
|
||||
}
|
||||
});
|
||||
FilenameTextBox.Text = ModeEditorUtils.GetCustomModeRelativePath(RemarkTextBox.Text);
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
341
Netch/Forms/SettingForm.Designer.cs
generated
@@ -33,9 +33,6 @@ namespace Netch.Forms
|
||||
{
|
||||
this.TabControl = new System.Windows.Forms.TabControl();
|
||||
this.GeneralTabPage = new System.Windows.Forms.TabPage();
|
||||
this.ServerPingTypeLabel = new System.Windows.Forms.Label();
|
||||
this.TCPingRadioBtn = new System.Windows.Forms.RadioButton();
|
||||
this.ICMPingRadioBtn = new System.Windows.Forms.RadioButton();
|
||||
this.PortGroupBox = new System.Windows.Forms.GroupBox();
|
||||
this.Socks5PortLabel = new System.Windows.Forms.Label();
|
||||
this.Socks5PortTextBox = new System.Windows.Forms.TextBox();
|
||||
@@ -44,14 +41,16 @@ namespace Netch.Forms
|
||||
this.RedirectorLabel = new System.Windows.Forms.Label();
|
||||
this.RedirectorTextBox = new System.Windows.Forms.TextBox();
|
||||
this.AllowDevicesCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.BootShadowsocksFromDLLCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.ResolveServerHostnameCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.ServerPingTypeLabel = new System.Windows.Forms.Label();
|
||||
this.ICMPingRadioBtn = new System.Windows.Forms.RadioButton();
|
||||
this.TCPingRadioBtn = new System.Windows.Forms.RadioButton();
|
||||
this.ProfileCountLabel = new System.Windows.Forms.Label();
|
||||
this.ProfileCountTextBox = new System.Windows.Forms.TextBox();
|
||||
this.StartedPingLabel = new System.Windows.Forms.Label();
|
||||
this.DetectionTickLabel = new System.Windows.Forms.Label();
|
||||
this.StartedPingIntervalTextBox = new System.Windows.Forms.TextBox();
|
||||
this.DetectionTickTextBox = new System.Windows.Forms.TextBox();
|
||||
this.StartedPingLabel = new System.Windows.Forms.Label();
|
||||
this.StartedPingIntervalTextBox = new System.Windows.Forms.TextBox();
|
||||
this.STUNServerLabel = new System.Windows.Forms.Label();
|
||||
this.STUN_ServerComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.AclLabel = new System.Windows.Forms.Label();
|
||||
@@ -59,12 +58,17 @@ namespace Netch.Forms
|
||||
this.LanguageLabel = new System.Windows.Forms.Label();
|
||||
this.LanguageComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.NFTabPage = new System.Windows.Forms.TabPage();
|
||||
this.ProcessProxyProtocolComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.ModifySystemDNSCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||
this.ProcessProxyProtocolLabel = new System.Windows.Forms.Label();
|
||||
this.ModifiedDNSLabel = new System.Windows.Forms.Label();
|
||||
this.ModifiedDNSTextBox = new System.Windows.Forms.TextBox();
|
||||
this.ProcessProxyProtocolComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.DNSRedirectorCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.RDRDNSLabel = new System.Windows.Forms.Label();
|
||||
this.RDRDNSTextBox = new System.Windows.Forms.TextBox();
|
||||
this.ICMPRedirectorCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.RDRICMPLabel = new System.Windows.Forms.Label();
|
||||
this.ModifiedICMPTextBox = new System.Windows.Forms.TextBox();
|
||||
this.RedirectorSSCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.ChildProcessHandleCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.TAPTabPage = new System.Windows.Forms.TabPage();
|
||||
this.TUNTAPGroupBox = new System.Windows.Forms.GroupBox();
|
||||
this.TUNTAPAddressLabel = new System.Windows.Forms.Label();
|
||||
@@ -80,8 +84,8 @@ namespace Netch.Forms
|
||||
this.UseFakeDNSCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.GlobalBypassIPsButton = new System.Windows.Forms.Button();
|
||||
this.v2rayTabPage = new System.Windows.Forms.TabPage();
|
||||
this.TLSAllowInsecureCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.XrayConeCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.TLSAllowInsecureCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.UseMuxCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.KCPGroupBox = new System.Windows.Forms.GroupBox();
|
||||
this.mtuLabel = new System.Windows.Forms.Label();
|
||||
@@ -119,6 +123,7 @@ namespace Netch.Forms
|
||||
this.GeneralTabPage.SuspendLayout();
|
||||
this.PortGroupBox.SuspendLayout();
|
||||
this.NFTabPage.SuspendLayout();
|
||||
this.groupBox1.SuspendLayout();
|
||||
this.TAPTabPage.SuspendLayout();
|
||||
this.TUNTAPGroupBox.SuspendLayout();
|
||||
this.v2rayTabPage.SuspendLayout();
|
||||
@@ -146,18 +151,17 @@ namespace Netch.Forms
|
||||
// GeneralTabPage
|
||||
//
|
||||
this.GeneralTabPage.BackColor = System.Drawing.SystemColors.ButtonFace;
|
||||
this.GeneralTabPage.Controls.Add(this.ServerPingTypeLabel);
|
||||
this.GeneralTabPage.Controls.Add(this.TCPingRadioBtn);
|
||||
this.GeneralTabPage.Controls.Add(this.ICMPingRadioBtn);
|
||||
this.GeneralTabPage.Controls.Add(this.PortGroupBox);
|
||||
this.GeneralTabPage.Controls.Add(this.BootShadowsocksFromDLLCheckBox);
|
||||
this.GeneralTabPage.Controls.Add(this.ResolveServerHostnameCheckBox);
|
||||
this.GeneralTabPage.Controls.Add(this.ServerPingTypeLabel);
|
||||
this.GeneralTabPage.Controls.Add(this.ICMPingRadioBtn);
|
||||
this.GeneralTabPage.Controls.Add(this.TCPingRadioBtn);
|
||||
this.GeneralTabPage.Controls.Add(this.ProfileCountLabel);
|
||||
this.GeneralTabPage.Controls.Add(this.ProfileCountTextBox);
|
||||
this.GeneralTabPage.Controls.Add(this.StartedPingLabel);
|
||||
this.GeneralTabPage.Controls.Add(this.DetectionTickLabel);
|
||||
this.GeneralTabPage.Controls.Add(this.StartedPingIntervalTextBox);
|
||||
this.GeneralTabPage.Controls.Add(this.DetectionTickTextBox);
|
||||
this.GeneralTabPage.Controls.Add(this.StartedPingLabel);
|
||||
this.GeneralTabPage.Controls.Add(this.StartedPingIntervalTextBox);
|
||||
this.GeneralTabPage.Controls.Add(this.STUNServerLabel);
|
||||
this.GeneralTabPage.Controls.Add(this.STUN_ServerComboBox);
|
||||
this.GeneralTabPage.Controls.Add(this.AclLabel);
|
||||
@@ -171,37 +175,6 @@ namespace Netch.Forms
|
||||
this.GeneralTabPage.TabIndex = 0;
|
||||
this.GeneralTabPage.Text = "General";
|
||||
//
|
||||
// ServerPingTypeLabel
|
||||
//
|
||||
this.ServerPingTypeLabel.AutoSize = true;
|
||||
this.ServerPingTypeLabel.Location = new System.Drawing.Point(267, 66);
|
||||
this.ServerPingTypeLabel.Name = "ServerPingTypeLabel";
|
||||
this.ServerPingTypeLabel.Size = new System.Drawing.Size(89, 12);
|
||||
this.ServerPingTypeLabel.TabIndex = 16;
|
||||
this.ServerPingTypeLabel.Text = "ServerPingType";
|
||||
//
|
||||
// TCPingRadioBtn
|
||||
//
|
||||
this.TCPingRadioBtn.AutoSize = true;
|
||||
this.TCPingRadioBtn.Location = new System.Drawing.Point(332, 85);
|
||||
this.TCPingRadioBtn.Name = "TCPingRadioBtn";
|
||||
this.TCPingRadioBtn.Size = new System.Drawing.Size(59, 16);
|
||||
this.TCPingRadioBtn.TabIndex = 15;
|
||||
this.TCPingRadioBtn.TabStop = true;
|
||||
this.TCPingRadioBtn.Text = "TCPing";
|
||||
this.TCPingRadioBtn.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// ICMPingRadioBtn
|
||||
//
|
||||
this.ICMPingRadioBtn.AutoSize = true;
|
||||
this.ICMPingRadioBtn.Location = new System.Drawing.Point(268, 85);
|
||||
this.ICMPingRadioBtn.Name = "ICMPingRadioBtn";
|
||||
this.ICMPingRadioBtn.Size = new System.Drawing.Size(65, 16);
|
||||
this.ICMPingRadioBtn.TabIndex = 14;
|
||||
this.ICMPingRadioBtn.TabStop = true;
|
||||
this.ICMPingRadioBtn.Text = "ICMPing";
|
||||
this.ICMPingRadioBtn.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// PortGroupBox
|
||||
//
|
||||
this.PortGroupBox.Controls.Add(this.Socks5PortLabel);
|
||||
@@ -280,33 +253,54 @@ namespace Netch.Forms
|
||||
this.AllowDevicesCheckBox.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
this.AllowDevicesCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// BootShadowsocksFromDLLCheckBox
|
||||
//
|
||||
this.BootShadowsocksFromDLLCheckBox.AutoSize = true;
|
||||
this.BootShadowsocksFromDLLCheckBox.Location = new System.Drawing.Point(267, 15);
|
||||
this.BootShadowsocksFromDLLCheckBox.Name = "BootShadowsocksFromDLLCheckBox";
|
||||
this.BootShadowsocksFromDLLCheckBox.Size = new System.Drawing.Size(60, 16);
|
||||
this.BootShadowsocksFromDLLCheckBox.TabIndex = 1;
|
||||
this.BootShadowsocksFromDLLCheckBox.Text = "SS DLL";
|
||||
this.BootShadowsocksFromDLLCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// ResolveServerHostnameCheckBox
|
||||
//
|
||||
this.ResolveServerHostnameCheckBox.AutoSize = true;
|
||||
this.ResolveServerHostnameCheckBox.Location = new System.Drawing.Point(267, 37);
|
||||
this.ResolveServerHostnameCheckBox.Location = new System.Drawing.Point(267, 15);
|
||||
this.ResolveServerHostnameCheckBox.Name = "ResolveServerHostnameCheckBox";
|
||||
this.ResolveServerHostnameCheckBox.Size = new System.Drawing.Size(162, 16);
|
||||
this.ResolveServerHostnameCheckBox.TabIndex = 2;
|
||||
this.ResolveServerHostnameCheckBox.TabIndex = 1;
|
||||
this.ResolveServerHostnameCheckBox.Text = "Resolve Server Hostname";
|
||||
this.ResolveServerHostnameCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// ServerPingTypeLabel
|
||||
//
|
||||
this.ServerPingTypeLabel.AutoSize = true;
|
||||
this.ServerPingTypeLabel.Location = new System.Drawing.Point(267, 44);
|
||||
this.ServerPingTypeLabel.Name = "ServerPingTypeLabel";
|
||||
this.ServerPingTypeLabel.Size = new System.Drawing.Size(89, 12);
|
||||
this.ServerPingTypeLabel.TabIndex = 2;
|
||||
this.ServerPingTypeLabel.Text = "ServerPingType";
|
||||
//
|
||||
// ICMPingRadioBtn
|
||||
//
|
||||
this.ICMPingRadioBtn.AutoSize = true;
|
||||
this.ICMPingRadioBtn.Location = new System.Drawing.Point(268, 63);
|
||||
this.ICMPingRadioBtn.Name = "ICMPingRadioBtn";
|
||||
this.ICMPingRadioBtn.Size = new System.Drawing.Size(65, 16);
|
||||
this.ICMPingRadioBtn.TabIndex = 3;
|
||||
this.ICMPingRadioBtn.TabStop = true;
|
||||
this.ICMPingRadioBtn.Text = "ICMPing";
|
||||
this.ICMPingRadioBtn.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// TCPingRadioBtn
|
||||
//
|
||||
this.TCPingRadioBtn.AutoSize = true;
|
||||
this.TCPingRadioBtn.Location = new System.Drawing.Point(332, 63);
|
||||
this.TCPingRadioBtn.Name = "TCPingRadioBtn";
|
||||
this.TCPingRadioBtn.Size = new System.Drawing.Size(59, 16);
|
||||
this.TCPingRadioBtn.TabIndex = 4;
|
||||
this.TCPingRadioBtn.TabStop = true;
|
||||
this.TCPingRadioBtn.Text = "TCPing";
|
||||
this.TCPingRadioBtn.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// ProfileCountLabel
|
||||
//
|
||||
this.ProfileCountLabel.AutoSize = true;
|
||||
this.ProfileCountLabel.Location = new System.Drawing.Point(12, 160);
|
||||
this.ProfileCountLabel.Name = "ProfileCountLabel";
|
||||
this.ProfileCountLabel.Size = new System.Drawing.Size(77, 12);
|
||||
this.ProfileCountLabel.TabIndex = 3;
|
||||
this.ProfileCountLabel.TabIndex = 5;
|
||||
this.ProfileCountLabel.Text = "ProfileCount";
|
||||
//
|
||||
// ProfileCountTextBox
|
||||
@@ -314,50 +308,50 @@ namespace Netch.Forms
|
||||
this.ProfileCountTextBox.Location = new System.Drawing.Point(120, 157);
|
||||
this.ProfileCountTextBox.Name = "ProfileCountTextBox";
|
||||
this.ProfileCountTextBox.Size = new System.Drawing.Size(90, 21);
|
||||
this.ProfileCountTextBox.TabIndex = 4;
|
||||
this.ProfileCountTextBox.TabIndex = 6;
|
||||
this.ProfileCountTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
// StartedPingLabel
|
||||
//
|
||||
this.StartedPingLabel.AutoSize = true;
|
||||
this.StartedPingLabel.Location = new System.Drawing.Point(12, 187);
|
||||
this.StartedPingLabel.Name = "StartedPingLabel";
|
||||
this.StartedPingLabel.Size = new System.Drawing.Size(137, 12);
|
||||
this.StartedPingLabel.TabIndex = 5;
|
||||
this.StartedPingLabel.Text = "Delay test after start";
|
||||
//
|
||||
// DetectionTickLabel
|
||||
//
|
||||
this.DetectionTickLabel.AutoSize = true;
|
||||
this.DetectionTickLabel.Location = new System.Drawing.Point(225, 160);
|
||||
this.DetectionTickLabel.Name = "DetectionTickLabel";
|
||||
this.DetectionTickLabel.Size = new System.Drawing.Size(119, 12);
|
||||
this.DetectionTickLabel.TabIndex = 6;
|
||||
this.DetectionTickLabel.TabIndex = 7;
|
||||
this.DetectionTickLabel.Text = "Detection Tick(sec)";
|
||||
//
|
||||
// StartedPingIntervalTextBox
|
||||
//
|
||||
this.StartedPingIntervalTextBox.Location = new System.Drawing.Point(177, 184);
|
||||
this.StartedPingIntervalTextBox.Name = "StartedPingIntervalTextBox";
|
||||
this.StartedPingIntervalTextBox.Size = new System.Drawing.Size(68, 21);
|
||||
this.StartedPingIntervalTextBox.TabIndex = 7;
|
||||
this.StartedPingIntervalTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
// DetectionTickTextBox
|
||||
//
|
||||
this.DetectionTickTextBox.Location = new System.Drawing.Point(366, 157);
|
||||
this.DetectionTickTextBox.Name = "DetectionTickTextBox";
|
||||
this.DetectionTickTextBox.Size = new System.Drawing.Size(68, 21);
|
||||
this.DetectionTickTextBox.TabIndex = 7;
|
||||
this.DetectionTickTextBox.TabIndex = 8;
|
||||
this.DetectionTickTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
// StartedPingLabel
|
||||
//
|
||||
this.StartedPingLabel.AutoSize = true;
|
||||
this.StartedPingLabel.Location = new System.Drawing.Point(12, 187);
|
||||
this.StartedPingLabel.Name = "StartedPingLabel";
|
||||
this.StartedPingLabel.Size = new System.Drawing.Size(137, 12);
|
||||
this.StartedPingLabel.TabIndex = 9;
|
||||
this.StartedPingLabel.Text = "Delay test after start";
|
||||
//
|
||||
// StartedPingIntervalTextBox
|
||||
//
|
||||
this.StartedPingIntervalTextBox.Location = new System.Drawing.Point(177, 184);
|
||||
this.StartedPingIntervalTextBox.Name = "StartedPingIntervalTextBox";
|
||||
this.StartedPingIntervalTextBox.Size = new System.Drawing.Size(68, 21);
|
||||
this.StartedPingIntervalTextBox.TabIndex = 10;
|
||||
this.StartedPingIntervalTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
// STUNServerLabel
|
||||
//
|
||||
this.STUNServerLabel.AutoSize = true;
|
||||
this.STUNServerLabel.Location = new System.Drawing.Point(12, 216);
|
||||
this.STUNServerLabel.Name = "STUNServerLabel";
|
||||
this.STUNServerLabel.Size = new System.Drawing.Size(71, 12);
|
||||
this.STUNServerLabel.TabIndex = 8;
|
||||
this.STUNServerLabel.TabIndex = 11;
|
||||
this.STUNServerLabel.Text = "STUN Server";
|
||||
//
|
||||
// STUN_ServerComboBox
|
||||
@@ -366,7 +360,7 @@ namespace Netch.Forms
|
||||
this.STUN_ServerComboBox.Location = new System.Drawing.Point(120, 213);
|
||||
this.STUN_ServerComboBox.Name = "STUN_ServerComboBox";
|
||||
this.STUN_ServerComboBox.Size = new System.Drawing.Size(314, 20);
|
||||
this.STUN_ServerComboBox.TabIndex = 9;
|
||||
this.STUN_ServerComboBox.TabIndex = 12;
|
||||
//
|
||||
// AclLabel
|
||||
//
|
||||
@@ -374,7 +368,7 @@ namespace Netch.Forms
|
||||
this.AclLabel.Location = new System.Drawing.Point(12, 248);
|
||||
this.AclLabel.Name = "AclLabel";
|
||||
this.AclLabel.Size = new System.Drawing.Size(65, 12);
|
||||
this.AclLabel.TabIndex = 10;
|
||||
this.AclLabel.TabIndex = 13;
|
||||
this.AclLabel.Text = "Custom ACL";
|
||||
//
|
||||
// AclAddrTextBox
|
||||
@@ -382,7 +376,7 @@ namespace Netch.Forms
|
||||
this.AclAddrTextBox.Location = new System.Drawing.Point(120, 245);
|
||||
this.AclAddrTextBox.Name = "AclAddrTextBox";
|
||||
this.AclAddrTextBox.Size = new System.Drawing.Size(314, 21);
|
||||
this.AclAddrTextBox.TabIndex = 11;
|
||||
this.AclAddrTextBox.TabIndex = 14;
|
||||
this.AclAddrTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
// LanguageLabel
|
||||
@@ -391,7 +385,7 @@ namespace Netch.Forms
|
||||
this.LanguageLabel.Location = new System.Drawing.Point(12, 277);
|
||||
this.LanguageLabel.Name = "LanguageLabel";
|
||||
this.LanguageLabel.Size = new System.Drawing.Size(53, 12);
|
||||
this.LanguageLabel.TabIndex = 12;
|
||||
this.LanguageLabel.TabIndex = 15;
|
||||
this.LanguageLabel.Text = "Language";
|
||||
//
|
||||
// LanguageComboBox
|
||||
@@ -401,17 +395,14 @@ namespace Netch.Forms
|
||||
this.LanguageComboBox.Location = new System.Drawing.Point(120, 274);
|
||||
this.LanguageComboBox.Name = "LanguageComboBox";
|
||||
this.LanguageComboBox.Size = new System.Drawing.Size(121, 20);
|
||||
this.LanguageComboBox.TabIndex = 13;
|
||||
this.LanguageComboBox.TabIndex = 16;
|
||||
//
|
||||
// NFTabPage
|
||||
//
|
||||
this.NFTabPage.BackColor = System.Drawing.SystemColors.ButtonFace;
|
||||
this.NFTabPage.Controls.Add(this.ModifySystemDNSCheckBox);
|
||||
this.NFTabPage.Controls.Add(this.ModifiedDNSLabel);
|
||||
this.NFTabPage.Controls.Add(this.ModifiedDNSTextBox);
|
||||
this.NFTabPage.Controls.Add(this.groupBox1);
|
||||
this.NFTabPage.Controls.Add(this.RedirectorSSCheckBox);
|
||||
this.NFTabPage.Controls.Add(this.ProcessProxyProtocolLabel);
|
||||
this.NFTabPage.Controls.Add(this.ProcessProxyProtocolComboBox);
|
||||
this.NFTabPage.Controls.Add(this.ChildProcessHandleCheckBox);
|
||||
this.NFTabPage.Location = new System.Drawing.Point(4, 25);
|
||||
this.NFTabPage.Name = "NFTabPage";
|
||||
this.NFTabPage.Padding = new System.Windows.Forms.Padding(3);
|
||||
@@ -419,62 +410,116 @@ namespace Netch.Forms
|
||||
this.NFTabPage.TabIndex = 1;
|
||||
this.NFTabPage.Text = "Process Mode";
|
||||
//
|
||||
// ProcessProxyProtocolComboBox
|
||||
// groupBox1
|
||||
//
|
||||
this.ProcessProxyProtocolComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.ProcessProxyProtocolComboBox.FormattingEnabled = true;
|
||||
this.ProcessProxyProtocolComboBox.Location = new System.Drawing.Point(167, 58);
|
||||
this.ProcessProxyProtocolComboBox.Name = "ProcessProxyProtocolComboBox";
|
||||
this.ProcessProxyProtocolComboBox.Size = new System.Drawing.Size(121, 20);
|
||||
this.ProcessProxyProtocolComboBox.TabIndex = 3;
|
||||
//
|
||||
// ModifySystemDNSCheckBox
|
||||
//
|
||||
this.ModifySystemDNSCheckBox.AutoSize = true;
|
||||
this.ModifySystemDNSCheckBox.Location = new System.Drawing.Point(8, 16);
|
||||
this.ModifySystemDNSCheckBox.Name = "ModifySystemDNSCheckBox";
|
||||
this.ModifySystemDNSCheckBox.Size = new System.Drawing.Size(126, 16);
|
||||
this.ModifySystemDNSCheckBox.TabIndex = 0;
|
||||
this.ModifySystemDNSCheckBox.Text = "Modify System DNS";
|
||||
this.ModifySystemDNSCheckBox.UseVisualStyleBackColor = true;
|
||||
this.groupBox1.Controls.Add(this.ProcessProxyProtocolLabel);
|
||||
this.groupBox1.Controls.Add(this.ProcessProxyProtocolComboBox);
|
||||
this.groupBox1.Controls.Add(this.DNSRedirectorCheckBox);
|
||||
this.groupBox1.Controls.Add(this.RDRDNSLabel);
|
||||
this.groupBox1.Controls.Add(this.RDRDNSTextBox);
|
||||
this.groupBox1.Controls.Add(this.ICMPRedirectorCheckBox);
|
||||
this.groupBox1.Controls.Add(this.RDRICMPLabel);
|
||||
this.groupBox1.Controls.Add(this.ModifiedICMPTextBox);
|
||||
this.groupBox1.Location = new System.Drawing.Point(5, 6);
|
||||
this.groupBox1.Name = "groupBox1";
|
||||
this.groupBox1.Size = new System.Drawing.Size(450, 117);
|
||||
this.groupBox1.TabIndex = 0;
|
||||
this.groupBox1.TabStop = false;
|
||||
//
|
||||
// ProcessProxyProtocolLabel
|
||||
//
|
||||
this.ProcessProxyProtocolLabel.AutoSize = true;
|
||||
this.ProcessProxyProtocolLabel.Location = new System.Drawing.Point(24, 61);
|
||||
this.ProcessProxyProtocolLabel.Location = new System.Drawing.Point(23, 21);
|
||||
this.ProcessProxyProtocolLabel.Name = "ProcessProxyProtocolLabel";
|
||||
this.ProcessProxyProtocolLabel.Size = new System.Drawing.Size(89, 12);
|
||||
this.ProcessProxyProtocolLabel.TabIndex = 2;
|
||||
this.ProcessProxyProtocolLabel.TabIndex = 0;
|
||||
this.ProcessProxyProtocolLabel.Text = "Proxy Protocol";
|
||||
//
|
||||
// ModifiedDNSLabel
|
||||
// ProcessProxyProtocolComboBox
|
||||
//
|
||||
this.ModifiedDNSLabel.AutoSize = true;
|
||||
this.ModifiedDNSLabel.Location = new System.Drawing.Point(223, 17);
|
||||
this.ModifiedDNSLabel.Name = "ModifiedDNSLabel";
|
||||
this.ModifiedDNSLabel.Size = new System.Drawing.Size(23, 12);
|
||||
this.ModifiedDNSLabel.TabIndex = 2;
|
||||
this.ModifiedDNSLabel.Text = "DNS";
|
||||
this.ProcessProxyProtocolComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.ProcessProxyProtocolComboBox.FormattingEnabled = true;
|
||||
this.ProcessProxyProtocolComboBox.Location = new System.Drawing.Point(118, 16);
|
||||
this.ProcessProxyProtocolComboBox.Name = "ProcessProxyProtocolComboBox";
|
||||
this.ProcessProxyProtocolComboBox.Size = new System.Drawing.Size(191, 20);
|
||||
this.ProcessProxyProtocolComboBox.TabIndex = 1;
|
||||
//
|
||||
// ModifiedDNSTextBox
|
||||
// DNSRedirectorCheckBox
|
||||
//
|
||||
this.ModifiedDNSTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this.ModifySystemDNSCheckBox, "Checked", true));
|
||||
this.ModifiedDNSTextBox.Location = new System.Drawing.Point(264, 14);
|
||||
this.ModifiedDNSTextBox.Name = "ModifiedDNSTextBox";
|
||||
this.ModifiedDNSTextBox.Size = new System.Drawing.Size(194, 21);
|
||||
this.ModifiedDNSTextBox.TabIndex = 1;
|
||||
this.ModifiedDNSTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
this.DNSRedirectorCheckBox.AutoSize = true;
|
||||
this.DNSRedirectorCheckBox.Location = new System.Drawing.Point(6, 51);
|
||||
this.DNSRedirectorCheckBox.Name = "DNSRedirectorCheckBox";
|
||||
this.DNSRedirectorCheckBox.Size = new System.Drawing.Size(108, 16);
|
||||
this.DNSRedirectorCheckBox.TabIndex = 2;
|
||||
this.DNSRedirectorCheckBox.Text = "DNS Redirector";
|
||||
this.DNSRedirectorCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// RDRDNSLabel
|
||||
//
|
||||
this.RDRDNSLabel.AutoSize = true;
|
||||
this.RDRDNSLabel.Location = new System.Drawing.Point(224, 52);
|
||||
this.RDRDNSLabel.Name = "RDRDNSLabel";
|
||||
this.RDRDNSLabel.Size = new System.Drawing.Size(23, 12);
|
||||
this.RDRDNSLabel.TabIndex = 3;
|
||||
this.RDRDNSLabel.Text = "DNS";
|
||||
//
|
||||
// RDRDNSTextBox
|
||||
//
|
||||
this.RDRDNSTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this.DNSRedirectorCheckBox, "Checked", true));
|
||||
this.RDRDNSTextBox.Location = new System.Drawing.Point(253, 46);
|
||||
this.RDRDNSTextBox.Name = "RDRDNSTextBox";
|
||||
this.RDRDNSTextBox.Size = new System.Drawing.Size(191, 21);
|
||||
this.RDRDNSTextBox.TabIndex = 4;
|
||||
this.RDRDNSTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
// ICMPRedirectorCheckBox
|
||||
//
|
||||
this.ICMPRedirectorCheckBox.AutoSize = true;
|
||||
this.ICMPRedirectorCheckBox.Location = new System.Drawing.Point(6, 81);
|
||||
this.ICMPRedirectorCheckBox.Name = "ICMPRedirectorCheckBox";
|
||||
this.ICMPRedirectorCheckBox.Size = new System.Drawing.Size(114, 16);
|
||||
this.ICMPRedirectorCheckBox.TabIndex = 5;
|
||||
this.ICMPRedirectorCheckBox.Text = "ICMP Redirector";
|
||||
this.ICMPRedirectorCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// RDRICMPLabel
|
||||
//
|
||||
this.RDRICMPLabel.AutoSize = true;
|
||||
this.RDRICMPLabel.Location = new System.Drawing.Point(218, 81);
|
||||
this.RDRICMPLabel.Name = "RDRICMPLabel";
|
||||
this.RDRICMPLabel.Size = new System.Drawing.Size(29, 12);
|
||||
this.RDRICMPLabel.TabIndex = 6;
|
||||
this.RDRICMPLabel.Text = "ICMP";
|
||||
//
|
||||
// ModifiedICMPTextBox
|
||||
//
|
||||
this.ModifiedICMPTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", this.ICMPRedirectorCheckBox, "Checked", true));
|
||||
this.ModifiedICMPTextBox.Location = new System.Drawing.Point(253, 78);
|
||||
this.ModifiedICMPTextBox.Name = "ModifiedICMPTextBox";
|
||||
this.ModifiedICMPTextBox.Size = new System.Drawing.Size(191, 21);
|
||||
this.ModifiedICMPTextBox.TabIndex = 7;
|
||||
this.ModifiedICMPTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
// RedirectorSSCheckBox
|
||||
//
|
||||
this.RedirectorSSCheckBox.AutoSize = true;
|
||||
this.RedirectorSSCheckBox.Location = new System.Drawing.Point(8, 38);
|
||||
this.RedirectorSSCheckBox.Location = new System.Drawing.Point(11, 129);
|
||||
this.RedirectorSSCheckBox.Name = "RedirectorSSCheckBox";
|
||||
this.RedirectorSSCheckBox.Size = new System.Drawing.Size(102, 16);
|
||||
this.RedirectorSSCheckBox.TabIndex = 0;
|
||||
this.RedirectorSSCheckBox.TabIndex = 1;
|
||||
this.RedirectorSSCheckBox.Text = "Redirector SS";
|
||||
this.RedirectorSSCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// ChildProcessHandleCheckBox
|
||||
//
|
||||
this.ChildProcessHandleCheckBox.AutoSize = true;
|
||||
this.ChildProcessHandleCheckBox.Location = new System.Drawing.Point(11, 151);
|
||||
this.ChildProcessHandleCheckBox.Name = "ChildProcessHandleCheckBox";
|
||||
this.ChildProcessHandleCheckBox.Size = new System.Drawing.Size(144, 16);
|
||||
this.ChildProcessHandleCheckBox.TabIndex = 2;
|
||||
this.ChildProcessHandleCheckBox.Text = "Child Process Handle";
|
||||
this.ChildProcessHandleCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// TAPTabPage
|
||||
//
|
||||
this.TAPTabPage.BackColor = System.Drawing.SystemColors.ButtonFace;
|
||||
@@ -621,8 +666,8 @@ namespace Netch.Forms
|
||||
// v2rayTabPage
|
||||
//
|
||||
this.v2rayTabPage.BackColor = System.Drawing.SystemColors.ButtonFace;
|
||||
this.v2rayTabPage.Controls.Add(this.TLSAllowInsecureCheckBox);
|
||||
this.v2rayTabPage.Controls.Add(this.XrayConeCheckBox);
|
||||
this.v2rayTabPage.Controls.Add(this.TLSAllowInsecureCheckBox);
|
||||
this.v2rayTabPage.Controls.Add(this.UseMuxCheckBox);
|
||||
this.v2rayTabPage.Controls.Add(this.KCPGroupBox);
|
||||
this.v2rayTabPage.Location = new System.Drawing.Point(4, 25);
|
||||
@@ -632,33 +677,33 @@ namespace Netch.Forms
|
||||
this.v2rayTabPage.TabIndex = 3;
|
||||
this.v2rayTabPage.Text = "V2Ray";
|
||||
//
|
||||
// TLSAllowInsecureCheckBox
|
||||
//
|
||||
this.TLSAllowInsecureCheckBox.AutoSize = true;
|
||||
this.TLSAllowInsecureCheckBox.Location = new System.Drawing.Point(6, 42);
|
||||
this.TLSAllowInsecureCheckBox.Name = "TLSAllowInsecureCheckBox";
|
||||
this.TLSAllowInsecureCheckBox.Size = new System.Drawing.Size(126, 16);
|
||||
this.TLSAllowInsecureCheckBox.TabIndex = 0;
|
||||
this.TLSAllowInsecureCheckBox.Text = "TLS AllowInsecure";
|
||||
this.TLSAllowInsecureCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// XrayConeCheckBox
|
||||
//
|
||||
this.XrayConeCheckBox.AutoSize = true;
|
||||
this.XrayConeCheckBox.Location = new System.Drawing.Point(6, 15);
|
||||
this.XrayConeCheckBox.Name = "XrayConeCheckBox";
|
||||
this.XrayConeCheckBox.Size = new System.Drawing.Size(336, 16);
|
||||
this.XrayConeCheckBox.TabIndex = 1;
|
||||
this.XrayConeCheckBox.TabIndex = 0;
|
||||
this.XrayConeCheckBox.Text = "FullCone Support (Required Server Xray-core v1.3.0+)";
|
||||
this.XrayConeCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// TLSAllowInsecureCheckBox
|
||||
//
|
||||
this.TLSAllowInsecureCheckBox.AutoSize = true;
|
||||
this.TLSAllowInsecureCheckBox.Location = new System.Drawing.Point(6, 42);
|
||||
this.TLSAllowInsecureCheckBox.Name = "TLSAllowInsecureCheckBox";
|
||||
this.TLSAllowInsecureCheckBox.Size = new System.Drawing.Size(126, 16);
|
||||
this.TLSAllowInsecureCheckBox.TabIndex = 1;
|
||||
this.TLSAllowInsecureCheckBox.Text = "TLS AllowInsecure";
|
||||
this.TLSAllowInsecureCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// UseMuxCheckBox
|
||||
//
|
||||
this.UseMuxCheckBox.AutoSize = true;
|
||||
this.UseMuxCheckBox.Location = new System.Drawing.Point(148, 42);
|
||||
this.UseMuxCheckBox.Name = "UseMuxCheckBox";
|
||||
this.UseMuxCheckBox.Size = new System.Drawing.Size(66, 16);
|
||||
this.UseMuxCheckBox.TabIndex = 1;
|
||||
this.UseMuxCheckBox.TabIndex = 2;
|
||||
this.UseMuxCheckBox.Text = "Use Mux";
|
||||
this.UseMuxCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -680,7 +725,7 @@ namespace Netch.Forms
|
||||
this.KCPGroupBox.Location = new System.Drawing.Point(9, 75);
|
||||
this.KCPGroupBox.Name = "KCPGroupBox";
|
||||
this.KCPGroupBox.Size = new System.Drawing.Size(427, 204);
|
||||
this.KCPGroupBox.TabIndex = 2;
|
||||
this.KCPGroupBox.TabIndex = 3;
|
||||
this.KCPGroupBox.TabStop = false;
|
||||
this.KCPGroupBox.Text = "KCP";
|
||||
//
|
||||
@@ -1012,6 +1057,8 @@ namespace Netch.Forms
|
||||
this.PortGroupBox.PerformLayout();
|
||||
this.NFTabPage.ResumeLayout(false);
|
||||
this.NFTabPage.PerformLayout();
|
||||
this.groupBox1.ResumeLayout(false);
|
||||
this.groupBox1.PerformLayout();
|
||||
this.TAPTabPage.ResumeLayout(false);
|
||||
this.TUNTAPGroupBox.ResumeLayout(false);
|
||||
this.TUNTAPGroupBox.PerformLayout();
|
||||
@@ -1047,7 +1094,6 @@ namespace Netch.Forms
|
||||
private System.Windows.Forms.Label Socks5PortLabel;
|
||||
private System.Windows.Forms.TextBox Socks5PortTextBox;
|
||||
private System.Windows.Forms.CheckBox ResolveServerHostnameCheckBox;
|
||||
private System.Windows.Forms.CheckBox BootShadowsocksFromDLLCheckBox;
|
||||
private System.Windows.Forms.GroupBox TUNTAPGroupBox;
|
||||
private System.Windows.Forms.CheckBox UseFakeDNSCheckBox;
|
||||
private System.Windows.Forms.CheckBox ProxyDNSCheckBox;
|
||||
@@ -1061,7 +1107,7 @@ namespace Netch.Forms
|
||||
private System.Windows.Forms.Label TUNTAPAddressLabel;
|
||||
private System.Windows.Forms.TextBox TUNTAPAddressTextBox;
|
||||
private System.Windows.Forms.Button GlobalBypassIPsButton;
|
||||
private System.Windows.Forms.CheckBox ModifySystemDNSCheckBox;
|
||||
private System.Windows.Forms.CheckBox DNSRedirectorCheckBox;
|
||||
private System.Windows.Forms.Button ControlButton;
|
||||
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
|
||||
private System.Windows.Forms.TabPage OtherTabPage;
|
||||
@@ -1107,13 +1153,18 @@ namespace Netch.Forms
|
||||
private System.Windows.Forms.Label ChinaDNSLabel;
|
||||
private System.Windows.Forms.TextBox OtherDNSTextBox;
|
||||
private System.Windows.Forms.TextBox ChinaDNSTextBox;
|
||||
private System.Windows.Forms.TextBox ModifiedDNSTextBox;
|
||||
private System.Windows.Forms.Label ModifiedDNSLabel;
|
||||
private System.Windows.Forms.TextBox RDRDNSTextBox;
|
||||
private System.Windows.Forms.Label RDRDNSLabel;
|
||||
private System.Windows.Forms.CheckBox RedirectorSSCheckBox;
|
||||
private System.Windows.Forms.Label ServerPingTypeLabel;
|
||||
private System.Windows.Forms.RadioButton TCPingRadioBtn;
|
||||
private System.Windows.Forms.RadioButton ICMPingRadioBtn;
|
||||
private System.Windows.Forms.ComboBox ProcessProxyProtocolComboBox;
|
||||
private System.Windows.Forms.Label ProcessProxyProtocolLabel;
|
||||
private System.Windows.Forms.CheckBox ICMPRedirectorCheckBox;
|
||||
private System.Windows.Forms.TextBox ModifiedICMPTextBox;
|
||||
private System.Windows.Forms.Label RDRICMPLabel;
|
||||
private System.Windows.Forms.CheckBox ChildProcessHandleCheckBox;
|
||||
private System.Windows.Forms.GroupBox groupBox1;
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,6 @@ namespace Netch.Forms
|
||||
c => Global.Settings.LocalAddress = AllowDevicesCheckBox.Checked ? "0.0.0.0" : "127.0.0.1",
|
||||
Global.Settings.LocalAddress switch {"127.0.0.1" => false, "0.0.0.0" => true, _ => false});
|
||||
|
||||
BindCheckBox(BootShadowsocksFromDLLCheckBox, c => Global.Settings.BootShadowsocksFromDLL = c, Global.Settings.BootShadowsocksFromDLL);
|
||||
BindCheckBox(ResolveServerHostnameCheckBox, c => Global.Settings.ResolveServerHostname = c, Global.Settings.ResolveServerHostname);
|
||||
|
||||
BindRadioBox(ICMPingRadioBtn, _ => { }, !Global.Settings.ServerTCPing);
|
||||
@@ -109,12 +108,18 @@ namespace Netch.Forms
|
||||
|
||||
#region Process Mode
|
||||
|
||||
BindCheckBox(ModifySystemDNSCheckBox, b => Global.Settings.ModifySystemDNS = b, Global.Settings.ModifySystemDNS);
|
||||
BindCheckBox(DNSRedirectorCheckBox, b => Global.Settings.RedirectDNS = b, Global.Settings.RedirectDNS);
|
||||
|
||||
BindTextBox(ModifiedDNSTextBox, s => DnsUtils.TrySplit(s, out _, 2), s => Global.Settings.ModifiedDNS = s, Global.Settings.ModifiedDNS);
|
||||
BindTextBox(RDRDNSTextBox, s => DnsUtils.TrySplit(s, out _, 2), s => Global.Settings.RedirectDNSAddr = s, Global.Settings.RedirectDNSAddr);
|
||||
|
||||
BindCheckBox(ICMPRedirectorCheckBox, b => Global.Settings.RedirectICMP = b, Global.Settings.RedirectICMP);
|
||||
|
||||
BindTextBox(ModifiedICMPTextBox, s => DnsUtils.TrySplit(s, out _, 2), s => Global.Settings.RedirectICMPAddr = s, Global.Settings.RedirectICMPAddr);
|
||||
|
||||
BindCheckBox(RedirectorSSCheckBox, s => Global.Settings.RedirectorSS = s, Global.Settings.RedirectorSS);
|
||||
|
||||
BindCheckBox(ChildProcessHandleCheckBox, s => Global.Settings.ChildProcessHandle = s, Global.Settings.ChildProcessHandle);
|
||||
|
||||
BindListComboBox(ProcessProxyProtocolComboBox,
|
||||
s => Global.Settings.ProcessProxyProtocol = (PortType) Enum.Parse(typeof(PortType), s.ToString(), false),
|
||||
Enum.GetNames(typeof(PortType)).Cast<object>().ToArray(),
|
||||
|
||||
120
Netch/Forms/SettingForm.resx
Normal file
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -30,7 +30,9 @@ namespace Netch
|
||||
/// </summary>
|
||||
private static readonly Lazy<MainForm> LazyMainForm = new(() => new MainForm());
|
||||
|
||||
public static readonly Mutex Mutex = new(false, "Global\\Netch");
|
||||
private static readonly Lazy<Mutex> LazyMutex = new(() => new Mutex(false, "Global\\Netch"));
|
||||
|
||||
public static Mutex Mutex => LazyMutex.Value;
|
||||
|
||||
#if DEBUG
|
||||
public static bool Testing = false;
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Netch.Controllers;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Models
|
||||
@@ -81,27 +82,18 @@ namespace Netch.Models
|
||||
var mode = Global.Modes.FirstOrDefault(m => m!.FullName != null && m.RelativePath!.Equals(relativePath.ToString()));
|
||||
|
||||
if (mode == null)
|
||||
{
|
||||
Logging.Warning($"{relativePath} file included in {Remark} not found");
|
||||
}
|
||||
else if (mode == this)
|
||||
{
|
||||
Logging.Warning("Can't self-reference");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mode.Type != Type)
|
||||
{
|
||||
Logging.Warning($"{mode.Remark}'s mode is not as same as {Remark}'s mode");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mode.Rule.Any(rule => rule.StartsWith("#include")))
|
||||
Logging.Warning("Cannot reference mode that reference other mode");
|
||||
else
|
||||
result.AddRange(mode.FullRule);
|
||||
}
|
||||
}
|
||||
throw new MessageException($"{relativePath} file included in {Remark} not found");
|
||||
|
||||
if (mode == this)
|
||||
throw new MessageException("Can't self-reference");
|
||||
|
||||
if (mode.Type != Type)
|
||||
throw new MessageException($"{mode.Remark}'s mode is not as same as {Remark}'s mode");
|
||||
|
||||
if (mode.Rule.Any(rule => rule.StartsWith("#include")))
|
||||
throw new Exception("Cannot reference mode that reference other mode");
|
||||
|
||||
result.AddRange(mode.FullRule);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -102,11 +102,6 @@ namespace Netch.Models
|
||||
|
||||
public AioDNSConfig AioDNS { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 是否使用DLL启动Shadowsocks
|
||||
/// </summary>
|
||||
public bool BootShadowsocksFromDLL { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 全局绕过 IP 列表
|
||||
/// </summary>
|
||||
@@ -158,14 +153,24 @@ namespace Netch.Models
|
||||
public int ModeComboBoxSelectedIndex { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 要修改为的系统 DNS
|
||||
/// 转发DNS地址
|
||||
/// </summary>
|
||||
public string ModifiedDNS { get; set; } = "1.1.1.1,8.8.8.8";
|
||||
public string RedirectDNSAddr { get; set; } = "8.8.8.8";
|
||||
|
||||
/// <summary>
|
||||
/// 修改系统 DNS
|
||||
/// 是否开启DNS转发
|
||||
/// </summary>
|
||||
public bool ModifySystemDNS { get; set; } = false;
|
||||
public bool RedirectDNS { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 转发ICMP地址
|
||||
/// </summary>
|
||||
public string RedirectICMPAddr { get; set; } = "1.2.4.8";
|
||||
|
||||
/// <summary>
|
||||
/// 是否开启ICMP转发
|
||||
/// </summary>
|
||||
public bool RedirectICMP { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// GFWList
|
||||
@@ -202,6 +207,11 @@ namespace Netch.Models
|
||||
/// </summary>
|
||||
public bool RedirectorSS { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否代理子进程
|
||||
/// </summary>
|
||||
public bool ChildProcessHandle { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Redirector TCP 占用端口
|
||||
/// </summary>
|
||||
@@ -272,11 +282,6 @@ namespace Netch.Models
|
||||
/// </summary>
|
||||
public TUNTAPConfig TUNTAP { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// UDP Socket 占用端口
|
||||
/// </summary>
|
||||
public ushort UDPSocketPort { get; set; } = 18291;
|
||||
|
||||
/// <summary>
|
||||
/// 是否打开软件时更新订阅
|
||||
/// </summary>
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Controllers;
|
||||
using Netch.Forms;
|
||||
using Netch.Utils;
|
||||
using Vanara.PInvoke;
|
||||
using static Vanara.PInvoke.User32;
|
||||
|
||||
namespace Netch
|
||||
{
|
||||
@@ -42,8 +46,7 @@ namespace Netch
|
||||
// 检查是否已经运行
|
||||
if (!Global.Mutex.WaitOne(0, false))
|
||||
{
|
||||
OnlyInstance.Send(OnlyInstance.Commands.Show);
|
||||
Logging.Info("唤起单实例");
|
||||
ShowOpened();
|
||||
|
||||
// 退出进程
|
||||
Environment.Exit(1);
|
||||
@@ -72,11 +75,6 @@ namespace Netch
|
||||
|
||||
Logging.Info($"版本: {UpdateChecker.Owner}/{UpdateChecker.Repo}@{UpdateChecker.Version}");
|
||||
Task.Run(() => { Logging.Info($"主程序 SHA256: {Utils.Utils.SHA256CheckSum(Global.NetchExecutable)}"); });
|
||||
Task.Run(() =>
|
||||
{
|
||||
Logging.Info("启动单实例");
|
||||
OnlyInstance.Server();
|
||||
});
|
||||
|
||||
// 绑定错误捕获
|
||||
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
|
||||
@@ -92,5 +90,41 @@ namespace Netch
|
||||
Logging.Error(e.Exception.ToString());
|
||||
Utils.Utils.Open(Logging.LogFile);
|
||||
}
|
||||
|
||||
private static void ShowOpened()
|
||||
{
|
||||
HWND GetWindowHandleByPidAndTitle(int process, string title)
|
||||
{
|
||||
var sb = new StringBuilder(256);
|
||||
HWND pLast = IntPtr.Zero;
|
||||
do
|
||||
{
|
||||
pLast = FindWindowEx(HWND.NULL, pLast, null, null);
|
||||
GetWindowThreadProcessId(pLast, out var id);
|
||||
if (id != process)
|
||||
continue;
|
||||
|
||||
if (GetWindowText(pLast, sb, sb.Capacity) <= 0)
|
||||
continue;
|
||||
|
||||
if (sb.ToString().Equals(title))
|
||||
return pLast;
|
||||
} while (pLast != IntPtr.Zero);
|
||||
|
||||
return HWND.NULL;
|
||||
}
|
||||
|
||||
var self = Process.GetCurrentProcess();
|
||||
var activeProcess = Process.GetProcessesByName("Netch").Single(p => p.Id != self.Id);
|
||||
HWND handle = activeProcess.MainWindowHandle;
|
||||
if (handle.IsNull)
|
||||
handle = GetWindowHandleByPidAndTitle(activeProcess.Id, "Netch");
|
||||
|
||||
if (handle.IsNull)
|
||||
return;
|
||||
|
||||
ShowWindow(handle, ShowWindowCommand.SW_NORMAL);
|
||||
SwitchToThisWindow(handle, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,7 @@
|
||||
<PackageReference Include="Vanara.PInvoke.User32" Version="3.3.5" />
|
||||
<PackageReference Include="WindowsFirewallHelper" Version="2.0.4.70-beta2" />
|
||||
<PackageReference Include="WindowsJobAPI" Version="5.0.1" />
|
||||
<PackageReference Include="WindowsProxy" Version="5.0.0" />
|
||||
<PackageReference Include="WindowsProxy" Version="5.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
|
||||
|
||||
@@ -165,6 +165,9 @@
|
||||
"SS DLL": "SS DLL",
|
||||
"Modify System DNS": "修改系统 DNS",
|
||||
"Proxy Protocol": "代理协议",
|
||||
"DNS Redirector": "DNS转发",
|
||||
"ICMP Redirector": "ICMP转发",
|
||||
"Child Process Handle": "子进程代理",
|
||||
"ProfileCount": "快捷配置数量",
|
||||
"Delay test after start": "启动后延迟测试",
|
||||
"ServerPingType": "测速方式",
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Netch.Controllers;
|
||||
using Netch.Models;
|
||||
using Netch.Utils;
|
||||
|
||||
namespace Netch.Servers.Shadowsocks
|
||||
{
|
||||
public class SSController : Guard, IServerController
|
||||
{
|
||||
public bool DllFlag;
|
||||
|
||||
public override string MainFile { get; protected set; } = "Shadowsocks.exe";
|
||||
|
||||
protected override IEnumerable<string> StartedKeywords { get; } = new[] {"listening at"};
|
||||
@@ -28,35 +24,6 @@ namespace Netch.Servers.Shadowsocks
|
||||
{
|
||||
var server = (Shadowsocks) s;
|
||||
|
||||
DllFlag = Global.Settings.BootShadowsocksFromDLL && mode.Type is 0 or 1 or 2 && !server.HasPlugin();
|
||||
|
||||
//从DLL启动Shaowsocks
|
||||
if (DllFlag)
|
||||
{
|
||||
State = State.Starting;
|
||||
var client = Encoding.UTF8.GetBytes($"{this.LocalAddress()}:{this.Socks5LocalPort()}");
|
||||
var remote = Encoding.UTF8.GetBytes($"{server.AutoResolveHostname()}:{server.Port}");
|
||||
var passwd = Encoding.UTF8.GetBytes($"{server.Password}");
|
||||
var method = Encoding.UTF8.GetBytes($"{server.EncryptMethod}");
|
||||
if (!ShadowsocksDLL.Info(client, remote, passwd, method))
|
||||
{
|
||||
State = State.Stopped;
|
||||
throw new MessageException("DLL SS INFO 设置失败!");
|
||||
}
|
||||
|
||||
Logging.Info("DLL SS INFO 设置成功!");
|
||||
|
||||
if (!ShadowsocksDLL.Start())
|
||||
{
|
||||
State = State.Stopped;
|
||||
throw new MessageException("DLL SS 启动失败!");
|
||||
}
|
||||
|
||||
Logging.Info("DLL SS 启动成功!");
|
||||
State = State.Started;
|
||||
return;
|
||||
}
|
||||
|
||||
#region Argument
|
||||
|
||||
var argument = new StringBuilder();
|
||||
@@ -76,22 +43,7 @@ namespace Netch.Servers.Shadowsocks
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
if (DllFlag)
|
||||
ShadowsocksDLL.Stop();
|
||||
else
|
||||
StopInstance();
|
||||
}
|
||||
|
||||
private class ShadowsocksDLL
|
||||
{
|
||||
[DllImport("shadowsocks-windows-dynamic", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool Info(byte[] client, byte[] remote, byte[] passwd, byte[] method);
|
||||
|
||||
[DllImport("shadowsocks-windows-dynamic", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool Start();
|
||||
|
||||
[DllImport("shadowsocks-windows-dynamic", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,7 +76,7 @@ namespace Netch.Servers.Shadowsocks
|
||||
|
||||
public IEnumerable<Server> ParseSsdUri(string s)
|
||||
{
|
||||
var json = JsonSerializer.Deserialize<Main>(ShareLink.URLSafeBase64Decode(s.Substring(6)));
|
||||
var json = JsonSerializer.Deserialize<Main>(ShareLink.URLSafeBase64Decode(s.Substring(6)))!;
|
||||
|
||||
return json.servers.Select(server => new Shadowsocks
|
||||
{
|
||||
|
||||
@@ -97,7 +97,7 @@ namespace Netch.Servers.VMess
|
||||
|
||||
if (data.TransferProtocol == "quic")
|
||||
{
|
||||
if (VMessGlobal.QUIC.Contains(vmess.host))
|
||||
if (VMessGlobal.QUIC.Contains(vmess.host!))
|
||||
{
|
||||
data.QUICSecure = vmess.host;
|
||||
data.QUICSecret = vmess.path;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Controllers;
|
||||
using Netch.Properties;
|
||||
using Netch.Utils;
|
||||
@@ -14,65 +14,140 @@ namespace Netch.Updater
|
||||
{
|
||||
public class Updater
|
||||
{
|
||||
private static IEnumerable<string> _keepDirectory = new List<string>(new[] {"data", "mode\\Custom"});
|
||||
private readonly string _targetPath;
|
||||
private readonly string _tempFolder;
|
||||
private readonly string _updateFilePath;
|
||||
#region Download Update and apply update
|
||||
|
||||
private Updater(string updateFilePath, string targetPath)
|
||||
/// <summary>
|
||||
/// Download Update and apply update (all arguments are FullPath)
|
||||
/// </summary>
|
||||
/// <param name="downloadDirectory"></param>
|
||||
/// <param name="installDirectory"></param>
|
||||
/// <param name="onDownloadProgressChanged"></param>
|
||||
/// <param name="keyword"></param>
|
||||
/// <exception cref="MessageException"></exception>
|
||||
public static void DownloadAndUpdate(string downloadDirectory,
|
||||
string installDirectory,
|
||||
DownloadProgressChangedEventHandler onDownloadProgressChanged,
|
||||
string? keyword = null)
|
||||
{
|
||||
_targetPath = targetPath;
|
||||
_tempFolder = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
|
||||
Directory.CreateDirectory(_tempFolder);
|
||||
UpdateChecker.GetLatestUpdateFileNameAndHash(out var updateFileName, out var sha256, keyword);
|
||||
|
||||
_updateFilePath = Path.GetFullPath(updateFilePath);
|
||||
_keepDirectory = _keepDirectory.Select(s => Path.Combine(targetPath, s));
|
||||
// update file Full Path
|
||||
var updateFile = Path.Combine(downloadDirectory, updateFileName);
|
||||
var updater = new Updater(updateFile, installDirectory);
|
||||
|
||||
if (File.Exists(updateFile))
|
||||
{
|
||||
if (Utils.Utils.SHA256CheckSum(updateFile) == sha256)
|
||||
{
|
||||
updater.ApplyUpdate();
|
||||
return;
|
||||
}
|
||||
|
||||
File.Delete(updateFile);
|
||||
}
|
||||
|
||||
DownloadUpdateFile(onDownloadProgressChanged, updateFile, sha256);
|
||||
updater.ApplyUpdate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Download Update File
|
||||
/// </summary>
|
||||
/// <param name="onDownloadProgressChanged"></param>
|
||||
/// <param name="fileFullPath"></param>
|
||||
/// <param name="sha256"></param>
|
||||
/// <exception cref="MessageException"></exception>
|
||||
private static void DownloadUpdateFile(DownloadProgressChangedEventHandler onDownloadProgressChanged, string fileFullPath, string sha256)
|
||||
{
|
||||
using WebClient client = new();
|
||||
try
|
||||
{
|
||||
client.DownloadProgressChanged += onDownloadProgressChanged;
|
||||
client.DownloadFile(new Uri(UpdateChecker.LatestRelease.assets[0].browser_download_url), fileFullPath);
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.DownloadProgressChanged -= onDownloadProgressChanged;
|
||||
}
|
||||
|
||||
if (Utils.Utils.SHA256CheckSum(fileFullPath) != sha256)
|
||||
throw new MessageException(i18N.Translate("The downloaded file has the wrong hash"));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private readonly string _updateFile;
|
||||
private readonly string _installDirectory;
|
||||
private readonly string _tempDirectory;
|
||||
|
||||
private Updater(string updateFile, string installDirectory)
|
||||
{
|
||||
_updateFile = updateFile;
|
||||
_installDirectory = installDirectory;
|
||||
_tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
|
||||
|
||||
Directory.CreateDirectory(_tempDirectory);
|
||||
}
|
||||
|
||||
#region Apply Update
|
||||
|
||||
private static readonly ImmutableArray<string> KeepDirectories = new List<string> {"data", "mode\\Custom"}.ToImmutableArray();
|
||||
|
||||
private void ApplyUpdate()
|
||||
{
|
||||
var extractPath = Path.Combine(_tempFolder, "extract");
|
||||
// extract Update file to {tempDirectory}\extract
|
||||
var extractPath = Path.Combine(_tempDirectory, "extract");
|
||||
int exitCode;
|
||||
if ((exitCode = Extract(extractPath, true)) != 0)
|
||||
throw new Exception(i18N.Translate($"7za exit with code {exitCode}"));
|
||||
|
||||
// rename install directory files with .old suffix unless in keep folders
|
||||
MarkFilesOld();
|
||||
|
||||
MoveAllFilesOver(Path.Combine(extractPath, "Netch"), _targetPath);
|
||||
// move {tempDirectory}\extract\Netch to install folder
|
||||
MoveAllFilesOver(Path.Combine(extractPath, "Netch"), _installDirectory);
|
||||
|
||||
// save, release mutex, then exit
|
||||
Configuration.Save();
|
||||
Global.Mutex.ReleaseMutex();
|
||||
Global.MainForm.Invoke(new Action(() => { Global.Mutex.ReleaseMutex(); }));
|
||||
Process.Start(Global.NetchExecutable);
|
||||
Global.MainForm.Exit(true, false);
|
||||
}
|
||||
|
||||
private void MarkFilesOld()
|
||||
{
|
||||
foreach (var file in Directory.GetFiles(_targetPath, "*", SearchOption.AllDirectories))
|
||||
// extend keepDirectories relative path to absolute path
|
||||
var extendedKeepDirectories = KeepDirectories.Select(d => Path.Combine(_installDirectory, d)).ToImmutableArray();
|
||||
|
||||
// weed out keep files
|
||||
List<string> filesToDelete = new();
|
||||
foreach (var file in Directory.GetFiles(_installDirectory, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
if (_keepDirectory.Any(p => file.StartsWith(p)))
|
||||
if (extendedKeepDirectories.Any(p => file.StartsWith(p)))
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
File.Move(file, file + ".old");
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new Exception("Updater wasn't able to rename file: " + file);
|
||||
}
|
||||
if (Path.GetFileName(file) is ModeHelper.DISABLE_MODE_DIRECTORY_FILENAME)
|
||||
continue;
|
||||
|
||||
filesToDelete.Add(file);
|
||||
}
|
||||
|
||||
// rename files
|
||||
foreach (var file in filesToDelete)
|
||||
File.Move(file, file + ".old");
|
||||
}
|
||||
|
||||
private int Extract(string destDirName, bool overwrite)
|
||||
{
|
||||
var temp7za = Path.Combine(_tempFolder, "7za.exe");
|
||||
// release 7za.exe to {tempDirectory}\7za.exe
|
||||
var temp7za = Path.Combine(_tempDirectory, "7za.exe");
|
||||
|
||||
if (!File.Exists(temp7za))
|
||||
File.WriteAllBytes(temp7za, Resources._7za);
|
||||
|
||||
// run 7za
|
||||
var argument = new StringBuilder();
|
||||
argument.Append($" x \"{_updateFilePath}\" -o\"{destDirName}\"");
|
||||
argument.Append($" x \"{_updateFile}\" -o\"{destDirName}\"");
|
||||
if (overwrite)
|
||||
argument.Append(" -y");
|
||||
|
||||
@@ -108,6 +183,10 @@ namespace Netch.Updater
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Clean files marked as old when start
|
||||
|
||||
public static void CleanOld(string targetPath)
|
||||
{
|
||||
foreach (var f in Directory.GetFiles(targetPath, "*.old", SearchOption.AllDirectories))
|
||||
@@ -121,40 +200,6 @@ namespace Netch.Updater
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task DownloadAndUpdate(string downloadPath,
|
||||
string targetPath,
|
||||
DownloadProgressChangedEventHandler onDownloadProgressChanged)
|
||||
{
|
||||
var keyword = (string?) null;
|
||||
|
||||
if (!UpdateChecker.GetFileNameAndHashFromMarkdownForm(UpdateChecker.LatestRelease.body, out var fileName, out var sha256, keyword))
|
||||
throw new Exception(i18N.Translate("parse release note failed"));
|
||||
|
||||
var fileFullPath = Path.Combine(downloadPath, fileName);
|
||||
var updater = new Updater(fileFullPath, targetPath);
|
||||
|
||||
if (!(File.Exists(fileFullPath) && Utils.Utils.SHA256CheckSum(fileFullPath) == sha256))
|
||||
{
|
||||
using WebClient client = new();
|
||||
try
|
||||
{
|
||||
client.DownloadProgressChanged += onDownloadProgressChanged;
|
||||
await client.DownloadFileTaskAsync(new Uri(UpdateChecker.LatestRelease.assets[0].browser_download_url), fileFullPath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Exception(i18N.Translate("Download Update Failed", ": ") + e.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.DownloadProgressChanged -= onDownloadProgressChanged;
|
||||
}
|
||||
|
||||
if (Utils.Utils.SHA256CheckSum(fileFullPath) != sha256)
|
||||
throw new Exception(i18N.Translate("The downloaded file has the wrong hash"));
|
||||
}
|
||||
|
||||
updater.ApplyUpdate();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -57,9 +57,6 @@ namespace Netch.Utils
|
||||
{
|
||||
case null:
|
||||
break;
|
||||
case SSController {DllFlag: true}:
|
||||
instances.Add(Process.GetCurrentProcess());
|
||||
break;
|
||||
case Guard instanceController:
|
||||
if (instanceController.Instance != null)
|
||||
instances.Add(instanceController.Instance);
|
||||
|
||||
@@ -53,8 +53,7 @@ namespace Netch.Utils
|
||||
|
||||
#region Check Profile
|
||||
|
||||
foreach (var profile in settings.Profiles.Where(p => p.ServerRemark == string.Empty || p.ModeRemark == string.Empty)!)
|
||||
settings.Profiles.Remove(profile);
|
||||
settings.Profiles.RemoveAll(p => p.ServerRemark == string.Empty || p.ModeRemark == string.Empty);
|
||||
|
||||
if (settings.Profiles.Any(p => settings.Profiles.Any(p1 => p1 != p && p1.Index == p.Index)))
|
||||
for (var i = 0; i < settings.Profiles.Count; i++)
|
||||
@@ -67,7 +66,9 @@ namespace Netch.Utils
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Error(e.ToString());
|
||||
return new Setting();
|
||||
Utils.Open(Logging.LogFile);
|
||||
Environment.Exit(-1);
|
||||
return null!;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,15 +14,15 @@ namespace Netch.Utils.HttpProxyHandler
|
||||
{
|
||||
private static HttpWebServer? _httpWebServer;
|
||||
private static string? _pacContent;
|
||||
public static readonly string PacPrefix= $"http://127.0.0.1:{Global.Settings.Pac_Port}/pac/";
|
||||
|
||||
public static string InitPACServer(string address)
|
||||
public static string InitPACServer()
|
||||
{
|
||||
try
|
||||
{
|
||||
_pacContent = GetPacList(address);
|
||||
var prefixes = $"http://{address}:{Global.Settings.Pac_Port}/pac/";
|
||||
_pacContent = GetPacList("127.0.0.1");
|
||||
|
||||
_httpWebServer = new HttpWebServer(SendResponse, prefixes);
|
||||
_httpWebServer = new HttpWebServer(SendResponse, PacPrefix);
|
||||
Task.Run(() => _httpWebServer.StartWaitingRequest());
|
||||
|
||||
var pacUrl = GetPacUrl();
|
||||
@@ -77,7 +77,7 @@ namespace Netch.Utils.HttpProxyHandler
|
||||
/// <returns></returns>
|
||||
public static string GetPacUrl()
|
||||
{
|
||||
return $"http://127.0.0.1:{Global.Settings.Pac_Port}/pac/?t={DateTime.Now:yyyyMMddHHmmssfff}";
|
||||
return PacPrefix + $"?t={DateTime.Now:yyyyMMddHHmmssfff}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Netch.Controllers;
|
||||
@@ -12,6 +11,7 @@ namespace Netch.Utils
|
||||
public static class ModeHelper
|
||||
{
|
||||
private const string MODE_DIR = "mode";
|
||||
public const string DISABLE_MODE_DIRECTORY_FILENAME = "disabled";
|
||||
|
||||
public static readonly string ModeDirectory = Path.Combine(Global.NetchDir, $"{MODE_DIR}\\");
|
||||
|
||||
@@ -25,43 +25,37 @@ namespace Netch.Utils
|
||||
return Path.Combine(ModeDirectory, relativeName);
|
||||
}
|
||||
|
||||
public static string GetFullPath(Mode mode)
|
||||
{
|
||||
return Path.Combine(ModeDirectory, mode.RelativePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从模式文件夹读取模式并为 <see cref="Forms.MainForm.ModeComboBox" /> 绑定数据
|
||||
/// 从模式文件夹读取模式
|
||||
/// </summary>
|
||||
public static void Load()
|
||||
{
|
||||
Global.Modes.Clear();
|
||||
|
||||
if (!Directory.Exists(MODE_DIR))
|
||||
return;
|
||||
|
||||
var stack = new Stack<string>();
|
||||
stack.Push(MODE_DIR);
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
var dirInfo = new DirectoryInfo(stack.Pop());
|
||||
try
|
||||
{
|
||||
foreach (var childDirInfo in dirInfo.GetDirectories())
|
||||
stack.Push(childDirInfo.FullName);
|
||||
|
||||
foreach (var childFileInfo in dirInfo.GetFiles().Where(info => info.Name.EndsWith(".txt")))
|
||||
LoadModeFile(childFileInfo.FullName);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
LoadModeDirectory(ModeDirectory);
|
||||
|
||||
Sort();
|
||||
}
|
||||
|
||||
private static void LoadModeDirectory(string modeDirectory)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var directory in Directory.GetDirectories(modeDirectory))
|
||||
LoadModeDirectory(directory);
|
||||
|
||||
// skip Directory with a disabled file in
|
||||
if (File.Exists(Path.Combine(modeDirectory, DISABLE_MODE_DIRECTORY_FILENAME)))
|
||||
return;
|
||||
|
||||
foreach (var file in Directory.GetFiles(modeDirectory).Where(f => f.EndsWith(".txt")))
|
||||
LoadModeFile(file);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
private static void LoadModeFile(string fullName)
|
||||
{
|
||||
var mode = new Mode(fullName);
|
||||
@@ -119,9 +113,11 @@ namespace Netch.Utils
|
||||
|
||||
public static void Delete(Mode mode)
|
||||
{
|
||||
var fullName = GetFullPath(mode);
|
||||
if (File.Exists(fullName))
|
||||
File.Delete(fullName);
|
||||
if (mode.FullName == null)
|
||||
throw new ArgumentException("FullName");
|
||||
|
||||
if (File.Exists(mode.FullName))
|
||||
File.Delete(mode.FullName);
|
||||
|
||||
Global.Modes.Remove(mode);
|
||||
Global.MainForm.LoadModes();
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Netch.Utils
|
||||
{
|
||||
public static class OnlyInstance
|
||||
{
|
||||
public enum Commands
|
||||
{
|
||||
Show,
|
||||
Exit
|
||||
}
|
||||
|
||||
public static event EventHandler<Commands>? Called;
|
||||
|
||||
private static void OnCalled(Commands e)
|
||||
{
|
||||
Called?.Invoke(null, e);
|
||||
}
|
||||
|
||||
public static async void Server()
|
||||
{
|
||||
try
|
||||
{
|
||||
const int tryLimit = 3;
|
||||
var i = tryLimit;
|
||||
while (i > 0)
|
||||
try
|
||||
{
|
||||
PortHelper.CheckPort(Global.Settings.UDPSocketPort, PortType.UDP);
|
||||
if (i != tryLimit)
|
||||
Configuration.Save();
|
||||
|
||||
break;
|
||||
}
|
||||
catch
|
||||
{
|
||||
Global.Settings.UDPSocketPort = PortHelper.GetAvailablePort(PortType.UDP);
|
||||
i--;
|
||||
}
|
||||
|
||||
var data = new byte[1024];
|
||||
var newsock = new UdpClient(new IPEndPoint(IPAddress.Loopback, Global.Settings.UDPSocketPort));
|
||||
|
||||
while (true)
|
||||
{
|
||||
var result = await newsock.ReceiveAsync();
|
||||
data = result.Buffer;
|
||||
if (Enum.TryParse<Commands>(Encoding.ASCII.GetString(data, 0, data.Length), out var command))
|
||||
OnCalled(command);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Error(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public static async void Send(Commands command)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var udpClient = new UdpClient(new IPEndPoint(IPAddress.Loopback, Global.Settings.UDPSocketPort));
|
||||
udpClient.Connect(IPAddress.Loopback, Global.Settings.UDPSocketPort);
|
||||
var sendBytes = Encoding.ASCII.GetBytes(command.ToString());
|
||||
await udpClient.SendAsync(sendBytes, sendBytes.Length);
|
||||
|
||||
udpClient.Close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,8 +46,22 @@ namespace Netch.Utils
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
var errorFlag = false;
|
||||
foreach (var line in text.GetLines())
|
||||
list.AddRange(ParseUri(line));
|
||||
{
|
||||
try
|
||||
{
|
||||
list.AddRange(ParseUri(line));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
errorFlag = true;
|
||||
Logging.Error(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
if (errorFlag)
|
||||
Utils.Open(Logging.LogFile);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -61,30 +75,22 @@ namespace Netch.Utils
|
||||
{
|
||||
var list = new List<Server>();
|
||||
|
||||
try
|
||||
if (text.StartsWith("tg://socks?") || text.StartsWith("https://t.me/socks?"))
|
||||
{
|
||||
if (text.StartsWith("tg://socks?") || text.StartsWith("https://t.me/socks?"))
|
||||
{
|
||||
list.AddRange(ServerHelper.GetUtilByTypeName("Socks5").ParseUri(text));
|
||||
}
|
||||
else if (text.StartsWith("Netch://"))
|
||||
{
|
||||
list.Add(ParseNetchUri(text));
|
||||
}
|
||||
else
|
||||
{
|
||||
var scheme = GetUriScheme(text);
|
||||
var util = ServerHelper.GetUtilByUriScheme(scheme);
|
||||
if (util != null)
|
||||
list.AddRange(util.ParseUri(text));
|
||||
else
|
||||
Logging.Warning($"无法处理 {scheme} 协议订阅链接");
|
||||
}
|
||||
list.AddRange(ServerHelper.GetUtilByTypeName("Socks5").ParseUri(text));
|
||||
}
|
||||
catch (Exception e)
|
||||
else if (text.StartsWith("Netch://"))
|
||||
{
|
||||
Logging.Error(e.ToString());
|
||||
Utils.Open(Logging.LogFile);
|
||||
list.Add(ParseNetchUri(text));
|
||||
}
|
||||
else
|
||||
{
|
||||
var scheme = GetUriScheme(text);
|
||||
var util = ServerHelper.GetUtilByUriScheme(scheme);
|
||||
if (util != null)
|
||||
list.AddRange(util.ParseUri(text));
|
||||
else
|
||||
Logging.Warning($"无法处理 {scheme} 协议订阅链接");
|
||||
}
|
||||
|
||||
foreach (var node in list.Where(node => !node.Remark.IsNullOrWhiteSpace()))
|
||||
|
||||
@@ -48,8 +48,9 @@ namespace Netch.Utils
|
||||
var sb = new StringBuilder();
|
||||
foreach (var t in value)
|
||||
{
|
||||
if (new[] {'\\', '(', ')', '[', ']', '.'}.Any(s => s == t))
|
||||
sb.Append(@"\");
|
||||
var escapeCharacters = new[] {'\\', '*', '+', '?', '|', '{', '}', '[', ']', '(', ')', '^', '$', '.'};
|
||||
if (escapeCharacters.Any(s => s == t))
|
||||
sb.Append('\\');
|
||||
|
||||
sb.Append(t);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Netch.Utils
|
||||
break;
|
||||
}
|
||||
|
||||
var dictionary = JsonSerializer.Deserialize<Dictionary<string, string>>(text);
|
||||
var dictionary = JsonSerializer.Deserialize<Dictionary<string, string>>(text)!;
|
||||
|
||||
if (!dictionary.Any())
|
||||
{
|
||||
|
||||
11
README.md
@@ -7,9 +7,9 @@
|
||||
[](https://github.com/NetchX/Netch/actions)
|
||||
[](LICENSE)
|
||||
|
||||
[中文说明](/docs/README.zh-CN.md)
|
||||
[文档网站](https://netch.org/) [常见问题](https://netch.org/#/docs/zh-CN/faq)
|
||||
|
||||
[常见问题](https://netch.org/#/docs/zh-CN/faq)
|
||||
[中文说明](README.zh-CN.md)
|
||||
|
||||
Game network accelerator
|
||||
|
||||
@@ -31,12 +31,12 @@ Currently supports the following protocols
|
||||
- ShadowsocksR
|
||||
- Trojan
|
||||
- VMess
|
||||
- VLess
|
||||
- VLESS
|
||||
|
||||
As well, Netch avoid the restricted NAT problem caused by SSTap. You can use an NATTypeTester to test out what your NAT type is. When using SSTap to speed up some P2P gaming connections or the game is required for that kind of open NAT type, you may experience some bad situations such as unable to join the game
|
||||
|
||||
## Sponsor
|
||||
<a href="https://www.jetbrains.com/?from=Netch"><img src=".github/jetbrains-variant-4.svg" alt="JetBrains" width="200"/></a>
|
||||
<a href="https://www.jetbrains.com/?from=Netch"><img src="images/jetbrains-variant-4.svg" alt="JetBrains" width="200"/></a>
|
||||
|
||||
- [RabbitHosts](https://rabbithosts.com/cart.php)
|
||||
- [ManSora](https://www.mansora.co/cart.php)
|
||||
@@ -46,7 +46,7 @@ As well, Netch avoid the restricted NAT problem caused by SSTap. You can use an
|
||||
- XMR *48ju3ELNZEa6wwPBMexCJ9G218BGY2XwhH6B6bmkFuJ3QgM4hPw2Pra35jPtuBZSc7SLNWeBpiWJZWjQeMAiLnTx2tH2Efx*
|
||||
|
||||
## Screenshots
|
||||

|
||||

|
||||
|
||||
## Requirements
|
||||
- [.NET Framework 4.8 (Included in Windows 10 1903+)](https://dotnet.microsoft.com/download/dotnet-framework/net48)
|
||||
@@ -67,5 +67,6 @@ As well, Netch avoid the restricted NAT problem caused by SSTap. You can use an
|
||||
- [Privoxy](https://www.privoxy.org/)
|
||||
- [NatTypeTester](https://github.com/HMBSbige/NatTypeTester)
|
||||
- [NetFilter SDK](https://netfiltersdk.com/)
|
||||
- [pcap2socks](https://github.com/zhxie/pcap2socks)
|
||||
|
||||
[](https://starchart.cc/NetchX/Netch)
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
[](https://github.com/NetchX/Netch/actions)
|
||||
[](LICENSE)
|
||||
|
||||
游戏加速工具
|
||||
[文档网站](https://netch.org/) [常见问题](https://netch.org/#/docs/zh-CN/faq)
|
||||
|
||||
[网站](https://netch.org/)
|
||||
游戏加速工具
|
||||
|
||||
## TOC
|
||||
- [Netch](#Netch)
|
||||
@@ -17,8 +17,6 @@
|
||||
- [简介](#简介)
|
||||
- [赞助商](#赞助商)
|
||||
- [捐赠](#捐赠)
|
||||
- [新手入门](Quickstart.zh-CN.md)
|
||||
- [进阶用法](Advanced_Usage.zh-CN.md)
|
||||
- [依赖](#依赖)
|
||||
- [语言支持](#语言支持)
|
||||
|
||||
@@ -31,15 +29,12 @@ Netch 是一款 Windows 平台的开源游戏加速工具,Netch 可以实现
|
||||
- ShadowsocksR
|
||||
- Trojan
|
||||
- VMess
|
||||
- VLess
|
||||
- VLESS
|
||||
|
||||
与此同时 Netch 避免了 SSTap 的 NAT 问题 ,检查 NAT 类型即可知道是否有 NAT 问题。使用 SSTap 加速部分 P2P 联机,对 NAT 类型有要求的游戏时,可能会因为 NAT 类型严格遇到无法加入联机,或者其他影响游戏体验的情况
|
||||
|
||||
|
||||
需要更多特性请移步魔改仓库 [Netch-ForOwnUse](https://github.com/AmazingDM/Netch-ForOwnUse),
|
||||
|
||||
## 赞助商
|
||||
<a href="https://www.jetbrains.com/?from=Netch"><img src="../.github/jetbrains-variant-4.svg" alt="JetBrains" width="200"/></a>
|
||||
<a href="https://www.jetbrains.com/?from=Netch"><img src="images/jetbrains-variant-4.svg" alt="JetBrains" width="200"/></a>
|
||||
|
||||
- [RabbitHosts](https://rabbithosts.com/cart.php)
|
||||
- [ManSora](https://www.mansora.co/cart.php)
|
||||
@@ -48,16 +43,13 @@ Netch 是一款 Windows 平台的开源游戏加速工具,Netch 可以实现
|
||||
## 捐赠
|
||||
- XMR *48ju3ELNZEa6wwPBMexCJ9G218BGY2XwhH6B6bmkFuJ3QgM4hPw2Pra35jPtuBZSc7SLNWeBpiWJZWjQeMAiLnTx2tH2Efx*
|
||||
|
||||
## 新手入门
|
||||
[新手入门教程](Quickstart.zh-CN.md)
|
||||
|
||||
## 进阶用法
|
||||
[进阶教程](Advanced_Usage.zh-CN.md)
|
||||
## 依赖
|
||||
- [.NET Framework 4.8 (Windows 10 1903+ 已包含)](https://dotnet.microsoft.com/download/dotnet-framework/thank-you/net48-offline-installer)
|
||||
|
||||
## 语言支持
|
||||
Netch 支持多种语言,在启动时会根据系统语言选择自身语言。如果需要手动切换语言,可以在启动时加入命令行参数,命令行参数为目前支持的语言代码,可以去 [NetchTranslation/i18n](https://github.com/NetchX/NetchTranslation/tree/master/i18n) 文件夹下查看外部支持的语言代码文件。Netch 目前内置 en-US,zh-CN,外置 zh-TW。欢迎大家为 [NetchTranslation](https://github.com/NetchX/NetchTranslation) 提供其他语言的翻译
|
||||
Netch 内置 en-US 和 zh-CN,外置 zh-TW 等,默认根据系统语言选择语言。
|
||||
|
||||
[Netch 外置语言仓库](https://github.com/NetchX/NetchTranslation) ,欢迎提供其他语言的翻译
|
||||
|
||||
## 引用
|
||||
- [core](https://github.com/aiocloud/core)
|
||||
@@ -75,3 +67,4 @@ Netch 支持多种语言,在启动时会根据系统语言选择自身语言
|
||||
- [Privoxy](https://www.privoxy.org/)
|
||||
- [NatTypeTester](https://github.com/HMBSbige/NatTypeTester)
|
||||
- [NetFilter SDK](https://netfiltersdk.com/)
|
||||
- [pcap2socks](https://github.com/zhxie/pcap2socks)
|
||||
2
binaries
@@ -1,213 +0,0 @@
|
||||
# Netch 模式
|
||||
|
||||
## 目录
|
||||
|
||||
1. [模式介绍](#模式介绍)
|
||||
- 1.1 [模式 1 进程代理模式](#模式-1-进程代理模式)
|
||||
- 1.2 [模式 2(需要自己新建模式文件) TUN/TAP IP 黑名单代理模式](#模式-2需要自己新建模式文件-tuntap-ip-黑名单代理模式)
|
||||
- 1.3 [模式 3 TUN/TAP (IP 白名单)全局代理模式](#模式-3-tuntap-ip-白名单全局代理模式)
|
||||
- 1.4 [模式 4 HTTP 系统代理](#模式-4-http-系统代理)
|
||||
- 1.5 [模式 5 本地 Socks5 代理](#模式-5-本地-socks5-代理)
|
||||
- 1.6 [模式 6 本地 Socks5 和 HTTP 代理](#模式-6-本地-socks5-和-http-代理)
|
||||
2. [Socks 5 代理中转](#socks-5-代理中转)
|
||||
3. [新建进程代理模式](#新建进程代理模式)
|
||||
- 3.1 [模式](#模式)
|
||||
- 3.2 [扫描](#扫描)
|
||||
- 3.3 [启动](#启动)
|
||||
|
||||
## 模式介绍
|
||||
|
||||
目前 Netch 所有模式文件都在 `mode` 文件夹下。模式号即模式菜单中最左边中括号内数字
|
||||
|
||||
内置的模式中,如果模式名中有 Bypass China 的部分,即该模式会绕过中国 IP 段
|
||||
|
||||
模式 1 和模式 2 里面除了第一行格式不同,其他内容和 [SSTap-Rule](https://github.com/FQrabbit/SSTap-Rule) 相同。是否绕过中国的功能依赖于 [CNIP 文件](https://github.com/NetchX/Netch/blob/master/Netch/Resources/CNIP)
|
||||
|
||||
模式 3 到模式 5 的是否绕过中国的功能依赖于 [acl 文件](https://github.com/NetchX/Netch/blob/master/binaries/default.acl)
|
||||
|
||||
第一行格式均为如下样式,不同模式之间第一行的具体区别可以参照后面的内容
|
||||
|
||||
```Python
|
||||
# 备注, 类型(是主项目 USAGE.zh-CN.md 里提到的模式类型的值减一), 是否绕过中国(1 为是, 0 为否)
|
||||
```
|
||||
|
||||
### 模式 1 进程代理模式
|
||||
|
||||
- 根据进程名进行代理
|
||||
- 底层依赖于 [NetFilter SDK](https://netfiltersdk.com)
|
||||
- 对于第一次使用 Netch 的用户而言,不需要做多余的事情
|
||||
- 若 [NetFilter SDK](https://netfiltersdk.com) 的驱动不存在,会自动安装
|
||||
- 若驱动版本过低,会自动更新
|
||||
|
||||
范例文件
|
||||
|
||||
在这个模式里,第一行只有备注是有用的,规则内容支持C++正则表达式
|
||||
|
||||
```
|
||||
# 备注
|
||||
进程名 1(会被代理)
|
||||
!进程名 2(不会被代理)
|
||||
csgo.exe
|
||||
\\steam\\(代理运行路径包含steam的所有程序)
|
||||
...
|
||||
```
|
||||
|
||||
### 模式 2(需要自己新建模式文件) TUN/TAP IP 黑名单代理模式
|
||||
|
||||
- 黑名单代理指的是,除了名单内的 IP 走代理,其他连接都不走代理
|
||||
- 需要自己新建模式文件,第一行写法同模式 3,只是需要把 2 改成 1
|
||||
- 后续内容的格式同 [SSTap-rules](https://github.com/FQrabbit/SSTap-Rule),任何规则问题建议到那边去提
|
||||
- 可以通过左下角的`设置`来配置 IP 地址,子网掩码,网关,DNS
|
||||
- 该模式下直连 IP 段无效,暂时没有代码实现
|
||||
- 底层依赖于 [Tap-Windows](https://github.com/OpenVPN/tap-windows) 适配器等
|
||||
- 如果 Netch 提示没有该适配器,可以直接安装 [Tap-Windows](https://build.openvpn.net/downloads/releases/latest/tap-windows-latest-stable.exe) 或者通过安装 [OpenVPN](https://openvpn.net/community-downloads/),[SSTap](https://github.com/mayunbaba2/SSTap-beta-setup) 的方式获得该适配器
|
||||
|
||||
范例文件
|
||||
|
||||
在这个模式里,是否绕过中国的值是无效的
|
||||
|
||||
```
|
||||
# 备注, 1
|
||||
无类别域间路由写法 1(目的 IP 在这个子网内的网络请求都会被代理)
|
||||
无类别域间路由写法 2
|
||||
...
|
||||
```
|
||||
|
||||
### 模式 3 TUN/TAP (IP 白名单)全局代理模式
|
||||
|
||||
- 白名单代理指的是,除了名单内的 IP 不走代理,其他连接都走代理
|
||||
- 可以通过左下角的`设置`来配置 IP 地址,子网掩码,网关,DNS,直连 IP 段
|
||||
- 底层依赖于 [Tap-Windows](https://github.com/OpenVPN/tap-windows) 适配器,tun2socks 等
|
||||
- 如果 Netch 提示没有该适配器,可以直接安装 [Tap-Windows](https://build.openvpn.net/downloads/releases/latest/tap-windows-latest-stable.exe) 或者通过安装 [OpenVPN](https://openvpn.net/community-downloads/),[SSTap](https://github.com/mayunbaba2/SSTap-beta-setup) 的方式获得该适配器
|
||||
|
||||
范例文件
|
||||
|
||||
```
|
||||
# 备注, 2, 是否绕过中国(1 为是, 0 为否)
|
||||
无类别域间路由写法 1(目的 IP 只有在这个子网内的网络请求不会被代理,其他的都会被代理)
|
||||
无类别域间路由写法 2
|
||||
...
|
||||
```
|
||||
|
||||
### 模式 4 HTTP 系统代理
|
||||
|
||||
- 默认地址和端口为 127.0.0.1:2802
|
||||
- 端口可以在左下角设置里面更改
|
||||
- 会被设置为系统代理
|
||||
|
||||
范例文件
|
||||
|
||||
```
|
||||
# 备注, 3, 是否绕过中国(1 为是, 0 为否)
|
||||
(目前只有第一行是有效的)
|
||||
```
|
||||
|
||||
### 模式 5 本地 Socks5 代理
|
||||
|
||||
- 默认地址和端口为 127.0.0.1:2801
|
||||
- 端口可以在左下角设置里面更改
|
||||
- 不会被设置为系统代理,对于 Chrome 之类使用系统代理的浏览器需要设置使用插件 SwitchyOmega 之后才能被正常代理
|
||||
- 注意如果是使用 Firefox 的网络设置,请仅设置 Socks5 代理,清除其他代理配置,并取消勾选`为所有协议使用相同的代理服务器`
|
||||
- 其他模式均含 Socks5 代理,本模式可以理解为仅 Socks5 代理\
|
||||
|
||||
范例文件
|
||||
|
||||
```
|
||||
# 备注, 4, 是否绕过中国(1 为是, 0 为否)
|
||||
(目前只有第一行是有效的)
|
||||
```
|
||||
|
||||
### 模式 6 本地 Socks5 和 HTTP 代理
|
||||
|
||||
- Socks5 代理的默认地址和端口为 127.0.0.1:2801
|
||||
- HTTP 代理的默认地址和端口为 127.0.0.1:2802
|
||||
- 端口可以在左下角设置里面更改
|
||||
- 不会被设置为系统代理
|
||||
|
||||
范例文件
|
||||
|
||||
```
|
||||
# 备注, 5, 是否绕过中国(1 为是, 0 为否)
|
||||
(目前只有第一行是有效的)
|
||||
```
|
||||
|
||||
## Socks 5 代理中转
|
||||
|
||||
说明一下,Netch 并非是以网页代理为目的开发的程序,如果需要网络代理为目的的程序,需要 PAC,规则分流,订阅管理等功能的,请尽量参考使用以下软件而非 Netch(均为 Windows 平台)
|
||||
|
||||
ShadowsocksR
|
||||
|
||||
- [HMBSbige/ShadowsocksR-Windows](https://github.com/HMBSbige/ShadowsocksR-Windows/releases)
|
||||
|
||||
Shadowsocks
|
||||
|
||||
- [Clash for Windows](https://github.com/Fndroid/clash_for_windows_pkg/releases)
|
||||
|
||||
V2Ray
|
||||
|
||||
- [V2RayN](https://github.com/2dust/v2rayN/releases)
|
||||
|
||||
如果你想使用的代理工具目前 Netch 还不支持,或者需要一些 Netch 目前没有的功能,如 V2Ray 自定义配置,Socks5 本地代理规则分流的,可以在 Netch 里添加对应工具的本地 Socks5 代理端口后使用,注意如果你用的是模式 3 TUN/TAP (IP 白名单)全局代理模式,记得在`设置 - 全局直连 IP`中添加你的服务器 IP 地址,否则会产生代理回环
|
||||
|
||||
## 新建进程代理模式
|
||||
|
||||
- 现在软件还处在早期开发阶段,可能后续版本会发生很大变化,操作仅供参考
|
||||
|
||||
当前版本已添加配置编辑功能,根据自己的情况,使用订阅或者别的方法添加代理配置,我这里使用的是剪贴板导入
|
||||
|
||||

|
||||
|
||||
如果你发现你的程序没我截图的看起来清晰,可以右键 `Netch.exe - 属性 - 兼容性 - 更改高 DPI 设置 - 替代高 DPI 缩放执行 - 系统(增强)`
|
||||
|
||||
### 模式
|
||||
|
||||
如果你的游戏的模式已经被收录,也可以考虑在模式菜单中,选择使用已收录的模式。所有模式的文件,都在 `./mode/` 文件夹下,如果你需要多个模式的合并文件,可以使用记事本将其打开,将多个文件合并
|
||||
|
||||
ping 的值未必准确,因为这只是你本地到代理服务器而非游戏服务器的延迟
|
||||
|
||||
如果你的游戏的模式没被收录,可以看接下来的扫描步骤来手动创建模式
|
||||
|
||||
接着点击菜单栏上的`模式 - 创建进程模式`
|
||||
|
||||

|
||||
|
||||
### 扫描
|
||||
|
||||
在弹出的窗口中点击`扫描`
|
||||
|
||||

|
||||
|
||||
选择你要加速的游戏的安装路径,根据游戏不同,可能需要选择多个不同的目录进行扫描,参见[萌鹰的 Netch 教程](https://www.eaglemoe.com/archives/142)(包括 GTAOL 和 R6S 的配置方法)
|
||||
|
||||
>4. 选定 GTA5 游戏目录,点击确定,软件会自动扫描目录下的 exe 程式并填写进去
|
||||
>5. 再次点击扫描,选择 SocialClub 的安装地址(一般为 C:\Program Files\Rockstar Games\Social Club),点击确定,点击保存
|
||||
>
|
||||
>注意:加入游戏时请不要忘记加入社交组件,比如说 GTA 不要忘记 SocialClub ,彩虹六号不要忘记 Uplay,如果游戏进程名与其他进程名重复,则可手动修改已创建好的模式文件,在进程名前加上绝对路径即可。csgo.exe -> C:\steam\game\Counter-Strike Global Offensive\csgo.exe
|
||||
|
||||
这里以CSGO为例,只需添加CSGO游戏根目录即可
|
||||
|
||||

|
||||
|
||||
扫描时可能需要稍等片刻,扫描后记得填写备注
|
||||
|
||||
如果需要添加单个程序,也可以在添加按钮左侧的编辑栏中手动输入并添加
|
||||
|
||||
之后点保存进行`保存`
|
||||
|
||||

|
||||
|
||||
### 启动
|
||||
|
||||
最后确认服务器一栏和模式一栏均为之前自己添加并需要使用的,没问题后点击`启动`即可
|
||||
|
||||

|
||||
|
||||
启动后,你再去游戏根目录或者别的启动器如 Steam,Uplay 启动游戏即可。此时游戏就已经被代理了
|
||||
|
||||
如果在 Netch 启动前就启动了游戏,建议重启游戏
|
||||
|
||||
如果需要 Steam,Uplay 等启动器也被代理,参照前面的方式对 Steam,Uplay 根目录也进行扫描即可
|
||||
|
||||
## 语言支持
|
||||
|
||||
Netch 支持多种语言,在启动时会根据系统语言选择自身语言。如果需要手动切换语言,可以在启动时加入命令行参数,命令行参数为目前支持的语言代码,可以去 [NetchTranslation/i18n](https://github.com/NetchX/NetchTranslation/tree/master/i18n) 文件夹下查看外部支持的语言代码文件。Netch 目前内置 en-US,zh-CN,外置 zh-TW。欢迎大家为 [NetchTranslation](https://github.com/NetchX/NetchTranslation) 提供其他语言的翻译
|
||||
@@ -1,48 +0,0 @@
|
||||
# 新手入门
|
||||
**Version : 1.5.1**
|
||||
|
||||
[下载地址](https://github.com/NetchX/Netch/releases)
|
||||
|
||||
## 主界面
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## 设置界面
|
||||
|
||||

|
||||
|
||||
## 添加服务器
|
||||
|
||||
> Netch 目前仅支持以下代理协议:Shadowsocks,VMess,Socks5,ShadowsockR,Trojan。
|
||||
|
||||
首先,点击`服务器`增加所需服务器
|
||||
|
||||
<img width="80%" height="80%" src="screenshots/addServer.zh-CN.png">
|
||||
|
||||
可手动添加单个服务器,或者通过剪切板链接添加单个服务器。也可通过订阅链接批量添加。
|
||||
|
||||
点击 `订阅` ` 管理订阅链接` 进入以下界面。
|
||||
|
||||
<img width="80%" height="80%" src="screenshots/addLink.zh-CN.png">
|
||||
|
||||
填写备注与链接,然后保存即可。保存后在主界面点击 `订阅` ` 从订阅链接更新服务器`。完成服务器添加。添加完服务器后可对服务器进行修改,删除和测速。
|
||||
|
||||
## 选择模式
|
||||
|
||||
> 此处需要会一点英语,比如你应该知道 `吃鸡` 的英文名称是 `PlayerUnknown's Battlegrounds`
|
||||
|
||||
模式选择框有搜索功能,在模式框里输入字符即可搜索,使用英文名称进行搜索,搜索到所需的模式后单击选择,启用模式。相对应的游戏即可被加速
|
||||
|
||||
若没有所需的模式,请选择 `[3] Bypass LAN and China (TUN/TAP)` 的模式。此模式需要安装 [TAP-Windows](https://github.com/OpenVPN/tap-windows) 适配器,如果 Netch 提示没有该适配器,可以直接安装 [TAP-Windows](https://build.openvpn.net/downloads/releases/latest/tap-windows-latest-stable.exe) 来获得该适配器
|
||||
|
||||
关于更多的模式说明,详见 [进阶用法](Advanced_Usage.zh-CN.md)。
|
||||
|
||||
选择完模式后,点击启用,游戏已被代理。这一步需在开启游戏前完成。
|
||||
|
||||
## 配置说明
|
||||
|
||||
在设置界面填写完快捷配置数量后即可在主界面进行配置,填入配置名,选择相应的服务器和游戏模式,按下 `Ctrl` 与鼠标左键,即可保存当前配置。下次使用时,点击配置名即可快速启用。
|
||||
|
||||
~~ 如果你还觉得不会用,可以去用 SSTap (逃~~
|
||||
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |