mirror of
https://github.com/netchx/netch.git
synced 2026-05-11 23:45:06 +08:00
Compare commits
19 Commits
1.8.3-Beta
...
1.8.3-Beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e2bcdc8840 | ||
|
|
4202c8ac5a | ||
|
|
db765d60f0 | ||
|
|
28c248ea70 | ||
|
|
f818c444a4 | ||
|
|
d260afd49b | ||
|
|
66bfe39674 | ||
|
|
95d1b039cd | ||
|
|
b2a7d4fd59 | ||
|
|
ec6b9a2c18 | ||
|
|
dcb90ccdcd | ||
|
|
5da5daa112 | ||
|
|
5d5ee40cd6 | ||
|
|
32d3e97288 | ||
|
|
452c5ec67c | ||
|
|
9d2fd2cce3 | ||
|
|
5a3295d10c | ||
|
|
8269948288 | ||
|
|
8e545fc05f |
9
Interop.nfapinet/Interop.nfapinet.csproj
Normal file
9
Interop.nfapinet/Interop.nfapinet.csproj
Normal file
@@ -0,0 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net48</TargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -2,6 +2,8 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// ReSharper disable All
|
||||
|
||||
namespace nfapinet
|
||||
{
|
||||
public enum NF_STATUS
|
||||
@@ -9,6 +9,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SearchComboBox", "SearchCom
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTest", "UnitTest\UnitTest.csproj", "{53397641-35CA-4336-8E22-2CE12EF476AC}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Interop.nfapinet", "Interop.nfapinet\Interop.nfapinet.csproj", "{2C968ADF-4822-46A9-A7D9-D05A61CB14DE}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
@@ -26,6 +28,10 @@ Global
|
||||
{53397641-35CA-4336-8E22-2CE12EF476AC}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{53397641-35CA-4336-8E22-2CE12EF476AC}.Debug|x64.Build.0 = Debug|x64
|
||||
{53397641-35CA-4336-8E22-2CE12EF476AC}.Release|x64.ActiveCfg = Release|x64
|
||||
{2C968ADF-4822-46A9-A7D9-D05A61CB14DE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2C968ADF-4822-46A9-A7D9-D05A61CB14DE}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{2C968ADF-4822-46A9-A7D9-D05A61CB14DE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{2C968ADF-4822-46A9-A7D9-D05A61CB14DE}.Release|x64.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
16
Netch/Constants.cs
Normal file
16
Netch/Constants.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace Netch
|
||||
{
|
||||
public static class Constants
|
||||
{
|
||||
public const string EOF = "\r\n";
|
||||
public const string UserACL = "data\\user.acl";
|
||||
public const string BuiltinACL = "bin\\default.acl";
|
||||
|
||||
public static class Parameter
|
||||
{
|
||||
public const string Show = "-show";
|
||||
public const string ForceUpdate = "-forceUpdate";
|
||||
public const string Console = "-console";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,12 +30,12 @@ namespace Netch.Controllers
|
||||
/// <summary>
|
||||
/// 成功启动关键词
|
||||
/// </summary>
|
||||
protected virtual IEnumerable<string> StartedKeywords { get; } = new List<string>();
|
||||
protected virtual IEnumerable<string> StartedKeywords { get; set; } = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// 启动失败关键词
|
||||
/// </summary>
|
||||
protected virtual IEnumerable<string> StoppedKeywords { get; } = new List<string>();
|
||||
protected virtual IEnumerable<string> StoppedKeywords { get; set; } = new List<string>();
|
||||
|
||||
public abstract string Name { get; }
|
||||
|
||||
|
||||
@@ -193,16 +193,25 @@ namespace Netch.Controllers
|
||||
{
|
||||
foreach (var p in PortHelper.GetProcessByUsedTcpPort(port))
|
||||
{
|
||||
if (p.MainModule!.FileName.StartsWith(Global.NetchDir))
|
||||
string fileName;
|
||||
try
|
||||
{
|
||||
fileName = p.MainModule!.FileName;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Warning(e.ToString());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fileName.StartsWith(Global.NetchDir))
|
||||
{
|
||||
p.Kill();
|
||||
p.WaitForExit();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new MessageException(i18N.TranslateFormat("The {0} port is used by {1}.",
|
||||
$"{portName} ({port})",
|
||||
$"({p.Id}){p.MainModule.FileName}"));
|
||||
throw new MessageException(i18N.TranslateFormat("The {0} port is used by {1}.", $"{portName} ({port})", $"({p.Id}){fileName}"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Netch.Controllers
|
||||
|
||||
public override string MainFile { get; protected set; } = "pcap2socks.exe";
|
||||
|
||||
protected override IEnumerable<string> StartedKeywords { get; } = new[] {"└"};
|
||||
protected override IEnumerable<string> StartedKeywords { get; set; } = new[] {"└"};
|
||||
|
||||
private readonly OutboundAdapter _outbound = new();
|
||||
|
||||
|
||||
@@ -26,9 +26,9 @@ namespace Netch.Controllers
|
||||
/// </summary>
|
||||
public DNSController DNSController = new();
|
||||
|
||||
protected override IEnumerable<string> StartedKeywords { get; } = new[] {"Running"};
|
||||
protected override IEnumerable<string> StartedKeywords { get; set; } = new[] {"Running"};
|
||||
|
||||
protected override IEnumerable<string> StoppedKeywords { get; } = new[] {"failed", "invalid vconfig file"};
|
||||
protected override IEnumerable<string> StoppedKeywords { get; set; } = new[] {"failed", "invalid vconfig file"};
|
||||
|
||||
public override string MainFile { get; protected set; } = "tun2socks.exe";
|
||||
|
||||
@@ -61,23 +61,42 @@ namespace Netch.Controllers
|
||||
dns = new List<string> {"127.0.0.1"};
|
||||
}
|
||||
|
||||
SetupRouteTable(mode);
|
||||
var parameter = new Tun2SocksParameter
|
||||
{
|
||||
tunAddr = Global.Settings.TUNTAP.Address,
|
||||
tunMask = Global.Settings.TUNTAP.Netmask,
|
||||
tunGw = Global.Settings.TUNTAP.Gateway,
|
||||
tunDns = DnsUtils.Join(dns),
|
||||
tunName = TUNTAP.GetName(_tap.ComponentID),
|
||||
fakeDns = Global.Settings.TUNTAP.UseFakeDNS && Flags.SupportFakeDns
|
||||
};
|
||||
|
||||
Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", Name));
|
||||
|
||||
var argument = new StringBuilder();
|
||||
if (server is Socks5 socks5 && !socks5.Auth())
|
||||
argument.Append($"-proxyServer {server.AutoResolveHostname()}:{server.Port} ");
|
||||
parameter.proxyServer = $"{server.AutoResolveHostname()}:{server.Port}";
|
||||
else
|
||||
argument.Append($"-proxyServer 127.0.0.1:{Global.Settings.Socks5LocalPort} ");
|
||||
parameter.proxyServer = $"127.0.0.1:{Global.Settings.Socks5LocalPort}";
|
||||
|
||||
argument.Append(
|
||||
$"-tunAddr {Global.Settings.TUNTAP.Address} -tunMask {Global.Settings.TUNTAP.Netmask} -tunGw {Global.Settings.TUNTAP.Gateway} -tunDns {DnsUtils.Join(dns)} -tunName \"{TUNTAP.GetName(_tap.ComponentID)}\" ");
|
||||
StartInstanceAuto(parameter.ToString(), ProcessPriorityClass.RealTime);
|
||||
|
||||
if (Global.Settings.TUNTAP.UseFakeDNS && Global.Flags.SupportFakeDns)
|
||||
argument.Append("-fakeDns ");
|
||||
SetupRouteTable(mode);
|
||||
}
|
||||
|
||||
StartInstanceAuto(argument.ToString(), ProcessPriorityClass.RealTime);
|
||||
[Verb]
|
||||
public class Tun2SocksParameter : ParameterBase
|
||||
{
|
||||
public string proxyServer { get; set; }
|
||||
|
||||
public string tunAddr { get; set; }
|
||||
|
||||
public string tunMask { get; set; }
|
||||
|
||||
public string tunGw { get; set; }
|
||||
|
||||
public string tunDns { get; set; }
|
||||
|
||||
public string tunName { get; set; }
|
||||
|
||||
public bool fakeDns { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -127,14 +146,7 @@ namespace Netch.Controllers
|
||||
// 绕过规则 IP
|
||||
|
||||
// 将 TUN/TAP 网卡权重放到最高
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = "netsh",
|
||||
Arguments = $"interface ip set interface {_tap.Index} metric=0",
|
||||
WindowStyle = ProcessWindowStyle.Hidden,
|
||||
UseShellExecute = true,
|
||||
CreateNoWindow = true
|
||||
});
|
||||
SetInterface(RouteType.TUNTAP, 0);
|
||||
|
||||
Logging.Info("绕行 → 规则 IP");
|
||||
RouteAction(Action.Create, mode.FullRule, RouteType.Outbound);
|
||||
@@ -157,6 +169,29 @@ namespace Netch.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
private void SetInterface(RouteType routeType, int? metric = null)
|
||||
{
|
||||
IAdapter adapter = routeType switch
|
||||
{
|
||||
RouteType.Outbound => _outbound,
|
||||
RouteType.TUNTAP => _tap,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(routeType), routeType, null)
|
||||
};
|
||||
|
||||
var arguments = $"interface ip set interface {adapter.Index} ";
|
||||
if (metric != null)
|
||||
arguments += $"metric={metric} ";
|
||||
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = "netsh",
|
||||
Arguments = arguments,
|
||||
WindowStyle = ProcessWindowStyle.Hidden,
|
||||
UseShellExecute = true,
|
||||
CreateNoWindow = true
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除绕行规则
|
||||
/// </summary>
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Netch.Controllers
|
||||
public const string Copyright = @"Copyright © 2019 - 2021";
|
||||
|
||||
public const string AssemblyVersion = @"1.8.3";
|
||||
private const string Suffix = @"Beta2";
|
||||
private const string Suffix = @"Beta4";
|
||||
|
||||
public static readonly string Version = $"{AssemblyVersion}{(string.IsNullOrEmpty(Suffix) ? "" : $"-{Suffix}")}";
|
||||
|
||||
|
||||
16
Netch/Flags.cs
Normal file
16
Netch/Flags.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using Netch.Controllers;
|
||||
|
||||
namespace Netch
|
||||
{
|
||||
public static class Flags
|
||||
{
|
||||
public static readonly bool IsWindows10Upper = Environment.OSVersion.Version.Major >= 10;
|
||||
|
||||
private static readonly Lazy<bool> LazySupportFakeDns = new(() => new TUNTAPController().TestFakeDNS());
|
||||
|
||||
public static bool SupportFakeDns => LazySupportFakeDns.Value;
|
||||
|
||||
public static bool AlwaysShowNewVersionFound { get; set; }
|
||||
}
|
||||
}
|
||||
112
Netch/Forms/MainForm.Designer.cs
generated
112
Netch/Forms/MainForm.Designer.cs
generated
@@ -29,14 +29,12 @@
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
|
||||
this.MenuStrip = new System.Windows.Forms.MenuStrip();
|
||||
this.ServerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.ImportServersFromClipboardToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.ModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.CreateProcessModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.CreateRouteTableRuleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.ReloadModesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.SubscribeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.ManageSubscribeLinksToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.UpdateServersFromSubscribeLinksToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
@@ -95,13 +93,13 @@
|
||||
this.ConfigurationGroupBox.SuspendLayout();
|
||||
this.configLayoutPanel.SuspendLayout();
|
||||
this.tableLayoutPanel2.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize) (this.EditServerPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize) (this.CopyLinkPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize) (this.DeleteServerPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize) (this.SpeedPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.EditServerPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.CopyLinkPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.DeleteServerPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.SpeedPictureBox)).BeginInit();
|
||||
this.tableLayoutPanel3.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize) (this.EditModePictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize) (this.DeleteModePictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.EditModePictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.DeleteModePictureBox)).BeginInit();
|
||||
this.StatusStrip.SuspendLayout();
|
||||
this.NotifyMenu.SuspendLayout();
|
||||
this.ProfileGroupBox.SuspendLayout();
|
||||
@@ -113,10 +111,16 @@
|
||||
//
|
||||
this.MenuStrip.BackColor = System.Drawing.SystemColors.Control;
|
||||
this.MenuStrip.ImageScalingSize = new System.Drawing.Size(20, 20);
|
||||
this.MenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[]
|
||||
{
|
||||
this.ServerToolStripMenuItem, this.ModeToolStripMenuItem, this.SubscribeToolStripMenuItem, this.OptionsToolStripMenuItem, this.HelpToolStripMenuItem, this.exitToolStripMenuItem, this.AboutToolStripButton, this.NewVersionLabel, this.VersionLabel
|
||||
});
|
||||
this.MenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.ServerToolStripMenuItem,
|
||||
this.ModeToolStripMenuItem,
|
||||
this.SubscribeToolStripMenuItem,
|
||||
this.OptionsToolStripMenuItem,
|
||||
this.HelpToolStripMenuItem,
|
||||
this.exitToolStripMenuItem,
|
||||
this.AboutToolStripButton,
|
||||
this.NewVersionLabel,
|
||||
this.VersionLabel});
|
||||
this.MenuStrip.Location = new System.Drawing.Point(0, 0);
|
||||
this.MenuStrip.Name = "MenuStrip";
|
||||
this.MenuStrip.RenderMode = System.Windows.Forms.ToolStripRenderMode.Professional;
|
||||
@@ -125,10 +129,8 @@
|
||||
//
|
||||
// ServerToolStripMenuItem
|
||||
//
|
||||
this.ServerToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[]
|
||||
{
|
||||
this.ImportServersFromClipboardToolStripMenuItem
|
||||
});
|
||||
this.ServerToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.ImportServersFromClipboardToolStripMenuItem});
|
||||
this.ServerToolStripMenuItem.Margin = new System.Windows.Forms.Padding(3, 0, 0, 1);
|
||||
this.ServerToolStripMenuItem.Name = "ServerToolStripMenuItem";
|
||||
this.ServerToolStripMenuItem.Size = new System.Drawing.Size(57, 21);
|
||||
@@ -143,7 +145,9 @@
|
||||
//
|
||||
// ModeToolStripMenuItem
|
||||
//
|
||||
this.ModeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {this.CreateProcessModeToolStripMenuItem, this.CreateRouteTableRuleToolStripMenuItem, this.ReloadModesToolStripMenuItem});
|
||||
this.ModeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.CreateProcessModeToolStripMenuItem,
|
||||
this.CreateRouteTableRuleToolStripMenuItem});
|
||||
this.ModeToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
|
||||
this.ModeToolStripMenuItem.Name = "ModeToolStripMenuItem";
|
||||
this.ModeToolStripMenuItem.Size = new System.Drawing.Size(55, 21);
|
||||
@@ -163,19 +167,12 @@
|
||||
this.CreateRouteTableRuleToolStripMenuItem.Text = "Create Route Table Rule";
|
||||
this.CreateRouteTableRuleToolStripMenuItem.Click += new System.EventHandler(this.createRouteTableModeToolStripMenuItem_Click);
|
||||
//
|
||||
// ReloadModesToolStripMenuItem
|
||||
//
|
||||
this.ReloadModesToolStripMenuItem.Name = "ReloadModesToolStripMenuItem";
|
||||
this.ReloadModesToolStripMenuItem.Size = new System.Drawing.Size(217, 22);
|
||||
this.ReloadModesToolStripMenuItem.Text = "Reload Modes";
|
||||
this.ReloadModesToolStripMenuItem.Click += new System.EventHandler(this.ReloadModesToolStripMenuItem_Click);
|
||||
//
|
||||
// SubscribeToolStripMenuItem
|
||||
//
|
||||
this.SubscribeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[]
|
||||
{
|
||||
this.ManageSubscribeLinksToolStripMenuItem, this.UpdateServersFromSubscribeLinksToolStripMenuItem, this.UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem
|
||||
});
|
||||
this.SubscribeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.ManageSubscribeLinksToolStripMenuItem,
|
||||
this.UpdateServersFromSubscribeLinksToolStripMenuItem,
|
||||
this.UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem});
|
||||
this.SubscribeToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
|
||||
this.SubscribeToolStripMenuItem.Name = "SubscribeToolStripMenuItem";
|
||||
this.SubscribeToolStripMenuItem.Size = new System.Drawing.Size(77, 21);
|
||||
@@ -204,10 +201,15 @@
|
||||
//
|
||||
// OptionsToolStripMenuItem
|
||||
//
|
||||
this.OptionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[]
|
||||
{
|
||||
this.OpenDirectoryToolStripMenuItem, this.CleanDNSCacheToolStripMenuItem, this.UpdateACLToolStripMenuItem, this.updateACLWithProxyToolStripMenuItem, this.updatePACToolStripMenuItem, this.UninstallServiceToolStripMenuItem, this.UninstallTapDriverToolStripMenuItem, this.removeNetchFirewallRulesToolStripMenuItem
|
||||
});
|
||||
this.OptionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.OpenDirectoryToolStripMenuItem,
|
||||
this.CleanDNSCacheToolStripMenuItem,
|
||||
this.UpdateACLToolStripMenuItem,
|
||||
this.updateACLWithProxyToolStripMenuItem,
|
||||
this.updatePACToolStripMenuItem,
|
||||
this.UninstallServiceToolStripMenuItem,
|
||||
this.UninstallTapDriverToolStripMenuItem,
|
||||
this.removeNetchFirewallRulesToolStripMenuItem});
|
||||
this.OptionsToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
|
||||
this.OptionsToolStripMenuItem.Name = "OptionsToolStripMenuItem";
|
||||
this.OptionsToolStripMenuItem.Size = new System.Drawing.Size(66, 21);
|
||||
@@ -271,10 +273,9 @@
|
||||
//
|
||||
// HelpToolStripMenuItem
|
||||
//
|
||||
this.HelpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[]
|
||||
{
|
||||
this.CheckForUpdatesToolStripMenuItem, this.fAQToolStripMenuItem
|
||||
});
|
||||
this.HelpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.CheckForUpdatesToolStripMenuItem,
|
||||
this.fAQToolStripMenuItem});
|
||||
this.HelpToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 0, 1);
|
||||
this.HelpToolStripMenuItem.Name = "HelpToolStripMenuItem";
|
||||
this.HelpToolStripMenuItem.Size = new System.Drawing.Size(47, 21);
|
||||
@@ -550,10 +551,14 @@
|
||||
// StatusStrip
|
||||
//
|
||||
this.StatusStrip.ImageScalingSize = new System.Drawing.Size(20, 20);
|
||||
this.StatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[]
|
||||
{
|
||||
this.StatusLabel, this.UsedBandwidthLabel, this.DownloadSpeedLabel, this.UploadSpeedLabel, this.blankToolStripStatusLabel, this.NatTypeStatusLabel, this.NatTypeStatusLightLabel
|
||||
});
|
||||
this.StatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.StatusLabel,
|
||||
this.UsedBandwidthLabel,
|
||||
this.DownloadSpeedLabel,
|
||||
this.UploadSpeedLabel,
|
||||
this.blankToolStripStatusLabel,
|
||||
this.NatTypeStatusLabel,
|
||||
this.NatTypeStatusLightLabel});
|
||||
this.StatusStrip.Location = new System.Drawing.Point(0, 272);
|
||||
this.StatusStrip.Name = "StatusStrip";
|
||||
this.StatusStrip.Size = new System.Drawing.Size(740, 22);
|
||||
@@ -616,7 +621,7 @@
|
||||
//
|
||||
// ControlButton
|
||||
//
|
||||
this.ControlButton.Anchor = ((System.Windows.Forms.AnchorStyles) ((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.ControlButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.ControlButton.Location = new System.Drawing.Point(631, 3);
|
||||
this.ControlButton.Name = "ControlButton";
|
||||
this.ControlButton.Size = new System.Drawing.Size(75, 27);
|
||||
@@ -635,10 +640,9 @@
|
||||
// NotifyMenu
|
||||
//
|
||||
this.NotifyMenu.ImageScalingSize = new System.Drawing.Size(20, 20);
|
||||
this.NotifyMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[]
|
||||
{
|
||||
this.ShowMainFormToolStripButton, this.ExitToolStripButton
|
||||
});
|
||||
this.NotifyMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.ShowMainFormToolStripButton,
|
||||
this.ExitToolStripButton});
|
||||
this.NotifyMenu.Name = "NotifyMenu";
|
||||
this.NotifyMenu.ShowItemToolTips = false;
|
||||
this.NotifyMenu.Size = new System.Drawing.Size(108, 48);
|
||||
@@ -659,7 +663,7 @@
|
||||
//
|
||||
// SettingsButton
|
||||
//
|
||||
this.SettingsButton.Anchor = ((System.Windows.Forms.AnchorStyles) ((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.SettingsButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.SettingsButton.Location = new System.Drawing.Point(1, 3);
|
||||
this.SettingsButton.Name = "SettingsButton";
|
||||
this.SettingsButton.Size = new System.Drawing.Size(72, 27);
|
||||
@@ -728,7 +732,7 @@
|
||||
this.Controls.Add(this.MenuStrip);
|
||||
this.Controls.Add(this.StatusStrip);
|
||||
this.Controls.Add(this.flowLayoutPanel1);
|
||||
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (134)));
|
||||
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;
|
||||
@@ -744,13 +748,13 @@
|
||||
this.configLayoutPanel.ResumeLayout(false);
|
||||
this.configLayoutPanel.PerformLayout();
|
||||
this.tableLayoutPanel2.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize) (this.EditServerPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize) (this.CopyLinkPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize) (this.DeleteServerPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize) (this.SpeedPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.EditServerPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.CopyLinkPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.DeleteServerPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.SpeedPictureBox)).EndInit();
|
||||
this.tableLayoutPanel3.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize) (this.EditModePictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize) (this.DeleteModePictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.EditModePictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.DeleteModePictureBox)).EndInit();
|
||||
this.StatusStrip.ResumeLayout(false);
|
||||
this.StatusStrip.PerformLayout();
|
||||
this.NotifyMenu.ResumeLayout(false);
|
||||
@@ -760,6 +764,7 @@
|
||||
this.ButtomControlContainerControl.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
private System.Windows.Forms.ToolStripMenuItem CreateRouteTableRuleToolStripMenuItem;
|
||||
@@ -798,7 +803,6 @@
|
||||
private System.Windows.Forms.TableLayoutPanel ProfileTable;
|
||||
private System.Windows.Forms.ToolStripMenuItem UninstallTapDriverToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem CheckForUpdatesToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem ReloadModesToolStripMenuItem;
|
||||
private System.Windows.Forms.ComboBox ServerComboBox;
|
||||
private System.Windows.Forms.Label ServerLabel;
|
||||
private System.Windows.Forms.ToolStripMenuItem ServerToolStripMenuItem;
|
||||
|
||||
@@ -84,8 +84,6 @@ namespace Netch.Forms
|
||||
|
||||
private void MainForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
Netch.TimePoint("MainForm ctor (Pre MainForm Load)");
|
||||
|
||||
// 计算 ComboBox绘制 目标宽度
|
||||
RecordSize();
|
||||
|
||||
@@ -121,8 +119,6 @@ namespace Netch.Forms
|
||||
if (Global.Settings.StartWhenOpened)
|
||||
ControlButton_Click(null, null);
|
||||
});
|
||||
|
||||
Netch.TimePoint("Post Form Load", false);
|
||||
}
|
||||
|
||||
private void RecordSize()
|
||||
@@ -266,25 +262,6 @@ namespace Netch.Forms
|
||||
Show();
|
||||
}
|
||||
|
||||
private void ReloadModesToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Enabled = false;
|
||||
try
|
||||
{
|
||||
ModeHelper.Load();
|
||||
LoadModes();
|
||||
NotifyTip(i18N.Translate("Modes have been reload"));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
finally
|
||||
{
|
||||
Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Subscription
|
||||
@@ -467,7 +444,7 @@ namespace Netch.Forms
|
||||
if (useProxy)
|
||||
req.Proxy = new WebProxy($"http://127.0.0.1:{Global.Settings.HTTPLocalPort}");
|
||||
|
||||
await WebUtil.DownloadFileAsync(req, Path.Combine(Global.NetchDir, Global.UserACL));
|
||||
await WebUtil.DownloadFileAsync(req, Path.Combine(Global.NetchDir, Constants.UserACL));
|
||||
NotifyTip(i18N.Translate("ACL updated successfully"));
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -634,9 +611,7 @@ namespace Netch.Forms
|
||||
if (!IsWaiting())
|
||||
{
|
||||
// 停止
|
||||
State = State.Stopping;
|
||||
await MainController.StopAsync();
|
||||
State = State.Stopped;
|
||||
await StopAsyncCore();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1126,8 +1101,7 @@ namespace Netch.Forms
|
||||
// 启动需要禁用的控件
|
||||
UninstallServiceToolStripMenuItem.Enabled = UpdateACLToolStripMenuItem.Enabled = updateACLWithProxyToolStripMenuItem.Enabled =
|
||||
updatePACToolStripMenuItem.Enabled = UpdateServersFromSubscribeLinksToolStripMenuItem.Enabled =
|
||||
UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem.Enabled = UninstallTapDriverToolStripMenuItem.Enabled =
|
||||
ReloadModesToolStripMenuItem.Enabled = enabled;
|
||||
UpdateServersFromSubscribeLinksWithProxyToolStripMenuItem.Enabled = UninstallTapDriverToolStripMenuItem.Enabled = enabled;
|
||||
}
|
||||
|
||||
_state = value;
|
||||
@@ -1179,6 +1153,27 @@ namespace Netch.Forms
|
||||
}
|
||||
}
|
||||
|
||||
private async Task StopAsyncCore()
|
||||
{
|
||||
State = State.Stopping;
|
||||
await MainController.StopAsync();
|
||||
State = State.Stopped;
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
if (IsWaiting())
|
||||
return;
|
||||
|
||||
if (InvokeRequired)
|
||||
{
|
||||
Invoke(new Action(Stop));
|
||||
return;
|
||||
}
|
||||
|
||||
StopAsyncCore().Wait();
|
||||
}
|
||||
|
||||
private bool IsWaiting()
|
||||
{
|
||||
return State == State.Waiting || State == State.Stopped;
|
||||
@@ -1258,7 +1253,7 @@ namespace Netch.Forms
|
||||
{
|
||||
if (natType > 0 && natType < 5)
|
||||
{
|
||||
NatTypeStatusLightLabel.Visible = Global.Flags.IsWindows10Upper;
|
||||
NatTypeStatusLightLabel.Visible = Flags.IsWindows10Upper;
|
||||
var c = natType switch
|
||||
{
|
||||
1 => Color.LimeGreen,
|
||||
@@ -1388,8 +1383,8 @@ namespace Netch.Forms
|
||||
if (File.Exists(file))
|
||||
File.Delete(file);
|
||||
|
||||
if (!IsWaiting())
|
||||
await MainController.StopAsync();
|
||||
if (IsWaiting())
|
||||
await StopAsyncCore();
|
||||
|
||||
Dispose();
|
||||
Environment.Exit(Environment.ExitCode);
|
||||
@@ -1425,6 +1420,8 @@ namespace Netch.Forms
|
||||
{
|
||||
UpdateChecker.NewVersionFound += OnUpdateCheckerOnNewVersionFound;
|
||||
UpdateChecker.Check(Global.Settings.CheckBetaUpdate).Wait();
|
||||
if (Flags.AlwaysShowNewVersionFound)
|
||||
OnUpdateCheckerOnNewVersionFound(null!, null!);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -1482,8 +1479,14 @@ namespace Netch.Forms
|
||||
|
||||
#region NotifyIcon
|
||||
|
||||
private void ShowMainFormToolStripButton_Click(object sender, EventArgs e)
|
||||
public void ShowMainFormToolStripButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (InvokeRequired)
|
||||
{
|
||||
Invoke(new Action(() => ShowMainFormToolStripButton_Click(sender, e)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (WindowState == FormWindowState.Minimized)
|
||||
{
|
||||
Visible = true;
|
||||
@@ -1516,7 +1519,7 @@ namespace Netch.Forms
|
||||
|
||||
public void NotifyTip(string text, int timeout = 0, bool info = true)
|
||||
{
|
||||
// 会阻塞线程 timeout 秒
|
||||
// 会阻塞线程 timeout 秒(?)
|
||||
NotifyIcon.ShowBalloonTip(timeout, UpdateChecker.Name, text, info ? ToolTipIcon.Info : ToolTipIcon.Error);
|
||||
}
|
||||
|
||||
|
||||
132
Netch/Forms/MainForm.resx
Normal file
132
Netch/Forms/MainForm.resx
Normal file
@@ -0,0 +1,132 @@
|
||||
<?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>
|
||||
<metadata name="MenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<metadata name="StatusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>130, 17</value>
|
||||
</metadata>
|
||||
<metadata name="NotifyIcon.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>246, 17</value>
|
||||
</metadata>
|
||||
<metadata name="NotifyMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>359, 17</value>
|
||||
</metadata>
|
||||
</root>
|
||||
@@ -235,7 +235,7 @@ namespace Netch.Forms
|
||||
private void SettingForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
TUNTAPUseCustomDNSCheckBox_CheckedChanged(null, null);
|
||||
Task.Run(() => BeginInvoke(new Action(() => UseFakeDNSCheckBox.Visible = Global.Flags.SupportFakeDns)));
|
||||
Task.Run(() => BeginInvoke(new Action(() => UseFakeDNSCheckBox.Visible = Flags.SupportFakeDns)));
|
||||
}
|
||||
|
||||
private void TUNTAPUseCustomDNSCheckBox_CheckedChanged(object? sender, EventArgs? e)
|
||||
|
||||
@@ -2,9 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using Netch.Controllers;
|
||||
using Netch.Forms;
|
||||
using Netch.Models;
|
||||
|
||||
@@ -12,27 +10,11 @@ namespace Netch
|
||||
{
|
||||
public static class Global
|
||||
{
|
||||
/// <summary>
|
||||
/// 换行
|
||||
/// </summary>
|
||||
public const string EOF = "\r\n";
|
||||
|
||||
public const string UserACL = "data\\user.acl";
|
||||
public const string BuiltinACL = "bin\\default.acl";
|
||||
|
||||
public static readonly string NetchDir = Application.StartupPath;
|
||||
|
||||
public static readonly string NetchExecutable = Application.ExecutablePath;
|
||||
|
||||
/// <summary>
|
||||
/// 主窗体的静态实例
|
||||
/// </summary>
|
||||
private static readonly Lazy<MainForm> LazyMainForm = new(() => new MainForm());
|
||||
|
||||
private static readonly Lazy<Mutex> LazyMutex = new(() => new Mutex(false, "Global\\Netch"));
|
||||
|
||||
public static Mutex Mutex => LazyMutex.Value;
|
||||
|
||||
/// <summary>
|
||||
/// 用于读取和写入的配置
|
||||
/// </summary>
|
||||
@@ -43,15 +25,6 @@ namespace Netch
|
||||
/// </summary>
|
||||
public static readonly List<Mode> Modes = new();
|
||||
|
||||
public static class Flags
|
||||
{
|
||||
public static readonly bool IsWindows10Upper = Environment.OSVersion.Version.Major >= 10;
|
||||
|
||||
private static readonly Lazy<bool> LazySupportFakeDns = new(() => new TUNTAPController().TestFakeDNS());
|
||||
|
||||
public static bool SupportFakeDns => LazySupportFakeDns.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 主窗体的静态实例
|
||||
/// </summary>
|
||||
@@ -63,5 +36,8 @@ namespace Netch
|
||||
IgnoreNullValues = true,
|
||||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
|
||||
};
|
||||
|
||||
public static readonly string NetchDir = Application.StartupPath;
|
||||
public static readonly string NetchExecutable = Application.ExecutablePath;
|
||||
}
|
||||
}
|
||||
@@ -161,7 +161,7 @@ namespace Netch.Models
|
||||
/// <returns>模式文件字符串</returns>
|
||||
public string ToFileString()
|
||||
{
|
||||
return $"# {Remark}, {Type}, {(BypassChina ? 1 : 0)}{Global.EOF}{string.Join(Global.EOF, Rule)}";
|
||||
return $"# {Remark}, {Type}, {(BypassChina ? 1 : 0)}{Constants.EOF}{string.Join(Constants.EOF, Rule)}";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,42 +1,19 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
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
|
||||
{
|
||||
public static class Netch
|
||||
{
|
||||
private static readonly Stopwatch Stopwatch = new();
|
||||
|
||||
public static void StartStopwatch(string name)
|
||||
{
|
||||
if (Stopwatch.IsRunning)
|
||||
throw new Exception();
|
||||
|
||||
Stopwatch.Start();
|
||||
Console.WriteLine($"Start {name} Stopwatch");
|
||||
}
|
||||
|
||||
public static void TimePoint(string name, bool restart = true)
|
||||
{
|
||||
if (!Stopwatch.IsRunning)
|
||||
throw new Exception();
|
||||
|
||||
Stopwatch.Stop();
|
||||
Console.WriteLine($"{name} Stopwatch: {Stopwatch.ElapsedMilliseconds}");
|
||||
if (restart)
|
||||
Stopwatch.Restart();
|
||||
}
|
||||
public static readonly SingleInstance.SingleInstance SingleInstance = new($"Global\\{nameof(Netch)}");
|
||||
|
||||
/// <summary>
|
||||
/// 应用程序的主入口点
|
||||
@@ -47,10 +24,12 @@ namespace Netch
|
||||
#if DEBUG
|
||||
AttachConsole();
|
||||
#else
|
||||
if (args.Contains("-console"))
|
||||
if (args.Contains(Constants.Parameter.Console))
|
||||
AttachConsole();
|
||||
#endif
|
||||
StartStopwatch("Netch");
|
||||
|
||||
if (args.Contains(Constants.Parameter.ForceUpdate))
|
||||
Flags.AlwaysShowNewVersionFound = true;
|
||||
|
||||
// 设置当前目录
|
||||
Directory.SetCurrentDirectory(Global.NetchDir);
|
||||
@@ -66,20 +45,19 @@ namespace Netch
|
||||
if (!Directory.Exists(item))
|
||||
Directory.CreateDirectory(item);
|
||||
|
||||
TimePoint("Clean Old, Create Directory");
|
||||
// 加载配置
|
||||
Configuration.Load();
|
||||
|
||||
TimePoint("Load Configuration");
|
||||
// 检查是否已经运行
|
||||
if (!Global.Mutex.WaitOne(0, false))
|
||||
if (!SingleInstance.IsFirstInstance)
|
||||
{
|
||||
ShowOpened();
|
||||
|
||||
// 退出进程
|
||||
Environment.Exit(1);
|
||||
SingleInstance.PassArgumentsToFirstInstance(args.Append(Constants.Parameter.Show));
|
||||
Environment.Exit(0);
|
||||
return;
|
||||
}
|
||||
|
||||
SingleInstance.ArgumentsReceived.Subscribe(SingleInstance_ArgumentsReceived);
|
||||
SingleInstance.ListenForArgumentsFromSuccessiveInstances();
|
||||
|
||||
// 清理上一次的日志文件,防止淤积占用磁盘空间
|
||||
if (Directory.Exists("logging"))
|
||||
{
|
||||
@@ -104,8 +82,6 @@ namespace Netch
|
||||
Logging.Info($"版本: {UpdateChecker.Owner}/{UpdateChecker.Repo}@{UpdateChecker.Version}");
|
||||
Task.Run(() => { Logging.Info($"主程序 SHA256: {Utils.Utils.SHA256CheckSum(Global.NetchExecutable)}"); });
|
||||
|
||||
TimePoint("Get Info, Pre-Form");
|
||||
|
||||
// 绑定错误捕获
|
||||
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
|
||||
Application.ThreadException += Application_OnException;
|
||||
@@ -127,40 +103,12 @@ namespace Netch
|
||||
Utils.Utils.Open(Logging.LogFile);
|
||||
}
|
||||
|
||||
private static void ShowOpened()
|
||||
private static void SingleInstance_ArgumentsReceived(IEnumerable<string> args)
|
||||
{
|
||||
HWND GetWindowHandleByPidAndTitle(int process, string title)
|
||||
if (args.Contains(Constants.Parameter.Show))
|
||||
{
|
||||
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;
|
||||
Global.MainForm.ShowMainFormToolStripButton_Click(null!, 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="HMBSbige.SingleInstance" Version="5.0.0" />
|
||||
<PackageReference Include="MaxMind.GeoIP2" Version="4.0.1" />
|
||||
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.66" GeneratePathProperty="true" />
|
||||
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
||||
@@ -54,9 +55,9 @@
|
||||
<PackageReference Include="System.Reflection.Metadata" Version="5.0.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="5.0.1" />
|
||||
<PackageReference Include="TaskScheduler" Version="2.9.1" />
|
||||
<PackageReference Include="Vanara.PInvoke.IpHlpApi" Version="3.3.6" />
|
||||
<PackageReference Include="Vanara.PInvoke.IpHlpApi" Version="3.3.7" />
|
||||
<PackageReference Include="Microsoft-WindowsAPICodePack-Shell" Version="1.1.4" />
|
||||
<PackageReference Include="Vanara.PInvoke.User32" Version="3.3.6" />
|
||||
<PackageReference Include="Vanara.PInvoke.User32" Version="3.3.7" />
|
||||
<PackageReference Include="WindowsFirewallHelper" Version="2.0.4.70-beta2" />
|
||||
<PackageReference Include="WindowsProxy" Version="5.0.3" />
|
||||
</ItemGroup>
|
||||
@@ -77,6 +78,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Interop.nfapinet\Interop.nfapinet.csproj" />
|
||||
<ProjectReference Include="..\SearchComboBox\SearchComboBox.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -123,7 +125,7 @@
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||
<Exec Command="set TargetFramework=$(TargetFramework)
set Configuration=$(Configuration)
set ILMergeConsolePath=$(ILMergeConsolePath)
set TargetDir=$(TargetDir)
set SolutionDir=$(SolutionDir)
$(ProjectDir)PostBuild.bat" />
|
||||
<Exec Command="set TargetFramework=$(TargetFramework)
set Configuration=$(Configuration)
set ILMergeConsolePath=$(ILMergeConsolePath)
set TargetDir=$(TargetDir)
set SolutionDir=$(SolutionDir)
call $(ProjectDir)PostBuild.bat" />
|
||||
</Target>
|
||||
|
||||
<Target Condition="'$(PublishSingleFile)' == 'true'" AfterTargets="_ComputeFilesToBundle" Name="RemoveDupeAssemblies">
|
||||
|
||||
@@ -10,9 +10,9 @@ namespace Netch.Servers.Shadowsocks
|
||||
{
|
||||
public override string MainFile { get; protected set; } = "Shadowsocks.exe";
|
||||
|
||||
protected override IEnumerable<string> StartedKeywords { get; } = new[] {"listening at"};
|
||||
protected override IEnumerable<string> StartedKeywords { get; set; } = new[] {"listening at"};
|
||||
|
||||
protected override IEnumerable<string> StoppedKeywords { get; } = new[] {"Invalid config path", "usage", "plugin service exit unexpectedly"};
|
||||
protected override IEnumerable<string> StoppedKeywords { get; set; } = new[] {"Invalid config path", "usage", "plugin service exit unexpectedly"};
|
||||
|
||||
public override string Name { get; } = "Shadowsocks";
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Netch.Servers.Shadowsocks
|
||||
};
|
||||
|
||||
if (mode.BypassChina)
|
||||
command.acl = $"{Path.GetFullPath(File.Exists(Global.UserACL) ? Global.UserACL : Global.BuiltinACL)}";
|
||||
command.acl = $"{Path.GetFullPath(File.Exists(Constants.UserACL) ? Constants.UserACL : Constants.BuiltinACL)}";
|
||||
|
||||
StartInstanceAuto(command.ToString());
|
||||
}
|
||||
|
||||
@@ -10,9 +10,9 @@ namespace Netch.Servers.ShadowsocksR
|
||||
{
|
||||
public override string MainFile { get; protected set; } = "ShadowsocksR.exe";
|
||||
|
||||
protected override IEnumerable<string> StartedKeywords { get; } = new[] {"listening at"};
|
||||
protected override IEnumerable<string> StartedKeywords { get; set; } = new[] {"listening at"};
|
||||
|
||||
protected override IEnumerable<string> StoppedKeywords { get; } = new[] {"Invalid config path", "usage"};
|
||||
protected override IEnumerable<string> StoppedKeywords { get; set; } = new[] {"Invalid config path", "usage"};
|
||||
|
||||
public override string Name { get; } = "ShadowsocksR";
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Netch.Servers.ShadowsocksR
|
||||
};
|
||||
|
||||
if (mode.BypassChina)
|
||||
command.acl = $"{Path.GetFullPath(File.Exists(Global.UserACL) ? Global.UserACL : Global.BuiltinACL)}";
|
||||
command.acl = $"{Path.GetFullPath(File.Exists(Constants.UserACL) ? Constants.UserACL : Constants.BuiltinACL)}";
|
||||
|
||||
StartInstanceAuto(command.ToString());
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Netch.Servers.ShadowsocksR
|
||||
// https://github.com/shadowsocksr-backup/shadowsocks-rss/wiki/SSR-QRcode-scheme
|
||||
// ssr://base64(host:port:protocol:method:obfs:base64pass/?obfsparam=base64param&protoparam=base64param&remarks=base64remarks&group=base64group&udpport=0&uot=0)
|
||||
var paraStr =
|
||||
$"/?obfsparam={ShareLink.URLSafeBase64Encode(server.OBFSParam)}&protoparam={ShareLink.URLSafeBase64Encode(server.ProtocolParam)}&remarks={ShareLink.URLSafeBase64Encode(server.Remark)}";
|
||||
$"/?obfsparam={ShareLink.URLSafeBase64Encode(server.OBFSParam ?? "")}&protoparam={ShareLink.URLSafeBase64Encode(server.ProtocolParam ?? "")}&remarks={ShareLink.URLSafeBase64Encode(server.Remark)}";
|
||||
|
||||
return "ssr://" +
|
||||
ShareLink.URLSafeBase64Encode(
|
||||
|
||||
@@ -11,9 +11,9 @@ namespace Netch.Servers.Trojan
|
||||
{
|
||||
public override string MainFile { get; protected set; } = "Trojan.exe";
|
||||
|
||||
protected override IEnumerable<string> StartedKeywords { get; } = new[] {"started"};
|
||||
protected override IEnumerable<string> StartedKeywords { get; set; } = new[] {"started"};
|
||||
|
||||
protected override IEnumerable<string> StoppedKeywords { get; } = new[] {"exiting"};
|
||||
protected override IEnumerable<string> StoppedKeywords { get; set; } = new[] {"exiting"};
|
||||
|
||||
public override string Name { get; } = "Trojan";
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace Netch.Servers.V2ray.Utils
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
if (Global.Flags.SupportFakeDns && Global.Settings.TUNTAP.UseFakeDNS)
|
||||
if (Flags.SupportFakeDns && Global.Settings.TUNTAP.UseFakeDNS)
|
||||
directRuleObject.domain.Add("geosite:cn");
|
||||
else
|
||||
directRuleObject.ip.Add("geoip:cn");
|
||||
|
||||
@@ -10,9 +10,9 @@ namespace Netch.Servers.V2ray
|
||||
{
|
||||
public override string MainFile { get; protected set; } = "xray.exe";
|
||||
|
||||
protected override IEnumerable<string> StartedKeywords { get; } = new[] {"started"};
|
||||
protected override IEnumerable<string> StartedKeywords { get; set; } = new[] {"started"};
|
||||
|
||||
protected override IEnumerable<string> StoppedKeywords { get; } = new[] {"config file not readable", "failed to"};
|
||||
protected override IEnumerable<string> StoppedKeywords { get; set; } = new[] {"config file not readable", "failed to"};
|
||||
|
||||
public override string Name { get; } = "Xray";
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Windows.Threading;
|
||||
using Netch.Controllers;
|
||||
using Netch.Properties;
|
||||
using Netch.Utils;
|
||||
@@ -95,10 +96,19 @@ namespace Netch.Updater
|
||||
|
||||
private void ApplyUpdate()
|
||||
{
|
||||
// Pre Update
|
||||
var dispatcher = Dispatcher.CurrentDispatcher;
|
||||
var mainForm = Global.MainForm;
|
||||
|
||||
#region PreUpdate
|
||||
|
||||
ModeHelper.SuspendWatcher = true;
|
||||
// Stop and Save
|
||||
mainForm.Stop();
|
||||
Configuration.Save();
|
||||
|
||||
// Backup Configuration file
|
||||
try
|
||||
{
|
||||
// Backup Configuration file
|
||||
File.Copy(Configuration.SettingFileFullName, Configuration.SettingFileFullName + ".bak", true);
|
||||
}
|
||||
catch (Exception)
|
||||
@@ -106,6 +116,8 @@ namespace Netch.Updater
|
||||
// ignored
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// extract Update file to {tempDirectory}\extract
|
||||
var extractPath = Path.Combine(_tempDirectory, "extract");
|
||||
int exitCode;
|
||||
@@ -118,11 +130,10 @@ namespace Netch.Updater
|
||||
// move {tempDirectory}\extract\Netch to install folder
|
||||
MoveAllFilesOver(Path.Combine(extractPath, "Netch"), _installDirectory);
|
||||
|
||||
// save, release mutex, then exit
|
||||
Configuration.Save();
|
||||
Global.MainForm.Invoke(new Action(() => { Global.Mutex.ReleaseMutex(); }));
|
||||
// release mutex, exit
|
||||
dispatcher.Invoke(Netch.SingleInstance.Dispose);
|
||||
Process.Start(Global.NetchExecutable);
|
||||
Global.MainForm.Exit(true, false);
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
private void MarkFilesOld()
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace Netch.Utils
|
||||
/// </summary>
|
||||
public static void NetTraffic()
|
||||
{
|
||||
if (!Global.Flags.IsWindows10Upper)
|
||||
if (!Flags.IsWindows10Upper)
|
||||
return;
|
||||
|
||||
var counterLock = new object();
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Netch.Utils
|
||||
|
||||
private static void Write(string text, LogLevel logLevel)
|
||||
{
|
||||
var contents = $@"[{DateTime.Now}][{logLevel.ToString()}] {text}{Global.EOF}";
|
||||
var contents = $@"[{DateTime.Now}][{logLevel.ToString()}] {text}{Constants.EOF}";
|
||||
#if DEBUG
|
||||
switch (logLevel)
|
||||
{
|
||||
|
||||
@@ -16,6 +16,8 @@ namespace Netch.Utils
|
||||
|
||||
private static readonly FileSystemWatcher FileSystemWatcher;
|
||||
|
||||
public static bool SuspendWatcher { get; set; } = false;
|
||||
|
||||
static ModeHelper()
|
||||
{
|
||||
FileSystemWatcher = new FileSystemWatcher(ModeDirectoryFullName)
|
||||
@@ -33,6 +35,9 @@ namespace Netch.Utils
|
||||
|
||||
private static void OnModeChanged(object sender, FileSystemEventArgs e)
|
||||
{
|
||||
if (SuspendWatcher)
|
||||
return;
|
||||
|
||||
Load();
|
||||
Global.MainForm.LoadModes();
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Netch.Utils
|
||||
if (port == 0)
|
||||
throw new ArgumentOutOfRangeException();
|
||||
|
||||
var row = GetTcpTable2().Where(r => ntohs((ushort) r.dwLocalPort) == port);
|
||||
var row = GetTcpTable2().Where(r => ntohs((ushort) r.dwLocalPort) == port).Where(r => r.dwOwningPid is not (0 or 4));
|
||||
|
||||
return row.Select(r => Process.GetProcessById((int) r.dwOwningPid));
|
||||
}
|
||||
|
||||
2
binaries
2
binaries
Submodule binaries updated: c64a784152...db78c29ec3
Reference in New Issue
Block a user