diff --git a/v2rayN/v2rayN/Common/Utils.cs b/v2rayN/v2rayN/Common/Utils.cs index 64df907e..7dbbe6c0 100644 --- a/v2rayN/v2rayN/Common/Utils.cs +++ b/v2rayN/v2rayN/Common/Utils.cs @@ -22,6 +22,7 @@ using ZXing; using ZXing.Common; using ZXing.QrCode; using ZXing.Windows.Compatibility; +using Vanara.PInvoke; namespace v2rayN { @@ -756,7 +757,7 @@ namespace v2rayN public static void SetDarkBorder(System.Windows.Window window, bool dark) { // Make sure the handle is created before the window is shown - IntPtr hWnd = new System.Windows.Interop.WindowInteropHelper(window).EnsureHandle(); + IntPtr hWnd = new WindowInteropHelper(window).EnsureHandle(); int attribute = dark ? 1 : 0; uint attributeSize = (uint)Marshal.SizeOf(attribute); DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1, ref attribute, attributeSize); @@ -1170,6 +1171,42 @@ namespace v2rayN } } + public static bool RemoveDeviceByDevIstId(string deviceInstanceId) + { + var isRemoved = false; + var devs = SetupAPI.SetupDiGetClassDevs(SetupAPI.GUID_DEVCLASS_NET, null, HWND.NULL, SetupAPI.DIGCF.DIGCF_PROFILE); + var instanceIdSize = deviceInstanceId.Length + 1; + var devInfo = new SetupAPI.SP_DEVINFO_DATA() { cbSize = (uint)Marshal.SizeOf() }; + var instanceId = new StringBuilder(instanceIdSize); + uint index = 0; + + while (SetupAPI.SetupDiEnumDeviceInfo(devs, index++, ref devInfo)) + { + var success = SetupAPI.SetupDiGetDeviceInstanceId(devs, devInfo, instanceId, (uint)instanceIdSize, out uint size); + if (success && size == instanceIdSize && instanceId.ToString() == deviceInstanceId) + { + isRemoved = SetupAPI.SetupDiRemoveDevice(devs, ref devInfo); + } + } + SetupAPI.SetupDiDestroyDeviceInfoList(devs); + + return isRemoved; + } + + public static string GetSingboxTunDeviceInstanceId(string deviceName) + { + string deviceInstanceId = string.Empty; + string deviceId = "SWD\\WINTUN\\"; + + if (!string.IsNullOrEmpty(deviceName)) + { + List data = [.. Encoding.UTF8.GetBytes("wintun"), .. Encoding.UTF8.GetBytes(deviceName)]; + byte[] hash = MD5.HashData(data.ToArray()); + deviceInstanceId = deviceId + new Guid(hash).ToString("B").ToUpper(); + } + return deviceInstanceId; + } + #endregion 开机自动启动等 #region Windows API diff --git a/v2rayN/v2rayN/Global.cs b/v2rayN/v2rayN/Global.cs index 9df96dc0..a9d6900e 100644 --- a/v2rayN/v2rayN/Global.cs +++ b/v2rayN/v2rayN/Global.cs @@ -43,6 +43,7 @@ namespace v2rayN public const string DNSV2rayNormalFileName = "v2rayN.Sample.dns_v2ray_normal"; public const string DNSSingboxNormalFileName = "v2rayN.Sample.dns_singbox_normal"; + public const string DefaultSingboxTunDeviceName = "tun_singbox"; public const string DefaultSecurity = "auto"; public const string DefaultNetwork = "tcp"; public const string TcpHeaderHttp = "http"; diff --git a/v2rayN/v2rayN/Handler/CoreHandler.cs b/v2rayN/v2rayN/Handler/CoreHandler.cs index 6e7e685e..4f8137a4 100644 --- a/v2rayN/v2rayN/Handler/CoreHandler.cs +++ b/v2rayN/v2rayN/Handler/CoreHandler.cs @@ -54,7 +54,7 @@ namespace v2rayN.Handler { ShowMsg(true, $"{node!.GetSummary()}"); CoreStop(); - Utils.RemoveTunDevice(); + Utils.RemoveDeviceByDevIstId(Utils.GetSingboxTunDeviceInstanceId(Global.DefaultSingboxTunDeviceName)); CoreStart(node); } executingResetEvents.ForEach(result => result.Set()); diff --git a/v2rayN/v2rayN/v2rayN.csproj b/v2rayN/v2rayN/v2rayN.csproj index 2610148f..503ddc41 100644 --- a/v2rayN/v2rayN/v2rayN.csproj +++ b/v2rayN/v2rayN/v2rayN.csproj @@ -20,7 +20,8 @@ - + +