diff --git a/Netch/Controllers/MainController.cs b/Netch/Controllers/MainController.cs index ed00a620..b5fe036f 100644 --- a/Netch/Controllers/MainController.cs +++ b/Netch/Controllers/MainController.cs @@ -1,11 +1,11 @@ using System; +using System.Diagnostics; using System.IO; using System.Threading; using System.Threading.Tasks; using Netch.Models; using Netch.Servers.Socks5; using Netch.Utils; -using static Netch.Utils.PortHelper; namespace Netch.Controllers { @@ -105,10 +105,7 @@ namespace Netch.Controllers { controller = ServerHelper.GetUtilByTypeName(server.Type).GetController(); - if (controller is Guard instanceController) - Utils.Utils.KillProcessByName(instanceController.MainFile); - - PortCheck(controller.Socks5LocalPort(), "Socks5"); + TryReleaseTcpPort(controller.Socks5LocalPort(), "Socks5"); Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", controller.Name)); @@ -133,13 +130,13 @@ namespace Netch.Controllers private static void StartMode(Mode mode) { - ModeController = ModeHelper.GetModeControllerByType(mode.Type, out var port, out var portName, out var portType); + ModeController = ModeHelper.GetModeControllerByType(mode.Type, out var port, out var portName); if (ModeController == null) return; if (port != null) - PortCheck((ushort) port, portName, portType); + TryReleaseTcpPort((ushort) port, portName); Global.MainForm.StatusText(i18N.TranslateFormat("Starting {0}", ModeController.Name)); @@ -189,7 +186,7 @@ namespace Netch.Controllers { try { - CheckPort(port, portType); + PortHelper.CheckPort(port, portType); } catch (PortInUseException) { @@ -200,6 +197,27 @@ namespace Netch.Controllers throw new MessageException(i18N.TranslateFormat("The {0} port is reserved by system.", $"{portName} ({port})")); } } + + public static void TryReleaseTcpPort(ushort port, string portName) + { + Process? p; + if ((p = PortHelper.GetProcessByUsedTcpPort(port)) != null) + { + if (p.MainModule!.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}")); + } + } + + PortCheck(port, portName, PortType.TCP); + } } public class MessageException : Exception diff --git a/Netch/Utils/ModeHelper.cs b/Netch/Utils/ModeHelper.cs index 1df0d234..8d7357ff 100644 --- a/Netch/Utils/ModeHelper.cs +++ b/Netch/Utils/ModeHelper.cs @@ -137,17 +137,15 @@ namespace Netch.Utils }; } - public static IModeController? GetModeControllerByType(int type, out ushort? port, out string portName, out PortType portType) + public static IModeController? GetModeControllerByType(int type, out ushort? port, out string portName) { port = null; portName = string.Empty; - portType = PortType.Both; switch (type) { case 0: port = Global.Settings.RedirectorTCPPort; portName = "Redirector TCP"; - portType = PortType.TCP; return new NFController(); case 1: case 2: @@ -156,7 +154,6 @@ namespace Netch.Utils case 5: port = Global.Settings.HTTPLocalPort; portName = "HTTP"; - portType = PortType.TCP; StatusPortInfoText.HttpPort = (ushort) port; return new HTTPController(); case 4: diff --git a/Netch/Utils/PortHelper.cs b/Netch/Utils/PortHelper.cs index 790ad8fe..f857cf1c 100644 --- a/Netch/Utils/PortHelper.cs +++ b/Netch/Utils/PortHelper.cs @@ -4,6 +4,8 @@ using System.Diagnostics; using System.Linq; using System.Net.NetworkInformation; using Netch.Models; +using static Vanara.PInvoke.IpHlpApi; +using static Vanara.PInvoke.Ws2_32; namespace Netch.Utils { @@ -26,6 +28,18 @@ namespace Netch.Utils } } + public static Process? GetProcessByUsedTcpPort(ushort port) + { + if (port == 0) + throw new ArgumentOutOfRangeException(); + + var row = GetTcpTable2().SingleOrDefault(r => ntohs((ushort) r.dwLocalPort) == port); + if (row.dwOwningPid == 0) + return null; + + return Process.GetProcessById((int) row.dwOwningPid); + } + private static void GetReservedPortRange(PortType portType, ref List targetList) { var process = new Process diff --git a/Netch/Utils/Utils.cs b/Netch/Utils/Utils.cs index 107bbbe3..5bc6c944 100644 --- a/Netch/Utils/Utils.cs +++ b/Netch/Utils/Utils.cs @@ -114,24 +114,6 @@ namespace Netch.Utils } } - public static void KillProcessByName(string name) - { - try - { - foreach (var p in Process.GetProcessesByName(name)) - if (p.MainModule != null && p.MainModule.FileName.StartsWith(Global.NetchDir)) - p.Kill(); - } - catch (Win32Exception e) - { - Logging.Error($"结束进程 {name} 错误:" + e.Message); - } - catch (Exception) - { - // ignored - } - } - public static string GetFileVersion(string file) { return File.Exists(file) ? FileVersionInfo.GetVersionInfo(file).FileVersion : string.Empty;