捕捉到未处理错误打开日志

减少TUN/TAP设置路由表代码
日志细节优化
This commit is contained in:
ChsBuffer
2020-07-28 16:10:26 +08:00
parent b6a3f5bc36
commit c9396bd6b2
13 changed files with 240 additions and 352 deletions

View File

@@ -38,6 +38,7 @@ namespace Netch.Controllers
/// <returns>是否启动成功</returns>
public bool Start(Server server, Mode mode)
{
Logging.Info($"启动主控制器: {server.Type} [{mode.Type}]{mode.Remark}");
FlushDNSResolverCache();
var result = false;
@@ -90,7 +91,6 @@ namespace Netch.Controllers
if (result)
{
Logging.Info("加密代理已启动");
switch (mode.Type)
{
case 0: // 进程代理模式
@@ -136,7 +136,11 @@ namespace Netch.Controllers
}
}
if (!result) Stop();
if (!result)
{
Logging.Error("主控制器启动失败");
Stop();
}
return result;
}

View File

@@ -175,7 +175,7 @@ namespace Netch.Controllers
public static bool UninstallDriver()
{
Global.MainForm.StatusText(i18N.Translate("Uninstalling NF Service"));
Logging.Info("卸载NF驱动");
Logging.Info("卸载 NF 驱动");
try
{
if (NFService.Status == ServiceControllerStatus.Running)
@@ -211,7 +211,7 @@ namespace Netch.Controllers
/// <returns>驱动是否安装成功</returns>
public static bool InstallDriver()
{
Logging.Info("安装NF驱动");
Logging.Info("安装 NF 驱动");
try
{
File.Copy(BinDriver, SystemDriver);
@@ -227,7 +227,7 @@ namespace Netch.Controllers
var result = NFAPI.nf_registerDriver("netfilter2");
if (result == NF_STATUS.NF_STATUS_SUCCESS)
{
Logging.Info($"驱动安装成功,当前驱动版本:{DriverVersion(SystemDriver)}");
Logging.Info($"驱动安装成功");
}
else
{

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
@@ -38,7 +38,7 @@ namespace Netch.Controllers
Name = "Tap";
MainFile = "tun2socks.exe";
StartedKeywords("Running");
StoppedKeywords("failed","invalid vconfig file");
StoppedKeywords("failed", "invalid vconfig file");
}
/// <summary>
@@ -56,154 +56,113 @@ namespace Netch.Controllers
}
// 搜索出口
return SearchOutbounds();
return SearchAdapters();
}
private readonly List<IPNetwork> _directIPs = new List<IPNetwork>();
private readonly List<IPNetwork> _proxyIPs = new List<IPNetwork>();
/// <summary>
/// 设置绕行规则
/// <returns>是否设置成功</returns>
/// </summary>
private bool SetupBypass()
private bool SetupRouteTable()
{
Logging.Info("收集路由表规则");
Global.MainForm.StatusText(i18N.Translate("SetupBypass"));
Logging.Info("设置绕行规则 → 设置让服务器 IP 走直连");
// 让服务器 IP 走直连
foreach (var address in _serverAddresses)
if (!IPAddress.IsLoopback(address))
NativeMethods.CreateRoute(address.ToString(), 32, Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
// 处理模式的绕过中国
Logging.Info("绕行 → 全局绕过 IP");
_directIPs.AddRange(Global.Settings.BypassIPs.Select(IPNetwork.Parse));
Logging.Info("绕行 → 服务器 IP");
_directIPs.AddRange(_serverAddresses.Where(address => !IPAddress.IsLoopback(address)).Select(address => IPNetwork.Parse(address.ToString(), 32)));
if (_savedMode.BypassChina)
{
Logging.Info("设置绕行规则 → 处理模式的绕过中国");
using (var sr = new StringReader(Encoding.UTF8.GetString(Resources.CNIP)))
{
string text;
while ((text = sr.ReadLine()) != null)
{
var info = text.Split('/');
NativeMethods.CreateRoute(info[0], int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
}
}
Logging.Info("绕行 → 中国 IP");
_directIPs.AddRange(Encoding.UTF8.GetString(Resources.CNIP).Split('\n').Select(IPNetwork.Parse));
}
Logging.Info("设置绕行规则 → 处理全局绕过 IP");
// 处理全局绕过 IP
foreach (var ip in Global.Settings.BypassIPs)
Logging.Info("绕行 → 局域网 IP");
_directIPs.AddRange(_bypassLanIPs.Select(IPNetwork.Parse));
switch (_savedMode.Type)
{
var info = ip.Split('/');
var address = IPAddress.Parse(info[0]);
case 1:
// 代理规则
Logging.Info("代理 → 规则 IP");
_proxyIPs.AddRange(_savedMode.Rule.Select(IPNetwork.Parse));
if (!IPAddress.IsLoopback(address)) NativeMethods.CreateRoute(address.ToString(), int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
}
Logging.Info("设置绕行规则 → 处理绕过局域网 IP");
// 处理绕过局域网 IP
foreach (var ip in _bypassLanIPs)
{
var info = ip.Split('/');
var address = IPAddress.Parse(info[0]);
if (!IPAddress.IsLoopback(address)) NativeMethods.CreateRoute(address.ToString(), int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
}
if (_savedMode.Type == 2) // 处理仅规则内走直连
{
Logging.Info("设置绕行规则 → 处理仅规则内走直连");
// 将 TUN/TAP 网卡权重放到最高
var instance = new Process
{
StartInfo =
{
FileName = "netsh",
Arguments = string.Format("interface ip set interface {0} metric=0", Global.TUNTAP.Index),
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = true,
CreateNoWindow = true
}
};
instance.Start();
Logging.Info("设置绕行规则 → 创建默认路由");
// 创建默认路由
if (!NativeMethods.CreateRoute("0.0.0.0", 0, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index, 10))
{
State = State.Stopped;
foreach (var address in _serverAddresses) NativeMethods.DeleteRoute(address.ToString(), 32, Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
return false;
}
Logging.Info("设置绕行规则 → 创建规则路由");
// 创建规则路由
foreach (var ip in _savedMode.Rule)
{
var info = ip.Split('/');
if (info.Length == 2)
if (int.TryParse(info[1], out var prefix))
NativeMethods.CreateRoute(info[0], prefix, Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
}
}
else if (_savedMode.Type == 1) // 处理仅规则内走代理
{
Logging.Info("设置绕行规则->处理仅规则内走代理");
foreach (var ip in _savedMode.Rule)
{
var info = ip.Split('/');
if (info.Length == 2)
if (int.TryParse(info[1], out var prefix))
NativeMethods.CreateRoute(info[0], prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
}
//处理 NAT 类型检测,由于协议的原因,无法仅通过域名确定需要代理的 IP自己记录解析了返回的 IP仅支持默认检测服务器
if (Global.Settings.STUN_Server == "stun.stunprotocol.org")
try
{
var nttAddress = Dns.GetHostAddresses(Global.Settings.STUN_Server)[0];
if (int.TryParse("32", out var prefix)) NativeMethods.CreateRoute(nttAddress.ToString(), prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
var nttrAddress = Dns.GetHostAddresses("stunresponse.coldthunder11.com")[0];
if (int.TryParse("32", out var prefixr)) NativeMethods.CreateRoute(nttrAddress.ToString(), prefixr, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
}
catch
{
Logging.Info("NAT 类型测试域名解析失败,将不会被添加到代理列表");
}
//处理DNS代理
if (Global.Settings.TUNTAP.ProxyDNS)
{
Logging.Info("设置绕行规则 → 处理自定义 DNS 代理");
if (Global.Settings.TUNTAP.UseCustomDNS)
{
var dns = string.Empty;
foreach (var value in Global.Settings.TUNTAP.DNS)
//处理 NAT 类型检测,由于协议的原因,无法仅通过域名确定需要代理的 IP自己记录解析了返回的 IP仅支持默认检测服务器
if (Global.Settings.STUN_Server == "stun.stunprotocol.org")
try
{
dns += value;
dns += ',';
Logging.Info("代理 → STUN 服务器 IP");
_proxyIPs.AddRange(new[]
{
Dns.GetHostAddresses(Global.Settings.STUN_Server)[0],
Dns.GetHostAddresses("stunresponse.coldthunder11.com")[0]
}.Select(ip => IPNetwork.Parse(ip.ToString(), 32)));
}
catch
{
Logging.Info("NAT 类型测试域名解析失败,将不会被添加到代理列表");
}
dns = dns.Trim();
dns = dns.Substring(0, dns.Length - 1);
if (int.TryParse("32", out var prefix)) NativeMethods.CreateRoute(dns, prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
}
else
if (Global.Settings.TUNTAP.ProxyDNS)
{
if (int.TryParse("32", out var prefix))
Logging.Info("代理 → 自定义 DNS");
if (Global.Settings.TUNTAP.UseCustomDNS)
{
NativeMethods.CreateRoute("1.1.1.1", prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
NativeMethods.CreateRoute("8.8.8.8", prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
NativeMethods.CreateRoute("9.9.9.9", prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
NativeMethods.CreateRoute("185.222.222.222", prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
var dns = string.Empty;
foreach (var value in Global.Settings.TUNTAP.DNS)
{
dns += value;
dns += ',';
}
dns = dns.Trim();
dns = dns.Substring(0, dns.Length - 1);
RouteAction(Action.Create, dns, 32, RouteType.TUNTAP);
}
else
{
_proxyIPs.AddRange(new[] {"1.1.1.1", "8.8.8.8", "9.9.9.9", "185.222.222.222"}.Select(ip => IPNetwork.Parse(ip, 32)));
}
}
}
break;
case 2:
// 绕过规则
// 将 TUN/TAP 网卡权重放到最高
Process.Start(new ProcessStartInfo
{
FileName = "netsh",
Arguments = $"interface ip set interface {Global.TUNTAP.Index} metric=0",
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = true,
CreateNoWindow = true
}
);
Logging.Info("绕行 → 规则 IP");
_directIPs.AddRange(_savedMode.Rule.Select(IPNetwork.Parse));
Logging.Info("代理 → 全局");
if (!RouteAction(Action.Create, IPNetwork.Parse("0.0.0.0", 0), RouteType.TUNTAP))
{
State = State.Stopped;
return false;
}
break;
}
Logging.Info("设置路由规则");
RouteAction(Action.Create, _directIPs, RouteType.Gateway);
RouteAction(Action.Create, _proxyIPs, RouteType.TUNTAP);
return true;
}
@@ -211,100 +170,21 @@ namespace Netch.Controllers
/// <summary>
/// 清除绕行规则
/// </summary>
public bool ClearBypass()
private bool ClearBypass()
{
if (_savedMode.Type == 2)
switch (_savedMode.Type)
{
NativeMethods.DeleteRoute("0.0.0.0", 0, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index, 10);
foreach (var ip in _savedMode.Rule)
{
var info = ip.Split('/');
if (info.Length == 2)
if (int.TryParse(info[1], out var prefix))
NativeMethods.DeleteRoute(info[0], prefix, Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
}
}
else if (_savedMode.Type == 1)
{
foreach (var ip in _savedMode.Rule)
{
var info = ip.Split('/');
if (info.Length == 2)
if (int.TryParse(info[1], out var prefix))
NativeMethods.DeleteRoute(info[0], prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
}
if (Global.Settings.STUN_Server == "stun.stunprotocol.org")
try
{
var nttAddress = Dns.GetHostAddresses(Global.Settings.STUN_Server)[0];
if (int.TryParse("32", out var prefix)) NativeMethods.DeleteRoute(nttAddress.ToString(), prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
var nttrAddress = Dns.GetHostAddresses("stunresponse.coldthunder11.com")[0];
if (int.TryParse("32", out var prefixr)) NativeMethods.DeleteRoute(nttrAddress.ToString(), prefixr, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
}
catch
{
}
if (Global.Settings.TUNTAP.ProxyDNS)
{
if (Global.Settings.TUNTAP.UseCustomDNS)
{
var dns = string.Empty;
foreach (var value in Global.Settings.TUNTAP.DNS)
{
dns += value;
dns += ',';
}
dns = dns.Trim();
dns = dns.Substring(0, dns.Length - 1);
if (int.TryParse("32", out var prefix)) NativeMethods.DeleteRoute(dns, prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
}
else
{
if (int.TryParse("32", out var prefix)) NativeMethods.DeleteRoute("1.1.1.1", prefix, Global.Settings.TUNTAP.Gateway, Global.TUNTAP.Index);
}
}
case 1:
break;
case 2:
RouteAction(Action.Delete, "0.0.0.0", 0, RouteType.TUNTAP, 10);
break;
}
foreach (var ip in Global.Settings.BypassIPs)
{
var info = ip.Split('/');
var address = IPAddress.Parse(info[0]);
if (!IPAddress.IsLoopback(address)) NativeMethods.DeleteRoute(address.ToString(), int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
}
foreach (var ip in _bypassLanIPs)
{
var info = ip.Split('/');
var address = IPAddress.Parse(info[0]);
if (!IPAddress.IsLoopback(address)) NativeMethods.DeleteRoute(address.ToString(), int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
}
if (_savedMode.BypassChina)
using (var sr = new StringReader(Encoding.UTF8.GetString(Resources.CNIP)))
{
string text;
while ((text = sr.ReadLine()) != null)
{
var info = text.Split('/');
NativeMethods.DeleteRoute(info[0], int.Parse(info[1]), Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
}
}
foreach (var address in _serverAddresses)
if (!IPAddress.IsLoopback(address))
NativeMethods.DeleteRoute(address.ToString(), 32, Global.Adapter.Gateway.ToString(), Global.Adapter.Index);
RouteAction(Action.Delete, _directIPs, RouteType.Gateway);
RouteAction(Action.Delete, _proxyIPs, RouteType.TUNTAP);
_directIPs.Clear();
_proxyIPs.Clear();
return true;
}
@@ -317,14 +197,11 @@ namespace Netch.Controllers
if (!Configure()) return false;
Logging.Info("设置绕行规则");
SetupBypass();
Logging.Info("设置绕行规则完毕");
SetupRouteTable();
Instance = GetProcess();
var adapterName = TUNTAP.GetName(Global.TUNTAP.ComponentID);
Logging.Info($"tun2sock使用适配器{adapterName}");
string dns;
//V2ray使用Unbound本地DNS会导致查询异常缓慢故此V2ray不启动unbound而是使用自定义DNS
@@ -372,8 +249,8 @@ namespace Netch.Controllers
case State.Started:
return true;
case State.Stopped:
Stop();
return false;
Stop();
return false;
}
}
@@ -395,74 +272,25 @@ namespace Netch.Controllers
}
/// <summary>
/// 搜索出口
/// 搜索出口和TUNTAP适配器
/// </summary>
public static bool SearchOutbounds()
private static bool SearchAdapters()
{
Logging.Info("正在搜索出口中");
NetworkInterface adapter;
Logging.Info("搜索适配器");
if (Win32Native.GetBestRoute(BitConverter.ToUInt32(IPAddress.Parse("114.114.114.114").GetAddressBytes(), 0), 0, out var pRoute) == 0)
{
Global.Adapter.Index = pRoute.dwForwardIfIndex;
adapter = NetworkInterface.GetAllNetworkInterfaces().First(_ => _.GetIPProperties().GetIPv4Properties().Index == Global.Adapter.Index);
Global.Adapter.Address = adapter.GetIPProperties().UnicastAddresses.First(ip => ip.Address.AddressFamily == AddressFamily.InterNetwork).Address;
Global.Adapter.Gateway = new IPAddress(pRoute.dwForwardNextHop);
Logging.Info($"当前 网关 地址:{Global.Adapter.Gateway}");
Logging.Info($"出口 IPv4 地址:{Global.Adapter.Address}");
Logging.Info($"出口 网关 地址:{Global.Adapter.Gateway}");
Logging.Info($"出口适配器:{adapter.Name} {adapter.Id} {adapter.Description}, index: {Global.Adapter.Index}");
}
else
{
Logging.Error("GetBestRoute 搜索失败");
return false;
}
Logging.Info($"搜索适配器index{Global.Adapter.Index}");
var AddressGot = false;
foreach (var adapter in NetworkInterface.GetAllNetworkInterfaces())
try
{
var adapterProperties = adapter.GetIPProperties();
var p = adapterProperties.GetIPv4Properties();
Logging.Info($"检测适配器:{adapter.Name} {adapter.Id} {adapter.Description}, index: {p.Index}");
// 通过索引查找对应适配器的 IPv4 地址
if (p.Index == Global.Adapter.Index)
{
var AdapterIPs = string.Empty;
foreach (var ip in adapterProperties.UnicastAddresses)
{
if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
{
AddressGot = true;
Global.Adapter.Address = ip.Address;
Logging.Info($"当前出口 IPv4 地址:{Global.Adapter.Address}");
break;
}
AdapterIPs = $"{ip.Address} | ";
}
if (!AddressGot)
{
if (AdapterIPs.Length > 3)
{
AdapterIPs = AdapterIPs.Substring(0, AdapterIPs.Length - 3);
Logging.Info($"所有出口地址:{AdapterIPs}");
}
Logging.Error("出口无 IPv4 地址,当前只支持 IPv4 地址");
return false;
}
break;
}
}
catch (Exception)
{
// ignored
}
if (!AddressGot)
{
Logging.Error("无法找到当前使用适配器");
Logging.Error("GetBestRoute 搜索失败(找不到出口适配器)");
return false;
}
@@ -470,11 +298,11 @@ namespace Netch.Controllers
Global.TUNTAP.ComponentID = TUNTAP.GetComponentID();
if (string.IsNullOrEmpty(Global.TUNTAP.ComponentID))
{
Logging.Error("未找到可用 TUN/TAP 适配器");
Logging.Error("未找到可用 TAP 适配器");
if (MessageBoxX.Show(i18N.Translate("TUN/TAP driver is not detected. Is it installed now?"), confirm: true) == DialogResult.OK)
{
Configuration.addtap();
//给点时间不然立马安装完毕就查找适配器可能会导致找不到适配器ID
// 给点时间不然立马安装完毕就查找适配器可能会导致找不到适配器ID
Thread.Sleep(1000);
Global.TUNTAP.ComponentID = TUNTAP.GetComponentID();
}
@@ -482,24 +310,62 @@ namespace Netch.Controllers
{
return false;
}
//MessageBoxX.Show(i18N.Translate("Please install TAP-Windows and create an TUN/TAP adapter manually"));
// return false;
}
foreach (var adapter in NetworkInterface.GetAllNetworkInterfaces())
if (adapter.Id == Global.TUNTAP.ComponentID)
{
Global.TUNTAP.Adapter = adapter;
Global.TUNTAP.Index = adapter.GetIPProperties().GetIPv4Properties().Index;
adapter = NetworkInterface.GetAllNetworkInterfaces().First(_ => _.Id == Global.TUNTAP.ComponentID);
Global.TUNTAP.Adapter = adapter;
Global.TUNTAP.Index = adapter.GetIPProperties().GetIPv4Properties().Index;
Logging.Info($"TAP 适配器:{adapter.Name} {adapter.Id} {adapter.Description}, index: {Global.TUNTAP.Index}");
return true;
}
Logging.Info($"找到适配器TUN/TAP{adapter.Id}");
return true;
}
private enum RouteType
{
Gateway,
TUNTAP
}
Logging.Error("无法找到出口");
return false;
private enum Action
{
Create,
Delete
}
private static bool RouteAction(Action action, IEnumerable<IPNetwork> ipNetworks, RouteType routeType, int metric = 0)
{
return ipNetworks.All(address => RouteAction(action, address, routeType, metric));
}
private static bool RouteAction(Action action, string address, byte cidr, RouteType routeType, int metric = 0)
{
return RouteAction(action, IPNetwork.Parse(address, cidr), routeType, metric);
}
private static bool RouteAction(Action action, IPNetwork ipNetwork, RouteType routeType, int metric = 0)
{
string gateway;
int index;
switch (routeType)
{
case RouteType.Gateway:
gateway = Global.Adapter.Gateway.ToString();
index = Global.Adapter.Index;
break;
case RouteType.TUNTAP:
gateway = Global.Settings.TUNTAP.Gateway;
index = Global.TUNTAP.Index;
break;
default:
throw new ArgumentOutOfRangeException(nameof(routeType), routeType, null);
}
return action switch
{
Action.Create => NativeMethods.CreateRoute(ipNetwork.Network.ToString(), ipNetwork.Cidr, gateway, index, metric),
Action.Delete => NativeMethods.DeleteRoute(ipNetwork.Network.ToString(), ipNetwork.Cidr, gateway, index, metric),
_ => throw new ArgumentOutOfRangeException(nameof(action), action, null)
};
}
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.ComponentModel;
using System.Diagnostics;
using Netch.Models;
using Netch.Utils;
@@ -43,7 +44,7 @@ namespace Netch.Controllers
return (true, natType, localEnd, publicEnd);
}
catch (Exception e)
catch (Win32Exception e)
{
Logging.Error("NTT 进程出错\n" + e);
Stop();

View File

@@ -1,7 +1,6 @@
using System;
using System.Linq;
using System.Net;
using System.ServiceProcess;
using System.Threading.Tasks;
using System.Windows.Forms;
using Netch.Controllers;
@@ -9,7 +8,6 @@ using Netch.Forms.Mode;
using Netch.Forms.Server;
using Netch.Models;
using Netch.Utils;
using nfapinet;
using Trojan = Netch.Forms.Server.Trojan;
using VMess = Netch.Forms.Server.VMess;
using WebClient = Netch.Override.WebClient;
@@ -39,7 +37,7 @@ namespace Netch.Forms
}
else
{
MessageBoxX.Show(i18N.Translate("Import servers error!"), info: false);
MessageBoxX.Show(i18N.Translate("Import servers error!"), LogLevel.ERROR);
}
InitServer();
@@ -246,8 +244,7 @@ namespace Netch.Forms
}
catch (Exception e)
{
MessageBoxX.Show(e.ToString(),info:false);
Console.WriteLine(e);
MessageBoxX.Show(e.ToString(),LogLevel.ERROR);
throw;
}
Enabled = true;
@@ -290,7 +287,7 @@ namespace Netch.Forms
private void OpenDirectoryToolStripMenuItem_Click(object sender, EventArgs e)
{
Utils.Utils.OpenDir(@".\");
Utils.Utils.Open(@".\");
}
private void reinstallTapDriverToolStripMenuItem_Click(object sender, EventArgs e)

View File

@@ -11,7 +11,7 @@ namespace Netch
/// <summary>
/// 换行
/// </summary>
public static string EOF = "\r\n";
public const string EOF = "\r\n";
public static readonly string NetchDir = (AppDomain.CurrentDomain.BaseDirectory).TrimEnd();

9
Netch/Models/LogLevel.cs Normal file
View File

@@ -0,0 +1,9 @@
namespace Netch.Models
{
public enum LogLevel
{
INFO,
WARNING,
ERROR
}
}

View File

@@ -8,25 +8,25 @@ namespace Netch
/// 创建路由规则
/// </summary>
/// <param name="address">目标地址</param>
/// <param name="netmask">掩码地址</param>
/// <param name="cidr">CIDR</param>
/// <param name="gateway">网关地址</param>
/// <param name="index">适配器索引</param>
/// <param name="metric">跃点数</param>
/// <returns>是否成功</returns>
[DllImport("bin\\NetchCore", CallingConvention = CallingConvention.Cdecl, EntryPoint = "CreateRoute")]
public static extern bool CreateRoute(string address, int netmask, string gateway, int index, int metric = 0);
public static extern bool CreateRoute(string address, int cidr, string gateway, int index, int metric = 0);
/// <summary>
/// 修改路由规则
/// </summary>
/// <param name="address">目标地址</param>
/// <param name="netmask">掩码地址</param>
/// <param name="cidr">CIDR</param>
/// <param name="gateway">网关地址</param>
/// <param name="index">适配器索引</param>
/// <param name="metric">跃点数</param>
/// <returns>是否成功</returns>
[DllImport("bin\\NetchCore", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ChangeRoute")]
public static extern bool ChangeRoute(string address, int netmask, string gateway, int index, int metric = 0);
public static extern bool ChangeRoute(string address, int cidr, string gateway, int index, int metric = 0);
/// <summary>
/// 删除路由规则
@@ -38,7 +38,7 @@ namespace Netch
/// <param name="metric">跃点数</param>
/// <returns>是否成功</returns>
[DllImport("bin\\NetchCore", CallingConvention = CallingConvention.Cdecl, EntryPoint = "DeleteRoute")]
public static extern bool DeleteRoute(string address, int netmask, string gateway, int index, int metric = 0);
public static extern bool DeleteRoute(string address, int cidr, string gateway, int index, int metric = 0);
/// <summary>
/// 设置直连

View File

@@ -58,8 +58,8 @@ namespace Netch
// 记录当前系统语言
Logging.Info($"当前语言:{Global.Settings.Language}");
Logging.Info($"版本:{UpdateChecker.Owner}/{UpdateChecker.Repo} {UpdateChecker.Version}");
Logging.Info($"主程序创建日期:{File.GetCreationTime(Global.NetchDir + "\\Netch.exe"):yyyy-M-d HH:mm}");
Logging.Info($"版本: {UpdateChecker.Owner}/{UpdateChecker.Repo}@{UpdateChecker.Version}");
Logging.Info($"主程序创建日期: {File.GetCreationTime(Global.NetchDir + "\\Netch.exe"):yyyy-M-d HH:mm}");
// 检查是否已经运行
if (!mutex.WaitOne(0, false))
@@ -85,7 +85,9 @@ namespace Netch
{
if (!e.Exception.ToString().Contains("ComboBox"))
{
MessageBox.Show(e.Exception.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
Logging.Error("错误\n" + e);
Utils.Utils.Open(Logging.LogFile);
// MessageBox.Show(e.Exception.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
//Application.Exit();
}

View File

@@ -58,6 +58,7 @@
<ItemGroup>
<PackageReference Include="ini-parser" Version="2.5.2" />
<PackageReference Include="IPNetwork2" Version="2.5.211" />
<PackageReference Include="MaxMind.GeoIP2" Version="3.2.0" />
<PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="2.0.56" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />

View File

@@ -1,11 +1,12 @@
using System;
using System.IO;
using Netch.Models;
namespace Netch.Utils
{
public static class Logging
public static partial class Logging
{
private const string LogFile = "logging\\application.log";
public const string LogFile = "logging\\application.log";
/// <summary>
/// 信息
@@ -13,7 +14,7 @@ namespace Netch.Utils
/// <param name="text">内容</param>
public static void Info(string text)
{
File.AppendAllText(LogFile, $@"[{DateTime.Now}][INFO] {text}{Global.EOF}");
Write(text, LogLevel.INFO);
}
/// <summary>
@@ -22,7 +23,7 @@ namespace Netch.Utils
/// <param name="text">内容</param>
public static void Warning(string text)
{
File.AppendAllText(LogFile, $@"[{DateTime.Now}][WARNING] {text}{Global.EOF}");
Write(text, LogLevel.WARNING);
}
/// <summary>
@@ -31,7 +32,12 @@ namespace Netch.Utils
/// <param name="text">内容</param>
public static void Error(string text)
{
File.AppendAllText(LogFile, $@"[{DateTime.Now}][ERROR] {text}{Global.EOF}");
Write(text, LogLevel.ERROR);
}
private static void Write(string text, LogLevel logLevel)
{
File.AppendAllText(LogFile, $@"[{DateTime.Now}][{logLevel.ToString()}] {text}{Global.EOF}");
}
}
}

View File

@@ -1,4 +1,6 @@
using System.Windows.Forms;
using System;
using System.Windows.Forms;
using Netch.Models;
namespace Netch.Utils
{
@@ -8,17 +10,35 @@ namespace Netch.Utils
/// </summary>
/// <param name="text">内容</param>
/// <param name="title">自定义标题</param>
/// <param name="info">弹窗等级 (标题, 图标)</param>
/// <param name="level">弹窗等级 (标题, 图标)</param>
/// <param name="confirm">需要确认</param>
/// <param name="owner">阻止 owner Focus() 直到 Messageox 被关闭</param>
public static DialogResult Show(string text, string title = "", bool info = true, bool confirm = false,IWin32Window owner = null)
public static DialogResult Show(string text, LogLevel level = LogLevel.INFO, string title = "", bool confirm = false, IWin32Window owner = null)
{
MessageBoxIcon msgIcon;
if (string.IsNullOrWhiteSpace(title))
title = level switch
{
LogLevel.INFO => "Information",
LogLevel.WARNING => "Warning",
LogLevel.ERROR => "Error",
_ => throw new ArgumentOutOfRangeException(nameof(level), level, null)
};
msgIcon = level switch
{
LogLevel.INFO => MessageBoxIcon.Information,
LogLevel.WARNING => MessageBoxIcon.Warning,
LogLevel.ERROR => MessageBoxIcon.Exclamation,
_ => throw new ArgumentOutOfRangeException(nameof(level), level, null)
};
return MessageBox.Show(
owner: owner,
text: text,
caption: i18N.Translate(string.IsNullOrWhiteSpace(title) ? (info ? "Information" : "Error") : title),
caption: i18N.Translate(title),
buttons: confirm ? MessageBoxButtons.OKCancel : MessageBoxButtons.OK,
icon: info ? MessageBoxIcon.Information : MessageBoxIcon.Exclamation);
icon: msgIcon);
}
}
}

View File

@@ -11,17 +11,16 @@ namespace Netch.Utils
{
public static class Utils
{
public static bool OpenUrl(string path)
public static bool Open(string path)
{
try
{
new Process
Process.Start(new ProcessStartInfo()
{
StartInfo = new ProcessStartInfo(path)
{
UseShellExecute = true
}
}.Start();
FileName = "explorer.exe",
Arguments = path,
UseShellExecute = true
});
return true;
}
catch
@@ -30,23 +29,6 @@ namespace Netch.Utils
}
}
public static bool OpenDir(string dir)
{
if (Directory.Exists(dir))
{
try
{
return OpenUrl(dir);
}
catch
{
// ignored
}
}
return false;
}
public static async Task<int> TCPingAsync(IPAddress ip, int port, int timeout = 1000, CancellationToken ct = default)
{
using var client = new TcpClient(ip.AddressFamily);