From 9b01195f29d67ebca4072ffa4e56b62fd2d0b4c8 Mon Sep 17 00:00:00 2001 From: UMMANCODE Date: Thu, 18 Jul 2024 17:52:32 +0400 Subject: [PATCH] Modern namespaces and typos fixed --- v2rayN/ProtosLib/Tests.cs | 17 +- v2rayN/v2rayN/Base/MyDGTextColumn.cs | 10 +- v2rayN/v2rayN/Common/DownloaderHelper.cs | 345 ++- v2rayN/v2rayN/Common/FileManager.cs | 163 +- v2rayN/v2rayN/Common/HttpClientHelper.cs | 355 ++- v2rayN/v2rayN/Common/Job.cs | 304 ++- v2rayN/v2rayN/Common/JsonUtils.cs | 249 +- v2rayN/v2rayN/Common/Logging.cs | 137 +- v2rayN/v2rayN/Common/ProxySetting.cs | 705 +++--- v2rayN/v2rayN/Common/QRCodeHelper.cs | 177 +- v2rayN/v2rayN/Common/QueryableExtension.cs | 69 +- v2rayN/v2rayN/Common/SemanticVersion.cs | 351 ++- v2rayN/v2rayN/Common/SqliteHelper.cs | 231 +- v2rayN/v2rayN/Common/StringEx.cs | 171 +- v2rayN/v2rayN/Common/UI.cs | 61 +- v2rayN/v2rayN/Common/Utils.cs | 2209 ++++++++--------- v2rayN/v2rayN/Common/YamlUtils.cs | 101 +- .../v2rayN/Converters/DelayColorConverter.cs | 35 +- .../Converters/InverseBooleanConverter.cs | 33 +- .../v2rayN/Converters/MaterialDesignFonts.cs | 41 +- v2rayN/v2rayN/Enums/EConfigType.cs | 27 +- v2rayN/v2rayN/Enums/ECoreType.cs | 35 +- v2rayN/v2rayN/Enums/EGlobalHotkey.cs | 17 +- v2rayN/v2rayN/Enums/EInboundProtocol.cs | 23 +- v2rayN/v2rayN/Enums/EMove.cs | 17 +- v2rayN/v2rayN/Enums/ERuleMode.cs | 15 +- v2rayN/v2rayN/Enums/EServerColName.cs | 37 +- v2rayN/v2rayN/Enums/ESpeedActionType.cs | 15 +- v2rayN/v2rayN/Enums/ESysProxyType.cs | 15 +- v2rayN/v2rayN/Enums/ETransport.cs | 25 +- v2rayN/v2rayN/Enums/EViewAction.cs | 11 +- v2rayN/v2rayN/Global.cs | 349 ++- .../v2rayN/Properties/Resources.Designer.cs | 420 ++-- v2rayN/v2rayUpgrade/MainForm.cs | 273 +- v2rayN/v2rayUpgrade/Program.cs | 31 +- 35 files changed, 3518 insertions(+), 3556 deletions(-) diff --git a/v2rayN/ProtosLib/Tests.cs b/v2rayN/ProtosLib/Tests.cs index e1eb85b1..062550fb 100644 --- a/v2rayN/ProtosLib/Tests.cs +++ b/v2rayN/ProtosLib/Tests.cs @@ -1,13 +1,12 @@ using ProtosLib.Statistics; -namespace ProtosLib -{ - public class Tests - { - private StatsService.StatsServiceClient client_; +namespace ProtosLib; - public Tests() - { - } - } +public class Tests +{ + private StatsService.StatsServiceClient client_; + + public Tests() + { + } } \ No newline at end of file diff --git a/v2rayN/v2rayN/Base/MyDGTextColumn.cs b/v2rayN/v2rayN/Base/MyDGTextColumn.cs index 427ffacc..bbbcdcfb 100644 --- a/v2rayN/v2rayN/Base/MyDGTextColumn.cs +++ b/v2rayN/v2rayN/Base/MyDGTextColumn.cs @@ -1,9 +1,7 @@ using System.Windows.Controls; -namespace v2rayN.Base -{ - internal class MyDGTextColumn : DataGridTextColumn - { - public string ExName { get; set; } - } +namespace v2rayN.Base; + +internal class MyDGTextColumn : DataGridTextColumn { + public string ExName { get; set; } } \ No newline at end of file diff --git a/v2rayN/v2rayN/Common/DownloaderHelper.cs b/v2rayN/v2rayN/Common/DownloaderHelper.cs index ddfe3811..89196fd0 100644 --- a/v2rayN/v2rayN/Common/DownloaderHelper.cs +++ b/v2rayN/v2rayN/Common/DownloaderHelper.cs @@ -2,180 +2,179 @@ using System.IO; using System.Net; -namespace v2rayN +namespace v2rayN; + +internal class DownloaderHelper { - internal class DownloaderHelper + private static readonly Lazy _instance = new(() => new()); + public static DownloaderHelper Instance => _instance.Value; + + public async Task DownloadStringAsync(IWebProxy? webProxy, string url, string? userAgent, int timeout) + { + if (Utils.IsNullOrEmpty(url)) { - private static readonly Lazy _instance = new(() => new()); - public static DownloaderHelper Instance => _instance.Value; - - public async Task DownloadStringAsync(IWebProxy? webProxy, string url, string? userAgent, int timeout) - { - if (Utils.IsNullOrEmpty(url)) - { - return null; - } - - Uri uri = new(url); - //Authorization Header - var headers = new WebHeaderCollection(); - if (!Utils.IsNullOrEmpty(uri.UserInfo)) - { - headers.Add(HttpRequestHeader.Authorization, "Basic " + Utils.Base64Encode(uri.UserInfo)); - } - - var downloadOpt = new DownloadConfiguration() - { - Timeout = timeout * 1000, - MaxTryAgainOnFailover = 2, - RequestConfiguration = - { - Headers = headers, - UserAgent = userAgent, - Timeout = timeout * 1000, - Proxy = webProxy - } - }; - - using var downloader = new DownloadService(downloadOpt); - downloader.DownloadFileCompleted += (sender, value) => - { - if (value.Error != null) - { - throw value.Error; - } - }; - - using var cts = new CancellationTokenSource(); - using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token).WaitAsync(TimeSpan.FromSeconds(timeout), cts.Token); - using StreamReader reader = new(stream); - - downloadOpt = null; - - return reader.ReadToEnd(); - } - - public async Task DownloadDataAsync4Speed(IWebProxy webProxy, string url, IProgress progress, int timeout) - { - if (Utils.IsNullOrEmpty(url)) - { - throw new ArgumentNullException(nameof(url)); - } - - var downloadOpt = new DownloadConfiguration() - { - Timeout = timeout * 1000, - MaxTryAgainOnFailover = 2, - RequestConfiguration = - { - Timeout= timeout * 1000, - Proxy = webProxy - } - }; - - DateTime totalDatetime = DateTime.Now; - int totalSecond = 0; - var hasValue = false; - double maxSpeed = 0; - using var downloader = new DownloadService(downloadOpt); - //downloader.DownloadStarted += (sender, value) => - //{ - // if (progress != null) - // { - // progress.Report("Start download data..."); - // } - //}; - downloader.DownloadProgressChanged += (sender, value) => - { - TimeSpan ts = (DateTime.Now - totalDatetime); - if (progress != null && ts.Seconds > totalSecond) - { - hasValue = true; - totalSecond = ts.Seconds; - if (value.BytesPerSecondSpeed > maxSpeed) - { - maxSpeed = value.BytesPerSecondSpeed; - var speed = (maxSpeed / 1000 / 1000).ToString("#0.0"); - progress.Report(speed); - } - } - }; - downloader.DownloadFileCompleted += (sender, value) => - { - if (progress != null) - { - if (!hasValue && value.Error != null) - { - progress.Report(value.Error?.Message); - } - } - }; - //progress.Report("......"); - using var cts = new CancellationTokenSource(); - cts.CancelAfter(timeout * 1000); - using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token); - - downloadOpt = null; - } - - public async Task DownloadFileAsync(IWebProxy? webProxy, string url, string fileName, IProgress progress, int timeout) - { - if (Utils.IsNullOrEmpty(url)) - { - throw new ArgumentNullException(nameof(url)); - } - if (Utils.IsNullOrEmpty(fileName)) - { - throw new ArgumentNullException(nameof(fileName)); - } - if (File.Exists(fileName)) - { - File.Delete(fileName); - } - - var downloadOpt = new DownloadConfiguration() - { - Timeout = timeout * 1000, - MaxTryAgainOnFailover = 2, - RequestConfiguration = - { - Timeout= timeout * 1000, - Proxy = webProxy - } - }; - - var progressPercentage = 0; - var hasValue = false; - using var downloader = new DownloadService(downloadOpt); - downloader.DownloadStarted += (sender, value) => - { - progress?.Report(0); - }; - downloader.DownloadProgressChanged += (sender, value) => - { - hasValue = true; - var percent = (int)value.ProgressPercentage;// Convert.ToInt32((totalRead * 1d) / (total * 1d) * 100); - if (progressPercentage != percent && percent % 10 == 0) - { - progressPercentage = percent; - progress.Report(percent); - } - }; - downloader.DownloadFileCompleted += (sender, value) => - { - if (progress != null) - { - if (hasValue && value.Error == null) - { - progress.Report(101); - } - } - }; - - using var cts = new CancellationTokenSource(); - await downloader.DownloadFileTaskAsync(url, fileName, cts.Token).WaitAsync(TimeSpan.FromSeconds(timeout), cts.Token); - - downloadOpt = null; - } + return null; } + + Uri uri = new(url); + //Authorization Header + var headers = new WebHeaderCollection(); + if (!Utils.IsNullOrEmpty(uri.UserInfo)) + { + headers.Add(HttpRequestHeader.Authorization, "Basic " + Utils.Base64Encode(uri.UserInfo)); + } + + var downloadOpt = new DownloadConfiguration() + { + Timeout = timeout * 1000, + MaxTryAgainOnFailover = 2, + RequestConfiguration = + { + Headers = headers, + UserAgent = userAgent, + Timeout = timeout * 1000, + Proxy = webProxy + } + }; + + using var downloader = new DownloadService(downloadOpt); + downloader.DownloadFileCompleted += (sender, value) => + { + if (value.Error != null) + { + throw value.Error; + } + }; + + using var cts = new CancellationTokenSource(); + using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token).WaitAsync(TimeSpan.FromSeconds(timeout), cts.Token); + using StreamReader reader = new(stream); + + downloadOpt = null; + + return reader.ReadToEnd(); + } + + public async Task DownloadDataAsync4Speed(IWebProxy webProxy, string url, IProgress progress, int timeout) + { + if (Utils.IsNullOrEmpty(url)) + { + throw new ArgumentNullException(nameof(url)); + } + + var downloadOpt = new DownloadConfiguration() + { + Timeout = timeout * 1000, + MaxTryAgainOnFailover = 2, + RequestConfiguration = + { + Timeout= timeout * 1000, + Proxy = webProxy + } + }; + + DateTime totalDatetime = DateTime.Now; + int totalSecond = 0; + var hasValue = false; + double maxSpeed = 0; + using var downloader = new DownloadService(downloadOpt); + //downloader.DownloadStarted += (sender, value) => + //{ + // if (progress != null) + // { + // progress.Report("Start download data..."); + // } + //}; + downloader.DownloadProgressChanged += (sender, value) => + { + TimeSpan ts = (DateTime.Now - totalDatetime); + if (progress != null && ts.Seconds > totalSecond) + { + hasValue = true; + totalSecond = ts.Seconds; + if (value.BytesPerSecondSpeed > maxSpeed) + { + maxSpeed = value.BytesPerSecondSpeed; + var speed = (maxSpeed / 1000 / 1000).ToString("#0.0"); + progress.Report(speed); + } + } + }; + downloader.DownloadFileCompleted += (sender, value) => + { + if (progress != null) + { + if (!hasValue && value.Error != null) + { + progress.Report(value.Error?.Message); + } + } + }; + //progress.Report("......"); + using var cts = new CancellationTokenSource(); + cts.CancelAfter(timeout * 1000); + using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token); + + downloadOpt = null; + } + + public async Task DownloadFileAsync(IWebProxy? webProxy, string url, string fileName, IProgress progress, int timeout) + { + if (Utils.IsNullOrEmpty(url)) + { + throw new ArgumentNullException(nameof(url)); + } + if (Utils.IsNullOrEmpty(fileName)) + { + throw new ArgumentNullException(nameof(fileName)); + } + if (File.Exists(fileName)) + { + File.Delete(fileName); + } + + var downloadOpt = new DownloadConfiguration() + { + Timeout = timeout * 1000, + MaxTryAgainOnFailover = 2, + RequestConfiguration = + { + Timeout= timeout * 1000, + Proxy = webProxy + } + }; + + var progressPercentage = 0; + var hasValue = false; + using var downloader = new DownloadService(downloadOpt); + downloader.DownloadStarted += (sender, value) => + { + progress?.Report(0); + }; + downloader.DownloadProgressChanged += (sender, value) => + { + hasValue = true; + var percent = (int)value.ProgressPercentage;// Convert.ToInt32((totalRead * 1d) / (total * 1d) * 100); + if (progressPercentage != percent && percent % 10 == 0) + { + progressPercentage = percent; + progress.Report(percent); + } + }; + downloader.DownloadFileCompleted += (sender, value) => + { + if (progress != null) + { + if (hasValue && value.Error == null) + { + progress.Report(101); + } + } + }; + + using var cts = new CancellationTokenSource(); + await downloader.DownloadFileTaskAsync(url, fileName, cts.Token).WaitAsync(TimeSpan.FromSeconds(timeout), cts.Token); + + downloadOpt = null; + } } \ No newline at end of file diff --git a/v2rayN/v2rayN/Common/FileManager.cs b/v2rayN/v2rayN/Common/FileManager.cs index b721f5db..24976078 100644 --- a/v2rayN/v2rayN/Common/FileManager.cs +++ b/v2rayN/v2rayN/Common/FileManager.cs @@ -2,89 +2,88 @@ using System.IO.Compression; using System.Text; -namespace v2rayN +namespace v2rayN; + +public static class FileManager { - public static class FileManager + public static bool ByteArrayToFile(string fileName, byte[] content) + { + try { - public static bool ByteArrayToFile(string fileName, byte[] content) - { - try - { - File.WriteAllBytes(fileName, content); - return true; - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - } - return false; - } - - public static void UncompressedFile(string fileName, byte[] content) - { - try - { - using FileStream fs = File.Create(fileName); - using GZipStream input = new(new MemoryStream(content), CompressionMode.Decompress, false); - input.CopyTo(fs); - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - } - } - - public static string NonExclusiveReadAllText(string path) - { - return NonExclusiveReadAllText(path, Encoding.Default); - } - - public static string NonExclusiveReadAllText(string path, Encoding encoding) - { - try - { - using FileStream fs = new(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - using StreamReader sr = new(fs, encoding); - return sr.ReadToEnd(); - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - throw; - } - } - - public static bool ZipExtractToFile(string fileName, string toPath, string ignoredName) - { - try - { - using ZipArchive archive = ZipFile.OpenRead(fileName); - foreach (ZipArchiveEntry entry in archive.Entries) - { - if (entry.Length == 0) - { - continue; - } - try - { - if (!Utils.IsNullOrEmpty(ignoredName) && entry.Name.Contains(ignoredName)) - { - continue; - } - entry.ExtractToFile(Path.Combine(toPath, entry.Name), true); - } - catch (IOException ex) - { - Logging.SaveLog(ex.Message, ex); - } - } - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - return false; - } - return true; - } + File.WriteAllBytes(fileName, content); + return true; } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + } + return false; + } + + public static void UncompressedFile(string fileName, byte[] content) + { + try + { + using FileStream fs = File.Create(fileName); + using GZipStream input = new(new MemoryStream(content), CompressionMode.Decompress, false); + input.CopyTo(fs); + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + } + } + + public static string NonExclusiveReadAllText(string path) + { + return NonExclusiveReadAllText(path, Encoding.Default); + } + + public static string NonExclusiveReadAllText(string path, Encoding encoding) + { + try + { + using FileStream fs = new(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + using StreamReader sr = new(fs, encoding); + return sr.ReadToEnd(); + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + throw; + } + } + + public static bool ZipExtractToFile(string fileName, string toPath, string ignoredName) + { + try + { + using ZipArchive archive = ZipFile.OpenRead(fileName); + foreach (ZipArchiveEntry entry in archive.Entries) + { + if (entry.Length == 0) + { + continue; + } + try + { + if (!Utils.IsNullOrEmpty(ignoredName) && entry.Name.Contains(ignoredName)) + { + continue; + } + entry.ExtractToFile(Path.Combine(toPath, entry.Name), true); + } + catch (IOException ex) + { + Logging.SaveLog(ex.Message, ex); + } + } + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + return false; + } + return true; + } } \ No newline at end of file diff --git a/v2rayN/v2rayN/Common/HttpClientHelper.cs b/v2rayN/v2rayN/Common/HttpClientHelper.cs index 60f9ad2b..f8450af9 100644 --- a/v2rayN/v2rayN/Common/HttpClientHelper.cs +++ b/v2rayN/v2rayN/Common/HttpClientHelper.cs @@ -4,185 +4,184 @@ using System.Net.Http.Headers; using System.Net.Mime; using System.Text; -namespace v2rayN +namespace v2rayN; + +/// +/// +public class HttpClientHelper { - /// - /// - public class HttpClientHelper + private static readonly Lazy _instance = new(() => + { + HttpClientHandler handler = new() { UseCookies = false }; + HttpClientHelper helper = new(new HttpClient(handler)); + return helper; + }); + + public static HttpClientHelper Instance => _instance.Value; + private readonly HttpClient httpClient; + + private HttpClientHelper(HttpClient httpClient) => this.httpClient = httpClient; + + public async Task TryGetAsync(string url) + { + if (string.IsNullOrEmpty(url)) + return null; + + try { - private static readonly Lazy _instance = new(() => - { - HttpClientHandler handler = new() { UseCookies = false }; - HttpClientHelper helper = new(new HttpClient(handler)); - return helper; - }); - - public static HttpClientHelper Instance => _instance.Value; - private readonly HttpClient httpClient; - - private HttpClientHelper(HttpClient httpClient) => this.httpClient = httpClient; - - public async Task TryGetAsync(string url) - { - if (string.IsNullOrEmpty(url)) - return null; - - try - { - HttpResponseMessage response = await httpClient.GetAsync(url); - return await response.Content.ReadAsStringAsync(); - } - catch - { - return null; - } - } - - public async Task GetAsync(string url) - { - if (Utils.IsNullOrEmpty(url)) return null; - return await httpClient.GetStringAsync(url); - } - - public async Task GetAsync(HttpClient client, string url, CancellationToken token = default) - { - if (Utils.IsNullOrEmpty(url)) return null; - return await client.GetStringAsync(url, token); - } - - public async Task PutAsync(string url, Dictionary headers) - { - var jsonContent = JsonUtils.Serialize(headers); - var content = new StringContent(jsonContent, Encoding.UTF8, MediaTypeNames.Application.Json); - - var result = await httpClient.PutAsync(url, content); - } - - public async Task PatchAsync(string url, Dictionary headers) - { - var myContent = JsonUtils.Serialize(headers); - var buffer = System.Text.Encoding.UTF8.GetBytes(myContent); - var byteContent = new ByteArrayContent(buffer); - byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); - - await httpClient.PatchAsync(url, byteContent); - } - - public async Task DeleteAsync(string url) - { - await httpClient.DeleteAsync(url); - } - - public static async Task DownloadFileAsync(HttpClient client, string url, string fileName, IProgress? progress, CancellationToken token = default) - { - ArgumentNullException.ThrowIfNull(url); - ArgumentNullException.ThrowIfNull(fileName); - if (File.Exists(fileName)) File.Delete(fileName); - - using var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token); - - if (!response.IsSuccessStatusCode) throw new Exception(response.StatusCode.ToString()); - - var total = response.Content.Headers.ContentLength ?? -1L; - var canReportProgress = total != -1 && progress != null; - - using var stream = await response.Content.ReadAsStreamAsync(token); - using var file = File.Create(fileName); - var totalRead = 0L; - var buffer = new byte[1024 * 1024]; - var progressPercentage = 0; - - while (true) - { - token.ThrowIfCancellationRequested(); - - var read = await stream.ReadAsync(buffer, token); - totalRead += read; - - if (read == 0) break; - file.Write(buffer, 0, read); - - if (canReportProgress) - { - var percent = (int)(100.0 * totalRead / total); - //if (progressPercentage != percent && percent % 10 == 0) - { - progressPercentage = percent; - progress?.Report(percent); - } - } - } - if (canReportProgress) - { - progress?.Report(101); - } - } - - public async Task DownloadDataAsync4Speed(HttpClient client, string url, IProgress progress, CancellationToken token = default) - { - if (Utils.IsNullOrEmpty(url)) - { - throw new ArgumentNullException(nameof(url)); - } - - var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token); - - if (!response.IsSuccessStatusCode) - { - throw new Exception(response.StatusCode.ToString()); - } - - //var total = response.Content.Headers.ContentLength.HasValue ? response.Content.Headers.ContentLength.Value : -1L; - //var canReportProgress = total != -1 && progress != null; - - using var stream = await response.Content.ReadAsStreamAsync(token); - var totalRead = 0L; - var buffer = new byte[1024 * 64]; - var isMoreToRead = true; - string progressSpeed = string.Empty; - DateTime totalDatetime = DateTime.Now; - int totalSecond = 0; - - do - { - if (token.IsCancellationRequested) - { - if (totalRead > 0) - { - return; - } - else - { - token.ThrowIfCancellationRequested(); - } - } - - var read = await stream.ReadAsync(buffer, token); - - if (read == 0) - { - isMoreToRead = false; - } - else - { - var data = new byte[read]; - buffer.ToList().CopyTo(0, data, 0, read); - - totalRead += read; - - TimeSpan ts = (DateTime.Now - totalDatetime); - if (progress != null && ts.Seconds > totalSecond) - { - totalSecond = ts.Seconds; - var speed = (totalRead * 1d / ts.TotalMilliseconds / 1000).ToString("#0.0"); - if (progressSpeed != speed) - { - progressSpeed = speed; - progress.Report(speed); - } - } - } - } while (isMoreToRead); - } + HttpResponseMessage response = await httpClient.GetAsync(url); + return await response.Content.ReadAsStringAsync(); } + catch + { + return null; + } + } + + public async Task GetAsync(string url) + { + if (Utils.IsNullOrEmpty(url)) return null; + return await httpClient.GetStringAsync(url); + } + + public async Task GetAsync(HttpClient client, string url, CancellationToken token = default) + { + if (Utils.IsNullOrEmpty(url)) return null; + return await client.GetStringAsync(url, token); + } + + public async Task PutAsync(string url, Dictionary headers) + { + var jsonContent = JsonUtils.Serialize(headers); + var content = new StringContent(jsonContent, Encoding.UTF8, MediaTypeNames.Application.Json); + + var result = await httpClient.PutAsync(url, content); + } + + public async Task PatchAsync(string url, Dictionary headers) + { + var myContent = JsonUtils.Serialize(headers); + var buffer = System.Text.Encoding.UTF8.GetBytes(myContent); + var byteContent = new ByteArrayContent(buffer); + byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + + await httpClient.PatchAsync(url, byteContent); + } + + public async Task DeleteAsync(string url) + { + await httpClient.DeleteAsync(url); + } + + public static async Task DownloadFileAsync(HttpClient client, string url, string fileName, IProgress? progress, CancellationToken token = default) + { + ArgumentNullException.ThrowIfNull(url); + ArgumentNullException.ThrowIfNull(fileName); + if (File.Exists(fileName)) File.Delete(fileName); + + using var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token); + + if (!response.IsSuccessStatusCode) throw new Exception(response.StatusCode.ToString()); + + var total = response.Content.Headers.ContentLength ?? -1L; + var canReportProgress = total != -1 && progress != null; + + using var stream = await response.Content.ReadAsStreamAsync(token); + using var file = File.Create(fileName); + var totalRead = 0L; + var buffer = new byte[1024 * 1024]; + var progressPercentage = 0; + + while (true) + { + token.ThrowIfCancellationRequested(); + + var read = await stream.ReadAsync(buffer, token); + totalRead += read; + + if (read == 0) break; + file.Write(buffer, 0, read); + + if (canReportProgress) + { + var percent = (int)(100.0 * totalRead / total); + //if (progressPercentage != percent && percent % 10 == 0) + { + progressPercentage = percent; + progress?.Report(percent); + } + } + } + if (canReportProgress) + { + progress?.Report(101); + } + } + + public async Task DownloadDataAsync4Speed(HttpClient client, string url, IProgress progress, CancellationToken token = default) + { + if (Utils.IsNullOrEmpty(url)) + { + throw new ArgumentNullException(nameof(url)); + } + + var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token); + + if (!response.IsSuccessStatusCode) + { + throw new Exception(response.StatusCode.ToString()); + } + + //var total = response.Content.Headers.ContentLength.HasValue ? response.Content.Headers.ContentLength.Value : -1L; + //var canReportProgress = total != -1 && progress != null; + + using var stream = await response.Content.ReadAsStreamAsync(token); + var totalRead = 0L; + var buffer = new byte[1024 * 64]; + var isMoreToRead = true; + string progressSpeed = string.Empty; + DateTime totalDatetime = DateTime.Now; + int totalSecond = 0; + + do + { + if (token.IsCancellationRequested) + { + if (totalRead > 0) + { + return; + } + else + { + token.ThrowIfCancellationRequested(); + } + } + + var read = await stream.ReadAsync(buffer, token); + + if (read == 0) + { + isMoreToRead = false; + } + else + { + var data = new byte[read]; + buffer.ToList().CopyTo(0, data, 0, read); + + totalRead += read; + + TimeSpan ts = (DateTime.Now - totalDatetime); + if (progress != null && ts.Seconds > totalSecond) + { + totalSecond = ts.Seconds; + var speed = (totalRead * 1d / ts.TotalMilliseconds / 1000).ToString("#0.0"); + if (progressSpeed != speed) + { + progressSpeed = speed; + progress.Report(speed); + } + } + } + } while (isMoreToRead); + } } \ No newline at end of file diff --git a/v2rayN/v2rayN/Common/Job.cs b/v2rayN/v2rayN/Common/Job.cs index c25a2221..845ed6f2 100644 --- a/v2rayN/v2rayN/Common/Job.cs +++ b/v2rayN/v2rayN/Common/Job.cs @@ -1,176 +1,174 @@ using System.Diagnostics; using System.Runtime.InteropServices; -namespace v2rayN +namespace v2rayN; +/* + * See: + * http://stackoverflow.com/questions/6266820/working-example-of-createjobobject-setinformationjobobject-pinvoke-in-net + */ + +public class Job : IDisposable { - /* - * See: - * http://stackoverflow.com/questions/6266820/working-example-of-createjobobject-setinformationjobobject-pinvoke-in-net - */ + private IntPtr handle = IntPtr.Zero; - public class Job : IDisposable + public Job() + { + handle = CreateJobObject(IntPtr.Zero, null); + IntPtr extendedInfoPtr = IntPtr.Zero; + JOBOBJECT_BASIC_LIMIT_INFORMATION info = new() { - private IntPtr handle = IntPtr.Zero; + LimitFlags = 0x2000 + }; - public Job() - { - handle = CreateJobObject(IntPtr.Zero, null); - IntPtr extendedInfoPtr = IntPtr.Zero; - JOBOBJECT_BASIC_LIMIT_INFORMATION info = new() - { - LimitFlags = 0x2000 - }; + JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new() + { + BasicLimitInformation = info + }; - JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new() - { - BasicLimitInformation = info - }; + try + { + int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); + extendedInfoPtr = Marshal.AllocHGlobal(length); + Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); - try - { - int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); - extendedInfoPtr = Marshal.AllocHGlobal(length); - Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); + if (!SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, + (uint)length)) + throw new Exception(string.Format("Unable to set information. Error: {0}", + Marshal.GetLastWin32Error())); + } + finally + { + if (extendedInfoPtr != IntPtr.Zero) + { + Marshal.FreeHGlobal(extendedInfoPtr); + } + } + } - if (!SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, - (uint)length)) - throw new Exception(string.Format("Unable to set information. Error: {0}", - Marshal.GetLastWin32Error())); - } - finally - { - if (extendedInfoPtr != IntPtr.Zero) - { - Marshal.FreeHGlobal(extendedInfoPtr); - } - } - } + public bool AddProcess(IntPtr processHandle) + { + bool succ = AssignProcessToJobObject(handle, processHandle); - public bool AddProcess(IntPtr processHandle) - { - bool succ = AssignProcessToJobObject(handle, processHandle); - - if (!succ) - { - Logging.SaveLog("Failed to call AssignProcessToJobObject! GetLastError=" + Marshal.GetLastWin32Error()); - } - - return succ; - } - - public bool AddProcess(int processId) - { - return AddProcess(Process.GetProcessById(processId).Handle); - } - - #region IDisposable - - private bool disposed; - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (disposed) return; - disposed = true; - - if (disposing) - { - // no managed objects to free - } - - if (handle != IntPtr.Zero) - { - CloseHandle(handle); - handle = IntPtr.Zero; - } - } - - ~Job() - { - Dispose(false); - } - - #endregion IDisposable - - #region Interop - - [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] - private static extern IntPtr CreateJobObject(IntPtr a, string? lpName); - - [DllImport("kernel32.dll", SetLastError = true)] - private static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, UInt32 cbJobObjectInfoLength); - - [DllImport("kernel32.dll", SetLastError = true)] - private static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process); - - [DllImport("kernel32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool CloseHandle(IntPtr hObject); - - #endregion Interop + if (!succ) + { + Logging.SaveLog("Failed to call AssignProcessToJobObject! GetLastError=" + Marshal.GetLastWin32Error()); } - #region Helper classes + return succ; + } - [StructLayout(LayoutKind.Sequential)] - internal struct IO_COUNTERS + public bool AddProcess(int processId) + { + return AddProcess(Process.GetProcessById(processId).Handle); + } + + #region IDisposable + + private bool disposed; + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposed) return; + disposed = true; + + if (disposing) { - public UInt64 ReadOperationCount; - public UInt64 WriteOperationCount; - public UInt64 OtherOperationCount; - public UInt64 ReadTransferCount; - public UInt64 WriteTransferCount; - public UInt64 OtherTransferCount; + // no managed objects to free } - [StructLayout(LayoutKind.Sequential)] - internal struct JOBOBJECT_BASIC_LIMIT_INFORMATION + if (handle != IntPtr.Zero) { - public Int64 PerProcessUserTimeLimit; - public Int64 PerJobUserTimeLimit; - public UInt32 LimitFlags; - public UIntPtr MinimumWorkingSetSize; - public UIntPtr MaximumWorkingSetSize; - public UInt32 ActiveProcessLimit; - public UIntPtr Affinity; - public UInt32 PriorityClass; - public UInt32 SchedulingClass; + CloseHandle(handle); + handle = IntPtr.Zero; } + } - [StructLayout(LayoutKind.Sequential)] - public struct SECURITY_ATTRIBUTES - { - public UInt32 nLength; - public IntPtr lpSecurityDescriptor; - public Int32 bInheritHandle; - } + ~Job() + { + Dispose(false); + } - [StructLayout(LayoutKind.Sequential)] - internal struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION - { - public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation; - public IO_COUNTERS IoInfo; - public UIntPtr ProcessMemoryLimit; - public UIntPtr JobMemoryLimit; - public UIntPtr PeakProcessMemoryUsed; - public UIntPtr PeakJobMemoryUsed; - } + #endregion IDisposable - public enum JobObjectInfoType - { - AssociateCompletionPortInformation = 7, - BasicLimitInformation = 2, - BasicUIRestrictions = 4, - EndOfJobTimeInformation = 6, - ExtendedLimitInformation = 9, - SecurityLimitInformation = 5, - GroupInformation = 11 - } + #region Interop - #endregion Helper classes -} \ No newline at end of file + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + private static extern IntPtr CreateJobObject(IntPtr a, string? lpName); + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, UInt32 cbJobObjectInfoLength); + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process); + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool CloseHandle(IntPtr hObject); + + #endregion Interop +} + +#region Helper classes + +[StructLayout(LayoutKind.Sequential)] +internal struct IO_COUNTERS +{ + public UInt64 ReadOperationCount; + public UInt64 WriteOperationCount; + public UInt64 OtherOperationCount; + public UInt64 ReadTransferCount; + public UInt64 WriteTransferCount; + public UInt64 OtherTransferCount; +} + +[StructLayout(LayoutKind.Sequential)] +internal struct JOBOBJECT_BASIC_LIMIT_INFORMATION +{ + public Int64 PerProcessUserTimeLimit; + public Int64 PerJobUserTimeLimit; + public UInt32 LimitFlags; + public UIntPtr MinimumWorkingSetSize; + public UIntPtr MaximumWorkingSetSize; + public UInt32 ActiveProcessLimit; + public UIntPtr Affinity; + public UInt32 PriorityClass; + public UInt32 SchedulingClass; +} + +[StructLayout(LayoutKind.Sequential)] +public struct SECURITY_ATTRIBUTES +{ + public UInt32 nLength; + public IntPtr lpSecurityDescriptor; + public Int32 bInheritHandle; +} + +[StructLayout(LayoutKind.Sequential)] +internal struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION +{ + public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation; + public IO_COUNTERS IoInfo; + public UIntPtr ProcessMemoryLimit; + public UIntPtr JobMemoryLimit; + public UIntPtr PeakProcessMemoryUsed; + public UIntPtr PeakJobMemoryUsed; +} + +public enum JobObjectInfoType +{ + AssociateCompletionPortInformation = 7, + BasicLimitInformation = 2, + BasicUIRestrictions = 4, + EndOfJobTimeInformation = 6, + ExtendedLimitInformation = 9, + SecurityLimitInformation = 5, + GroupInformation = 11 +} + +#endregion Helper classes \ No newline at end of file diff --git a/v2rayN/v2rayN/Common/JsonUtils.cs b/v2rayN/v2rayN/Common/JsonUtils.cs index ab81d41e..f50e023f 100644 --- a/v2rayN/v2rayN/Common/JsonUtils.cs +++ b/v2rayN/v2rayN/Common/JsonUtils.cs @@ -3,132 +3,131 @@ using System.Text.Json; using System.Text.Json.Nodes; using System.Text.Json.Serialization; -namespace v2rayN +namespace v2rayN; + +internal class JsonUtils { - internal class JsonUtils + /// + /// DeepCopy + /// + /// + /// + /// + public static T DeepCopy(T obj) + { + return Deserialize(Serialize(obj, false))!; + } + + /// + /// Deserialize to object + /// + /// + /// + /// + public static T? Deserialize(string? strJson) + { + try { - /// - /// DeepCopy - /// - /// - /// - /// - public static T DeepCopy(T obj) - { - return Deserialize(Serialize(obj, false))!; - } - - /// - /// Deserialize to object - /// - /// - /// - /// - public static T? Deserialize(string? strJson) - { - try - { - if (string.IsNullOrWhiteSpace(strJson)) - { - return default; - } - return JsonSerializer.Deserialize(strJson); - } - catch - { - return default; - } - } - - /// - /// parse - /// - /// - /// - public static JsonNode? ParseJson(string strJson) - { - try - { - if (string.IsNullOrWhiteSpace(strJson)) - { - return null; - } - return JsonNode.Parse(strJson); - } - catch - { - //SaveLog(ex.Message, ex); - return null; - } - } - - /// - /// Serialize Object to Json string - /// - /// - /// - /// - public static string Serialize(object? obj, bool indented = true) - { - string result = string.Empty; - try - { - if (obj == null) - { - return result; - } - var options = new JsonSerializerOptions - { - WriteIndented = indented ? true : false, - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull - }; - result = JsonSerializer.Serialize(obj, options); - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - } - return result; - } - - /// - /// SerializeToNode - /// - /// - /// - public static JsonNode? SerializeToNode(object? obj) => JsonSerializer.SerializeToNode(obj); - - /// - /// Save as json file - /// - /// - /// - /// - /// - public static int ToFile(object? obj, string? filePath, bool nullValue = true) - { - if (filePath is null) - { - return -1; - } - try - { - using FileStream file = File.Create(filePath); - - var options = new JsonSerializerOptions - { - WriteIndented = true, - DefaultIgnoreCondition = nullValue ? JsonIgnoreCondition.Never : JsonIgnoreCondition.WhenWritingNull - }; - - JsonSerializer.Serialize(file, obj, options); - return 0; - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - return -1; - } - } + if (string.IsNullOrWhiteSpace(strJson)) + { + return default; + } + return JsonSerializer.Deserialize(strJson); } + catch + { + return default; + } + } + + /// + /// parse + /// + /// + /// + public static JsonNode? ParseJson(string strJson) + { + try + { + if (string.IsNullOrWhiteSpace(strJson)) + { + return null; + } + return JsonNode.Parse(strJson); + } + catch + { + //SaveLog(ex.Message, ex); + return null; + } + } + + /// + /// Serialize Object to Json string + /// + /// + /// + /// + public static string Serialize(object? obj, bool indented = true) + { + string result = string.Empty; + try + { + if (obj == null) + { + return result; + } + var options = new JsonSerializerOptions + { + WriteIndented = indented ? true : false, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull + }; + result = JsonSerializer.Serialize(obj, options); + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + } + return result; + } + + /// + /// SerializeToNode + /// + /// + /// + public static JsonNode? SerializeToNode(object? obj) => JsonSerializer.SerializeToNode(obj); + + /// + /// Save as json file + /// + /// + /// + /// + /// + public static int ToFile(object? obj, string? filePath, bool nullValue = true) + { + if (filePath is null) + { + return -1; + } + try + { + using FileStream file = File.Create(filePath); + + var options = new JsonSerializerOptions + { + WriteIndented = true, + DefaultIgnoreCondition = nullValue ? JsonIgnoreCondition.Never : JsonIgnoreCondition.WhenWritingNull + }; + + JsonSerializer.Serialize(file, obj, options); + return 0; + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + return -1; + } + } } \ No newline at end of file diff --git a/v2rayN/v2rayN/Common/Logging.cs b/v2rayN/v2rayN/Common/Logging.cs index ba5b97e7..75a29481 100644 --- a/v2rayN/v2rayN/Common/Logging.cs +++ b/v2rayN/v2rayN/Common/Logging.cs @@ -3,76 +3,75 @@ using NLog.Config; using NLog.Targets; using System.IO; -namespace v2rayN +namespace v2rayN; + +public class Logging { - public class Logging + public static void Setup() + { + LoggingConfiguration config = new(); + FileTarget fileTarget = new(); + config.AddTarget("file", fileTarget); + fileTarget.Layout = "${longdate}-${level:uppercase=true} ${message}"; + fileTarget.FileName = Utils.GetLogPath("${shortdate}.txt"); + config.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, fileTarget)); + LogManager.Configuration = config; + } + + public static void LoggingEnabled(bool enable) + { + if (!enable) { - public static void Setup() - { - LoggingConfiguration config = new(); - FileTarget fileTarget = new(); - config.AddTarget("file", fileTarget); - fileTarget.Layout = "${longdate}-${level:uppercase=true} ${message}"; - fileTarget.FileName = Utils.GetLogPath("${shortdate}.txt"); - config.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, fileTarget)); - LogManager.Configuration = config; - } - - public static void LoggingEnabled(bool enable) - { - if (!enable) - { - LogManager.SuspendLogging(); - } - } - - public static void ClearLogs() - { - Task.Run(() => - { - try - { - var now = DateTime.Now.AddMonths(-1); - var dir = Utils.GetLogPath(); - var files = Directory.GetFiles(dir, "*.txt"); - foreach (var filePath in files) - { - var file = new FileInfo(filePath); - if (file.CreationTime < now) - { - try - { - file.Delete(); - } - catch { } - } - } - } - catch { } - }); - } - - public static void SaveLog(string strContent) - { - if (LogManager.IsLoggingEnabled()) - { - var logger = LogManager.GetLogger("Log1"); - logger.Info(strContent); - } - } - - public static void SaveLog(string strTitle, Exception ex) - { - if (LogManager.IsLoggingEnabled()) - { - var logger = LogManager.GetLogger("Log2"); - logger.Debug($"{strTitle},{ex.Message}"); - logger.Debug(ex.StackTrace); - if (ex?.InnerException != null) - { - logger.Error(ex.InnerException); - } - } - } + LogManager.SuspendLogging(); } + } + + public static void ClearLogs() + { + Task.Run(() => + { + try + { + var now = DateTime.Now.AddMonths(-1); + var dir = Utils.GetLogPath(); + var files = Directory.GetFiles(dir, "*.txt"); + foreach (var filePath in files) + { + var file = new FileInfo(filePath); + if (file.CreationTime < now) + { + try + { + file.Delete(); + } + catch { } + } + } + } + catch { } + }); + } + + public static void SaveLog(string strContent) + { + if (LogManager.IsLoggingEnabled()) + { + var logger = LogManager.GetLogger("Log1"); + logger.Info(strContent); + } + } + + public static void SaveLog(string strTitle, Exception ex) + { + if (LogManager.IsLoggingEnabled()) + { + var logger = LogManager.GetLogger("Log2"); + logger.Debug($"{strTitle},{ex.Message}"); + logger.Debug(ex.StackTrace); + if (ex?.InnerException != null) + { + logger.Error(ex.InnerException); + } + } + } } \ No newline at end of file diff --git a/v2rayN/v2rayN/Common/ProxySetting.cs b/v2rayN/v2rayN/Common/ProxySetting.cs index cab07633..7c05079e 100644 --- a/v2rayN/v2rayN/Common/ProxySetting.cs +++ b/v2rayN/v2rayN/Common/ProxySetting.cs @@ -1,360 +1,359 @@ using System.Runtime.InteropServices; using static v2rayN.Common.ProxySetting.InternetConnectionOption; -namespace v2rayN.Common +namespace v2rayN.Common; + +internal class ProxySetting { - internal class ProxySetting + private const string _regPath = @"Software\Microsoft\Windows\CurrentVersion\Internet Settings"; + + private static bool SetProxyFallback(string? strProxy, string? exceptions, int type) + { + if (type == 1) { - private const string _regPath = @"Software\Microsoft\Windows\CurrentVersion\Internet Settings"; - - private static bool SetProxyFallback(string? strProxy, string? exceptions, int type) - { - if (type == 1) - { - Utils.RegWriteValue(_regPath, "ProxyEnable", 0); - Utils.RegWriteValue(_regPath, "ProxyServer", string.Empty); - Utils.RegWriteValue(_regPath, "ProxyOverride", string.Empty); - Utils.RegWriteValue(_regPath, "AutoConfigURL", string.Empty); - } - if (type == 2) - { - Utils.RegWriteValue(_regPath, "ProxyEnable", 1); - Utils.RegWriteValue(_regPath, "ProxyServer", strProxy ?? string.Empty); - Utils.RegWriteValue(_regPath, "ProxyOverride", exceptions ?? string.Empty); - Utils.RegWriteValue(_regPath, "AutoConfigURL", string.Empty); - } - else if (type == 4) - { - Utils.RegWriteValue(_regPath, "ProxyEnable", 0); - Utils.RegWriteValue(_regPath, "ProxyServer", string.Empty); - Utils.RegWriteValue(_regPath, "ProxyOverride", string.Empty); - Utils.RegWriteValue(_regPath, "AutoConfigURL", strProxy ?? string.Empty); - } - return true; - } - - /// - // set to use no proxy - /// - /// Error message with win32 error code - public static bool UnsetProxy() - { - return SetProxy(null, null, 1); - } - - /// - /// Set system proxy settings - /// - /// proxy address - /// exception addresses that do not use proxy - /// type of proxy defined in PerConnFlags - /// PROXY_TYPE_DIRECT = 0x00000001, // direct connection (no proxy) - /// PROXY_TYPE_PROXY = 0x00000002, // via named proxy - /// PROXY_TYPE_AUTO_PROXY_URL = 0x00000004, // autoproxy script URL - /// PROXY_TYPE_AUTO_DETECT = 0x00000008 // use autoproxy detection - /// - /// Error message with win32 error code - /// true: one of connection is successfully updated proxy settings - public static bool SetProxy(string? strProxy, string? exceptions, int type) - { - try - { - // set proxy for LAN - bool result = SetConnectionProxy(null, strProxy, exceptions, type); - // set proxy for dial up connections - var connections = EnumerateRasEntries(); - foreach (var connection in connections) - { - result |= SetConnectionProxy(connection, strProxy, exceptions, type); - } - return result; - } - catch (Exception ex) - { - SetProxyFallback(strProxy, exceptions, type); - Logging.SaveLog(ex.Message, ex); - return false; - } - } - - private static bool SetConnectionProxy(string? connectionName, string? strProxy, string? exceptions, int type) - { - InternetPerConnOptionList list = new(); - - int optionCount = 1; - if (type == 1) // No proxy - { - optionCount = 1; - } - else if (type is 2 or 4) // named proxy or autoproxy script URL - { - optionCount = Utils.IsNullOrEmpty(exceptions) ? 2 : 3; - } - - int m_Int = (int)PerConnFlags.PROXY_TYPE_DIRECT; - PerConnOption m_Option = PerConnOption.INTERNET_PER_CONN_FLAGS; - if (type == 2) // named proxy - { - m_Int = (int)(PerConnFlags.PROXY_TYPE_DIRECT | PerConnFlags.PROXY_TYPE_PROXY); - m_Option = PerConnOption.INTERNET_PER_CONN_PROXY_SERVER; - } - else if (type == 4) // autoproxy script url - { - m_Int = (int)(PerConnFlags.PROXY_TYPE_DIRECT | PerConnFlags.PROXY_TYPE_AUTO_PROXY_URL); - m_Option = PerConnOption.INTERNET_PER_CONN_AUTOCONFIG_URL; - } - - //int optionCount = Utile.IsNullOrEmpty(strProxy) ? 1 : (Utile.IsNullOrEmpty(exceptions) ? 2 : 3); - InternetConnectionOption[] options = new InternetConnectionOption[optionCount]; - // USE a proxy server ... - options[0].m_Option = PerConnOption.INTERNET_PER_CONN_FLAGS; - //options[0].m_Value.m_Int = (int)((optionCount < 2) ? PerConnFlags.PROXY_TYPE_DIRECT : (PerConnFlags.PROXY_TYPE_DIRECT | PerConnFlags.PROXY_TYPE_PROXY)); - options[0].m_Value.m_Int = m_Int; - // use THIS proxy server - if (optionCount > 1) - { - options[1].m_Option = m_Option; - options[1].m_Value.m_StringPtr = Marshal.StringToHGlobalAuto(strProxy); // !! remember to deallocate memory 1 - // except for these addresses ... - if (optionCount > 2) - { - options[2].m_Option = PerConnOption.INTERNET_PER_CONN_PROXY_BYPASS; - options[2].m_Value.m_StringPtr = Marshal.StringToHGlobalAuto(exceptions); // !! remember to deallocate memory 2 - } - } - - // default stuff - list.dwSize = Marshal.SizeOf(list); - if (connectionName != null) - { - list.szConnection = Marshal.StringToHGlobalAuto(connectionName); // !! remember to deallocate memory 3 - } - else - { - list.szConnection = nint.Zero; - } - list.dwOptionCount = options.Length; - list.dwOptionError = 0; - - int optSize = Marshal.SizeOf(typeof(InternetConnectionOption)); - // make a pointer out of all that ... - nint optionsPtr = Marshal.AllocCoTaskMem(optSize * options.Length); // !! remember to deallocate memory 4 - // copy the array over into that spot in memory ... - for (int i = 0; i < options.Length; ++i) - { - if (Environment.Is64BitOperatingSystem) - { - nint opt = new(optionsPtr.ToInt64() + i * optSize); - Marshal.StructureToPtr(options[i], opt, false); - } - else - { - nint opt = new(optionsPtr.ToInt32() + i * optSize); - Marshal.StructureToPtr(options[i], opt, false); - } - } - - list.options = optionsPtr; - - // and then make a pointer out of the whole list - nint ipcoListPtr = Marshal.AllocCoTaskMem(list.dwSize); // !! remember to deallocate memory 5 - Marshal.StructureToPtr(list, ipcoListPtr, false); - - // and finally, call the API method! - bool isSuccess = NativeMethods.InternetSetOption(nint.Zero, - InternetOption.INTERNET_OPTION_PER_CONNECTION_OPTION, - ipcoListPtr, list.dwSize); - int returnvalue = 0; // ERROR_SUCCESS - if (!isSuccess) - { // get the error codes, they might be helpful - returnvalue = Marshal.GetLastPInvokeError(); - } - else - { - // Notify the system that the registry settings have been changed and cause them to be refreshed - NativeMethods.InternetSetOption(nint.Zero, InternetOption.INTERNET_OPTION_SETTINGS_CHANGED, nint.Zero, 0); - NativeMethods.InternetSetOption(nint.Zero, InternetOption.INTERNET_OPTION_REFRESH, nint.Zero, 0); - } - - // FREE the data ASAP - if (list.szConnection != nint.Zero) Marshal.FreeHGlobal(list.szConnection); // release mem 3 - if (optionCount > 1) - { - Marshal.FreeHGlobal(options[1].m_Value.m_StringPtr); // release mem 1 - if (optionCount > 2) - { - Marshal.FreeHGlobal(options[2].m_Value.m_StringPtr); // release mem 2 - } - } - Marshal.FreeCoTaskMem(optionsPtr); // release mem 4 - Marshal.FreeCoTaskMem(ipcoListPtr); // release mem 5 - if (returnvalue != 0) - { - // throw the error codes, they might be helpful - throw new ApplicationException($"Set Internet Proxy failed with error code: {Marshal.GetLastWin32Error()}"); - } - - return true; - } - - /// - /// Retrieve list of connections including LAN and WAN to support PPPoE connection - /// - /// A list of RAS connection names. May be empty list if no dial up connection. - /// Error message with win32 error code - private static IEnumerable EnumerateRasEntries() - { - int entries = 0; - // attempt to query with 1 entry buffer - RASENTRYNAME[] rasEntryNames = new RASENTRYNAME[1]; - int bufferSize = Marshal.SizeOf(typeof(RASENTRYNAME)); - rasEntryNames[0].dwSize = Marshal.SizeOf(typeof(RASENTRYNAME)); - - uint result = NativeMethods.RasEnumEntries(null, null, rasEntryNames, ref bufferSize, ref entries); - // increase buffer if the buffer is not large enough - if (result == (uint)ErrorCode.ERROR_BUFFER_TOO_SMALL) - { - rasEntryNames = new RASENTRYNAME[bufferSize / Marshal.SizeOf(typeof(RASENTRYNAME))]; - for (int i = 0; i < rasEntryNames.Length; i++) - { - rasEntryNames[i].dwSize = Marshal.SizeOf(typeof(RASENTRYNAME)); - } - - result = NativeMethods.RasEnumEntries(null, null, rasEntryNames, ref bufferSize, ref entries); - } - if (result == 0) - { - var entryNames = new List(); - for (int i = 0; i < entries; i++) - { - entryNames.Add(rasEntryNames[i].szEntryName); - } - - return entryNames; - } - throw new ApplicationException($"RasEnumEntries failed with error code: {result}"); - } - - #region WinInet structures - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] - public struct InternetPerConnOptionList - { - public int dwSize; // size of the INTERNET_PER_CONN_OPTION_LIST struct - public nint szConnection; // connection name to set/query options - public int dwOptionCount; // number of options to set/query - public int dwOptionError; // on error, which option failed - - //[MarshalAs(UnmanagedType.)] - public nint options; - }; - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] - public struct InternetConnectionOption - { - private static readonly int Size; - public PerConnOption m_Option; - public InternetConnectionOptionValue m_Value; - - static InternetConnectionOption() - { - Size = Marshal.SizeOf(typeof(InternetConnectionOption)); - } - - // Nested Types - [StructLayout(LayoutKind.Explicit)] - public struct InternetConnectionOptionValue - { - // Fields - [FieldOffset(0)] - public System.Runtime.InteropServices.ComTypes.FILETIME m_FileTime; - - [FieldOffset(0)] - public int m_Int; - - [FieldOffset(0)] - public nint m_StringPtr; - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] - public struct RASENTRYNAME - { - public int dwSize; - - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = RAS_MaxEntryName + 1)] - public string szEntryName; - - public int dwFlags; - - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)] - public string szPhonebookPath; - } - - // Constants - public const int RAS_MaxEntryName = 256; - - public const int MAX_PATH = 260; // Standard MAX_PATH value in Windows - } - - #endregion WinInet structures - - #region WinInet enums - - // - // options manifests for Internet{Query|Set}Option - // - public enum InternetOption : uint - { - INTERNET_OPTION_PER_CONNECTION_OPTION = 75, - INTERNET_OPTION_REFRESH = 37, - INTERNET_OPTION_SETTINGS_CHANGED = 39 - } - - // - // Options used in INTERNET_PER_CONN_OPTON struct - // - public enum PerConnOption - { - INTERNET_PER_CONN_FLAGS = 1, // Sets or retrieves the connection type. The Value member will contain one or more of the values from PerConnFlags - INTERNET_PER_CONN_PROXY_SERVER = 2, // Sets or retrieves a string containing the proxy servers. - INTERNET_PER_CONN_PROXY_BYPASS = 3, // Sets or retrieves a string containing the URLs that do not use the proxy server. - INTERNET_PER_CONN_AUTOCONFIG_URL = 4//, // Sets or retrieves a string containing the URL to the automatic configuration script. - } - - // - // PER_CONN_FLAGS - // - [Flags] - public enum PerConnFlags - { - PROXY_TYPE_DIRECT = 0x00000001, // direct to net - PROXY_TYPE_PROXY = 0x00000002, // via named proxy - PROXY_TYPE_AUTO_PROXY_URL = 0x00000004, // autoproxy URL - PROXY_TYPE_AUTO_DETECT = 0x00000008 // use autoproxy detection - } - - public enum ErrorCode : uint - { - ERROR_BUFFER_TOO_SMALL = 603, - ERROR_INVALID_SIZE = 632 - } - - #endregion WinInet enums - - internal static class NativeMethods - { - [DllImport("WinInet.dll", SetLastError = true, CharSet = CharSet.Auto)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool InternetSetOption(nint hInternet, InternetOption dwOption, nint lpBuffer, int dwBufferLength); - - [DllImport("Rasapi32.dll", CharSet = CharSet.Auto)] - public static extern uint RasEnumEntries( - string? reserved, // Reserved, must be null - string? lpszPhonebook, // Pointer to full path and filename of phone-book file. If this parameter is NULL, the entries are enumerated from all the remote access phone-book files - [In, Out] RASENTRYNAME[]? lprasentryname, // Buffer to receive RAS entry names - ref int lpcb, // Size of the buffer - ref int lpcEntries // Number of entries written to the buffer - ); - } + Utils.RegWriteValue(_regPath, "ProxyEnable", 0); + Utils.RegWriteValue(_regPath, "ProxyServer", string.Empty); + Utils.RegWriteValue(_regPath, "ProxyOverride", string.Empty); + Utils.RegWriteValue(_regPath, "AutoConfigURL", string.Empty); } + if (type == 2) + { + Utils.RegWriteValue(_regPath, "ProxyEnable", 1); + Utils.RegWriteValue(_regPath, "ProxyServer", strProxy ?? string.Empty); + Utils.RegWriteValue(_regPath, "ProxyOverride", exceptions ?? string.Empty); + Utils.RegWriteValue(_regPath, "AutoConfigURL", string.Empty); + } + else if (type == 4) + { + Utils.RegWriteValue(_regPath, "ProxyEnable", 0); + Utils.RegWriteValue(_regPath, "ProxyServer", string.Empty); + Utils.RegWriteValue(_regPath, "ProxyOverride", string.Empty); + Utils.RegWriteValue(_regPath, "AutoConfigURL", strProxy ?? string.Empty); + } + return true; + } + + /// + // set to use no proxy + /// + /// Error message with win32 error code + public static bool UnsetProxy() + { + return SetProxy(null, null, 1); + } + + /// + /// Set system proxy settings + /// + /// proxy address + /// exception addresses that do not use proxy + /// type of proxy defined in PerConnFlags + /// PROXY_TYPE_DIRECT = 0x00000001, // direct connection (no proxy) + /// PROXY_TYPE_PROXY = 0x00000002, // via named proxy + /// PROXY_TYPE_AUTO_PROXY_URL = 0x00000004, // autoproxy script URL + /// PROXY_TYPE_AUTO_DETECT = 0x00000008 // use autoproxy detection + /// + /// Error message with win32 error code + /// true: one of connection is successfully updated proxy settings + public static bool SetProxy(string? strProxy, string? exceptions, int type) + { + try + { + // set proxy for LAN + bool result = SetConnectionProxy(null, strProxy, exceptions, type); + // set proxy for dial up connections + var connections = EnumerateRasEntries(); + foreach (var connection in connections) + { + result |= SetConnectionProxy(connection, strProxy, exceptions, type); + } + return result; + } + catch (Exception ex) + { + SetProxyFallback(strProxy, exceptions, type); + Logging.SaveLog(ex.Message, ex); + return false; + } + } + + private static bool SetConnectionProxy(string? connectionName, string? strProxy, string? exceptions, int type) + { + InternetPerConnOptionList list = new(); + + int optionCount = 1; + if (type == 1) // No proxy + { + optionCount = 1; + } + else if (type is 2 or 4) // named proxy or autoproxy script URL + { + optionCount = Utils.IsNullOrEmpty(exceptions) ? 2 : 3; + } + + int m_Int = (int)PerConnFlags.PROXY_TYPE_DIRECT; + PerConnOption m_Option = PerConnOption.INTERNET_PER_CONN_FLAGS; + if (type == 2) // named proxy + { + m_Int = (int)(PerConnFlags.PROXY_TYPE_DIRECT | PerConnFlags.PROXY_TYPE_PROXY); + m_Option = PerConnOption.INTERNET_PER_CONN_PROXY_SERVER; + } + else if (type == 4) // autoproxy script url + { + m_Int = (int)(PerConnFlags.PROXY_TYPE_DIRECT | PerConnFlags.PROXY_TYPE_AUTO_PROXY_URL); + m_Option = PerConnOption.INTERNET_PER_CONN_AUTOCONFIG_URL; + } + + //int optionCount = Utile.IsNullOrEmpty(strProxy) ? 1 : (Utile.IsNullOrEmpty(exceptions) ? 2 : 3); + InternetConnectionOption[] options = new InternetConnectionOption[optionCount]; + // USE a proxy server ... + options[0].m_Option = PerConnOption.INTERNET_PER_CONN_FLAGS; + //options[0].m_Value.m_Int = (int)((optionCount < 2) ? PerConnFlags.PROXY_TYPE_DIRECT : (PerConnFlags.PROXY_TYPE_DIRECT | PerConnFlags.PROXY_TYPE_PROXY)); + options[0].m_Value.m_Int = m_Int; + // use THIS proxy server + if (optionCount > 1) + { + options[1].m_Option = m_Option; + options[1].m_Value.m_StringPtr = Marshal.StringToHGlobalAuto(strProxy); // !! remember to deallocate memory 1 + // except for these addresses ... + if (optionCount > 2) + { + options[2].m_Option = PerConnOption.INTERNET_PER_CONN_PROXY_BYPASS; + options[2].m_Value.m_StringPtr = Marshal.StringToHGlobalAuto(exceptions); // !! remember to deallocate memory 2 + } + } + + // default stuff + list.dwSize = Marshal.SizeOf(list); + if (connectionName != null) + { + list.szConnection = Marshal.StringToHGlobalAuto(connectionName); // !! remember to deallocate memory 3 + } + else + { + list.szConnection = nint.Zero; + } + list.dwOptionCount = options.Length; + list.dwOptionError = 0; + + int optSize = Marshal.SizeOf(typeof(InternetConnectionOption)); + // make a pointer out of all that ... + nint optionsPtr = Marshal.AllocCoTaskMem(optSize * options.Length); // !! remember to deallocate memory 4 + // copy the array over into that spot in memory ... + for (int i = 0; i < options.Length; ++i) + { + if (Environment.Is64BitOperatingSystem) + { + nint opt = new(optionsPtr.ToInt64() + i * optSize); + Marshal.StructureToPtr(options[i], opt, false); + } + else + { + nint opt = new(optionsPtr.ToInt32() + i * optSize); + Marshal.StructureToPtr(options[i], opt, false); + } + } + + list.options = optionsPtr; + + // and then make a pointer out of the whole list + nint ipcoListPtr = Marshal.AllocCoTaskMem(list.dwSize); // !! remember to deallocate memory 5 + Marshal.StructureToPtr(list, ipcoListPtr, false); + + // and finally, call the API method! + bool isSuccess = NativeMethods.InternetSetOption(nint.Zero, + InternetOption.INTERNET_OPTION_PER_CONNECTION_OPTION, + ipcoListPtr, list.dwSize); + int returnvalue = 0; // ERROR_SUCCESS + if (!isSuccess) + { // get the error codes, they might be helpful + returnvalue = Marshal.GetLastPInvokeError(); + } + else + { + // Notify the system that the registry settings have been changed and cause them to be refreshed + NativeMethods.InternetSetOption(nint.Zero, InternetOption.INTERNET_OPTION_SETTINGS_CHANGED, nint.Zero, 0); + NativeMethods.InternetSetOption(nint.Zero, InternetOption.INTERNET_OPTION_REFRESH, nint.Zero, 0); + } + + // FREE the data ASAP + if (list.szConnection != nint.Zero) Marshal.FreeHGlobal(list.szConnection); // release mem 3 + if (optionCount > 1) + { + Marshal.FreeHGlobal(options[1].m_Value.m_StringPtr); // release mem 1 + if (optionCount > 2) + { + Marshal.FreeHGlobal(options[2].m_Value.m_StringPtr); // release mem 2 + } + } + Marshal.FreeCoTaskMem(optionsPtr); // release mem 4 + Marshal.FreeCoTaskMem(ipcoListPtr); // release mem 5 + if (returnvalue != 0) + { + // throw the error codes, they might be helpful + throw new ApplicationException($"Set Internet Proxy failed with error code: {Marshal.GetLastWin32Error()}"); + } + + return true; + } + + /// + /// Retrieve list of connections including LAN and WAN to support PPPoE connection + /// + /// A list of RAS connection names. May be empty list if no dial up connection. + /// Error message with win32 error code + private static IEnumerable EnumerateRasEntries() + { + int entries = 0; + // attempt to query with 1 entry buffer + RASENTRYNAME[] rasEntryNames = new RASENTRYNAME[1]; + int bufferSize = Marshal.SizeOf(typeof(RASENTRYNAME)); + rasEntryNames[0].dwSize = Marshal.SizeOf(typeof(RASENTRYNAME)); + + uint result = NativeMethods.RasEnumEntries(null, null, rasEntryNames, ref bufferSize, ref entries); + // increase buffer if the buffer is not large enough + if (result == (uint)ErrorCode.ERROR_BUFFER_TOO_SMALL) + { + rasEntryNames = new RASENTRYNAME[bufferSize / Marshal.SizeOf(typeof(RASENTRYNAME))]; + for (int i = 0; i < rasEntryNames.Length; i++) + { + rasEntryNames[i].dwSize = Marshal.SizeOf(typeof(RASENTRYNAME)); + } + + result = NativeMethods.RasEnumEntries(null, null, rasEntryNames, ref bufferSize, ref entries); + } + if (result == 0) + { + var entryNames = new List(); + for (int i = 0; i < entries; i++) + { + entryNames.Add(rasEntryNames[i].szEntryName); + } + + return entryNames; + } + throw new ApplicationException($"RasEnumEntries failed with error code: {result}"); + } + + #region WinInet structures + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + public struct InternetPerConnOptionList + { + public int dwSize; // size of the INTERNET_PER_CONN_OPTION_LIST struct + public nint szConnection; // connection name to set/query options + public int dwOptionCount; // number of options to set/query + public int dwOptionError; // on error, which option failed + + //[MarshalAs(UnmanagedType.)] + public nint options; + }; + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + public struct InternetConnectionOption + { + private static readonly int Size; + public PerConnOption m_Option; + public InternetConnectionOptionValue m_Value; + + static InternetConnectionOption() + { + Size = Marshal.SizeOf(typeof(InternetConnectionOption)); + } + + // Nested Types + [StructLayout(LayoutKind.Explicit)] + public struct InternetConnectionOptionValue + { + // Fields + [FieldOffset(0)] + public System.Runtime.InteropServices.ComTypes.FILETIME m_FileTime; + + [FieldOffset(0)] + public int m_Int; + + [FieldOffset(0)] + public nint m_StringPtr; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + public struct RASENTRYNAME + { + public int dwSize; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = RAS_MaxEntryName + 1)] + public string szEntryName; + + public int dwFlags; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)] + public string szPhonebookPath; + } + + // Constants + public const int RAS_MaxEntryName = 256; + + public const int MAX_PATH = 260; // Standard MAX_PATH value in Windows + } + + #endregion WinInet structures + + #region WinInet enums + + // + // options manifests for Internet{Query|Set}Option + // + public enum InternetOption : uint + { + INTERNET_OPTION_PER_CONNECTION_OPTION = 75, + INTERNET_OPTION_REFRESH = 37, + INTERNET_OPTION_SETTINGS_CHANGED = 39 + } + + // + // Options used in INTERNET_PER_CONN_OPTON struct + // + public enum PerConnOption + { + INTERNET_PER_CONN_FLAGS = 1, // Sets or retrieves the connection type. The Value member will contain one or more of the values from PerConnFlags + INTERNET_PER_CONN_PROXY_SERVER = 2, // Sets or retrieves a string containing the proxy servers. + INTERNET_PER_CONN_PROXY_BYPASS = 3, // Sets or retrieves a string containing the URLs that do not use the proxy server. + INTERNET_PER_CONN_AUTOCONFIG_URL = 4//, // Sets or retrieves a string containing the URL to the automatic configuration script. + } + + // + // PER_CONN_FLAGS + // + [Flags] + public enum PerConnFlags + { + PROXY_TYPE_DIRECT = 0x00000001, // direct to net + PROXY_TYPE_PROXY = 0x00000002, // via named proxy + PROXY_TYPE_AUTO_PROXY_URL = 0x00000004, // autoproxy URL + PROXY_TYPE_AUTO_DETECT = 0x00000008 // use autoproxy detection + } + + public enum ErrorCode : uint + { + ERROR_BUFFER_TOO_SMALL = 603, + ERROR_INVALID_SIZE = 632 + } + + #endregion WinInet enums + + internal static class NativeMethods + { + [DllImport("WinInet.dll", SetLastError = true, CharSet = CharSet.Auto)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool InternetSetOption(nint hInternet, InternetOption dwOption, nint lpBuffer, int dwBufferLength); + + [DllImport("Rasapi32.dll", CharSet = CharSet.Auto)] + public static extern uint RasEnumEntries( + string? reserved, // Reserved, must be null + string? lpszPhonebook, // Pointer to full path and filename of phone-book file. If this parameter is NULL, the entries are enumerated from all the remote access phone-book files + [In, Out] RASENTRYNAME[]? lprasentryname, // Buffer to receive RAS entry names + ref int lpcb, // Size of the buffer + ref int lpcEntries // Number of entries written to the buffer + ); + } } \ No newline at end of file diff --git a/v2rayN/v2rayN/Common/QRCodeHelper.cs b/v2rayN/v2rayN/Common/QRCodeHelper.cs index 255ab475..140de6ea 100644 --- a/v2rayN/v2rayN/Common/QRCodeHelper.cs +++ b/v2rayN/v2rayN/Common/QRCodeHelper.cs @@ -9,96 +9,95 @@ using ZXing.Common; using ZXing.QrCode; using ZXing.Windows.Compatibility; -namespace v2rayN +namespace v2rayN; + +/// +/// 含有QR码的描述类和包装编码和渲染 +/// +public class QRCodeHelper { - /// - /// 含有QR码的描述类和包装编码和渲染 - /// - public class QRCodeHelper + public static DrawingImage? GetQRCode(string? strContent) + { + if (strContent is null) { - public static DrawingImage? GetQRCode(string? strContent) - { - if (strContent is null) - { - return null; - } - try - { - QRCodeGenerator qrGenerator = new(); - QRCodeData qrCodeData = qrGenerator.CreateQrCode(strContent, QRCodeGenerator.ECCLevel.H); - XamlQRCode qrCode = new(qrCodeData); - DrawingImage qrCodeAsXaml = qrCode.GetGraphic(40); - return qrCodeAsXaml; - } - catch - { - return null; - } - } - - public static string ScanScreen(float dpiX, float dpiY) - { - try - { - var left = (int)(SystemParameters.WorkArea.Left); - var top = (int)(SystemParameters.WorkArea.Top); - var width = (int)(SystemParameters.WorkArea.Width / dpiX); - var height = (int)(SystemParameters.WorkArea.Height / dpiY); - - using Bitmap fullImage = new Bitmap(width, height); - using (Graphics g = Graphics.FromImage(fullImage)) - { - g.CopyFromScreen(left, top, 0, 0, fullImage.Size, CopyPixelOperation.SourceCopy); - } - int maxTry = 10; - for (int i = 0; i < maxTry; i++) - { - int marginLeft = (int)((double)fullImage.Width * i / 2.5 / maxTry); - int marginTop = (int)((double)fullImage.Height * i / 2.5 / maxTry); - Rectangle cropRect = new(marginLeft, marginTop, fullImage.Width - marginLeft * 2, fullImage.Height - marginTop * 2); - Bitmap target = new(width, height); - - double imageScale = (double)width / (double)cropRect.Width; - using (Graphics g = Graphics.FromImage(target)) - { - g.DrawImage(fullImage, new Rectangle(0, 0, target.Width, target.Height), - cropRect, - GraphicsUnit.Pixel); - } - - BitmapLuminanceSource source = new(target); - QRCodeReader reader = new(); - - BinaryBitmap bitmap = new(new HybridBinarizer(source)); - var result = reader.decode(bitmap); - if (result != null) - { - return result.Text; - } - else - { - BinaryBitmap bitmap2 = new(new HybridBinarizer(source.invert())); - var result2 = reader.decode(bitmap2); - if (result2 != null) - { - return result2.Text; - } - } - } - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - } - return string.Empty; - } - - public static Tuple GetDpiXY(Window window) - { - IntPtr hWnd = new WindowInteropHelper(window).EnsureHandle(); - Graphics g = Graphics.FromHwnd(hWnd); - - return new(96 / g.DpiX, 96 / g.DpiY); - } + return null; } + try + { + QRCodeGenerator qrGenerator = new(); + QRCodeData qrCodeData = qrGenerator.CreateQrCode(strContent, QRCodeGenerator.ECCLevel.H); + XamlQRCode qrCode = new(qrCodeData); + DrawingImage qrCodeAsXaml = qrCode.GetGraphic(40); + return qrCodeAsXaml; + } + catch + { + return null; + } + } + + public static string ScanScreen(float dpiX, float dpiY) + { + try + { + var left = (int)(SystemParameters.WorkArea.Left); + var top = (int)(SystemParameters.WorkArea.Top); + var width = (int)(SystemParameters.WorkArea.Width / dpiX); + var height = (int)(SystemParameters.WorkArea.Height / dpiY); + + using Bitmap fullImage = new Bitmap(width, height); + using (Graphics g = Graphics.FromImage(fullImage)) + { + g.CopyFromScreen(left, top, 0, 0, fullImage.Size, CopyPixelOperation.SourceCopy); + } + int maxTry = 10; + for (int i = 0; i < maxTry; i++) + { + int marginLeft = (int)((double)fullImage.Width * i / 2.5 / maxTry); + int marginTop = (int)((double)fullImage.Height * i / 2.5 / maxTry); + Rectangle cropRect = new(marginLeft, marginTop, fullImage.Width - marginLeft * 2, fullImage.Height - marginTop * 2); + Bitmap target = new(width, height); + + double imageScale = (double)width / (double)cropRect.Width; + using (Graphics g = Graphics.FromImage(target)) + { + g.DrawImage(fullImage, new Rectangle(0, 0, target.Width, target.Height), + cropRect, + GraphicsUnit.Pixel); + } + + BitmapLuminanceSource source = new(target); + QRCodeReader reader = new(); + + BinaryBitmap bitmap = new(new HybridBinarizer(source)); + var result = reader.decode(bitmap); + if (result != null) + { + return result.Text; + } + else + { + BinaryBitmap bitmap2 = new(new HybridBinarizer(source.invert())); + var result2 = reader.decode(bitmap2); + if (result2 != null) + { + return result2.Text; + } + } + } + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + } + return string.Empty; + } + + public static Tuple GetDpiXY(Window window) + { + IntPtr hWnd = new WindowInteropHelper(window).EnsureHandle(); + Graphics g = Graphics.FromHwnd(hWnd); + + return new(96 / g.DpiX, 96 / g.DpiY); + } } \ No newline at end of file diff --git a/v2rayN/v2rayN/Common/QueryableExtension.cs b/v2rayN/v2rayN/Common/QueryableExtension.cs index 113f2824..c7941d33 100644 --- a/v2rayN/v2rayN/Common/QueryableExtension.cs +++ b/v2rayN/v2rayN/Common/QueryableExtension.cs @@ -1,50 +1,49 @@ using System.Linq.Expressions; using System.Reflection; -namespace v2rayN +namespace v2rayN; + +public static class QueryableExtension { - public static class QueryableExtension - { - public static IOrderedQueryable OrderBy(this IQueryable query, string propertyName) - { - return _OrderBy(query, propertyName, false); - } + public static IOrderedQueryable OrderBy(this IQueryable query, string propertyName) + { + return _OrderBy(query, propertyName, false); + } - public static IOrderedQueryable OrderByDescending(this IQueryable query, string propertyName) - { - return _OrderBy(query, propertyName, true); - } + public static IOrderedQueryable OrderByDescending(this IQueryable query, string propertyName) + { + return _OrderBy(query, propertyName, true); + } - private static IOrderedQueryable _OrderBy(IQueryable query, string propertyName, bool isDesc) - { - string methodname = (isDesc) ? "OrderByDescendingInternal" : "OrderByInternal"; + private static IOrderedQueryable _OrderBy(IQueryable query, string propertyName, bool isDesc) + { + string methodname = (isDesc) ? "OrderByDescendingInternal" : "OrderByInternal"; - var memberProp = typeof(T).GetProperty(propertyName); + var memberProp = typeof(T).GetProperty(propertyName); - var method = typeof(QueryableExtension).GetMethod(methodname) - .MakeGenericMethod(typeof(T), memberProp.PropertyType); + var method = typeof(QueryableExtension).GetMethod(methodname) + .MakeGenericMethod(typeof(T), memberProp.PropertyType); - return (IOrderedQueryable)method.Invoke(null, new object[] { query, memberProp }); - } + return (IOrderedQueryable)method.Invoke(null, new object[] { query, memberProp }); + } - public static IOrderedQueryable OrderByInternal(IQueryable query, PropertyInfo memberProperty) - {//public - return query.OrderBy(_GetLambda(memberProperty)); - } + public static IOrderedQueryable OrderByInternal(IQueryable query, PropertyInfo memberProperty) + {//public + return query.OrderBy(_GetLambda(memberProperty)); + } - public static IOrderedQueryable OrderByDescendingInternal(IQueryable query, PropertyInfo memberProperty) - {//public - return query.OrderByDescending(_GetLambda(memberProperty)); - } + public static IOrderedQueryable OrderByDescendingInternal(IQueryable query, PropertyInfo memberProperty) + {//public + return query.OrderByDescending(_GetLambda(memberProperty)); + } - private static Expression> _GetLambda(PropertyInfo memberProperty) - { - if (memberProperty.PropertyType != typeof(TProp)) throw new Exception(); + private static Expression> _GetLambda(PropertyInfo memberProperty) + { + if (memberProperty.PropertyType != typeof(TProp)) throw new Exception(); - var thisArg = Expression.Parameter(typeof(T)); - var lambda = Expression.Lambda>(Expression.Property(thisArg, memberProperty), thisArg); + var thisArg = Expression.Parameter(typeof(T)); + var lambda = Expression.Lambda>(Expression.Property(thisArg, memberProperty), thisArg); - return lambda; - } - } + return lambda; + } } \ No newline at end of file diff --git a/v2rayN/v2rayN/Common/SemanticVersion.cs b/v2rayN/v2rayN/Common/SemanticVersion.cs index 597ed970..cd77798f 100644 --- a/v2rayN/v2rayN/Common/SemanticVersion.cs +++ b/v2rayN/v2rayN/Common/SemanticVersion.cs @@ -1,180 +1,179 @@ -namespace v2rayN +namespace v2rayN; + +public class SemanticVersion { - public class SemanticVersion + private int major; + private int minor; + private int patch; + private string version; + + public SemanticVersion(int major, int minor, int patch) + { + this.major = major; + this.minor = minor; + this.patch = patch; + this.version = $"{major}.{minor}.{patch}"; + } + + public SemanticVersion(string version) + { + this.version = version.RemovePrefix('v'); + try { - private int major; - private int minor; - private int patch; - private string version; - - public SemanticVersion(int major, int minor, int patch) - { - this.major = major; - this.minor = minor; - this.patch = patch; - this.version = $"{major}.{minor}.{patch}"; - } - - public SemanticVersion(string version) - { - this.version = version.RemovePrefix('v'); - try - { - string[] parts = this.version.Split('.'); - if (parts.Length == 2) - { - this.major = int.Parse(parts[0]); - this.minor = int.Parse(parts[1]); - this.patch = 0; - } - else if (parts.Length == 3) - { - this.major = int.Parse(parts[0]); - this.minor = int.Parse(parts[1]); - this.patch = int.Parse(parts[2]); - } - else - { - throw new ArgumentException("Invalid version string"); - } - } - catch - { - this.major = 0; - this.minor = 0; - this.patch = 0; - //this.version = "0.0.0"; - } - } - - public override bool Equals(object? obj) - { - if (obj is SemanticVersion other) - { - return this.major == other.major && this.minor == other.minor && this.patch == other.patch; - } - else - { - return false; - } - } - - public override int GetHashCode() - { - return this.major.GetHashCode() ^ this.minor.GetHashCode() ^ this.patch.GetHashCode(); - } - - /// - /// Use ToVersionString(string? prefix) instead if possible. - /// - /// major.minor.patch - public override string ToString() - { - return this.version; - } - - public string ToVersionString(string? prefix = null) - { - if (prefix == null) - { - return this.version; - } - else - { - return $"{prefix}{this.version}"; - } - } - - public static bool operator ==(SemanticVersion v1, SemanticVersion v2) - { return v1.Equals(v2); } - - public static bool operator !=(SemanticVersion v1, SemanticVersion v2) - { return !v1.Equals(v2); } - - public static bool operator >=(SemanticVersion v1, SemanticVersion v2) - { return v1.GreaterEquals(v2); } - - public static bool operator <=(SemanticVersion v1, SemanticVersion v2) - { return v1.LessEquals(v2); } - - #region Private - - private bool GreaterEquals(SemanticVersion other) - { - if (this.major < other.major) - { - return false; - } - else if (this.major > other.major) - { - return true; - } - else - { - if (this.minor < other.minor) - { - return false; - } - else if (this.minor > other.minor) - { - return true; - } - else - { - if (this.patch < other.patch) - { - return false; - } - else if (this.patch > other.patch) - { - return true; - } - else - { - return true; - } - } - } - } - - private bool LessEquals(SemanticVersion other) - { - if (this.major < other.major) - { - return true; - } - else if (this.major > other.major) - { - return false; - } - else - { - if (this.minor < other.minor) - { - return true; - } - else if (this.minor > other.minor) - { - return false; - } - else - { - if (this.patch < other.patch) - { - return true; - } - else if (this.patch > other.patch) - { - return false; - } - else - { - return true; - } - } - } - } - - #endregion Private + string[] parts = this.version.Split('.'); + if (parts.Length == 2) + { + this.major = int.Parse(parts[0]); + this.minor = int.Parse(parts[1]); + this.patch = 0; + } + else if (parts.Length == 3) + { + this.major = int.Parse(parts[0]); + this.minor = int.Parse(parts[1]); + this.patch = int.Parse(parts[2]); + } + else + { + throw new ArgumentException("Invalid version string"); + } } + catch + { + this.major = 0; + this.minor = 0; + this.patch = 0; + //this.version = "0.0.0"; + } + } + + public override bool Equals(object? obj) + { + if (obj is SemanticVersion other) + { + return this.major == other.major && this.minor == other.minor && this.patch == other.patch; + } + else + { + return false; + } + } + + public override int GetHashCode() + { + return this.major.GetHashCode() ^ this.minor.GetHashCode() ^ this.patch.GetHashCode(); + } + + /// + /// Use ToVersionString(string? prefix) instead if possible. + /// + /// major.minor.patch + public override string ToString() + { + return this.version; + } + + public string ToVersionString(string? prefix = null) + { + if (prefix == null) + { + return this.version; + } + else + { + return $"{prefix}{this.version}"; + } + } + + public static bool operator ==(SemanticVersion v1, SemanticVersion v2) + { return v1.Equals(v2); } + + public static bool operator !=(SemanticVersion v1, SemanticVersion v2) + { return !v1.Equals(v2); } + + public static bool operator >=(SemanticVersion v1, SemanticVersion v2) + { return v1.GreaterEquals(v2); } + + public static bool operator <=(SemanticVersion v1, SemanticVersion v2) + { return v1.LessEquals(v2); } + + #region Private + + private bool GreaterEquals(SemanticVersion other) + { + if (this.major < other.major) + { + return false; + } + else if (this.major > other.major) + { + return true; + } + else + { + if (this.minor < other.minor) + { + return false; + } + else if (this.minor > other.minor) + { + return true; + } + else + { + if (this.patch < other.patch) + { + return false; + } + else if (this.patch > other.patch) + { + return true; + } + else + { + return true; + } + } + } + } + + private bool LessEquals(SemanticVersion other) + { + if (this.major < other.major) + { + return true; + } + else if (this.major > other.major) + { + return false; + } + else + { + if (this.minor < other.minor) + { + return true; + } + else if (this.minor > other.minor) + { + return false; + } + else + { + if (this.patch < other.patch) + { + return true; + } + else if (this.patch > other.patch) + { + return false; + } + else + { + return true; + } + } + } + } + + #endregion Private } \ No newline at end of file diff --git a/v2rayN/v2rayN/Common/SqliteHelper.cs b/v2rayN/v2rayN/Common/SqliteHelper.cs index 70beb810..f8c3c8d8 100644 --- a/v2rayN/v2rayN/Common/SqliteHelper.cs +++ b/v2rayN/v2rayN/Common/SqliteHelper.cs @@ -1,123 +1,122 @@ using SQLite; using System.Collections; -namespace v2rayN +namespace v2rayN; + +public sealed class SQLiteHelper { - public sealed class SQLiteHelper + private static readonly Lazy _instance = new(() => new()); + public static SQLiteHelper Instance => _instance.Value; + private string _connstr; + private SQLiteConnection _db; + private SQLiteAsyncConnection _dbAsync; + private static readonly object objLock = new(); + public readonly string _configDB = "guiNDB.db"; + + public SQLiteHelper() + { + _connstr = Utils.GetConfigPath(_configDB); + _db = new SQLiteConnection(_connstr, false); + _dbAsync = new SQLiteAsyncConnection(_connstr, false); + } + + public CreateTableResult CreateTable() + { + return _db.CreateTable(); + } + + public int Insert(object model) + { + return _db.Insert(model); + } + + public int InsertAll(IEnumerable models) + { + lock (objLock) { - private static readonly Lazy _instance = new(() => new()); - public static SQLiteHelper Instance => _instance.Value; - private string _connstr; - private SQLiteConnection _db; - private SQLiteAsyncConnection _dbAsync; - private static readonly object objLock = new(); - public readonly string _configDB = "guiNDB.db"; - - public SQLiteHelper() - { - _connstr = Utils.GetConfigPath(_configDB); - _db = new SQLiteConnection(_connstr, false); - _dbAsync = new SQLiteAsyncConnection(_connstr, false); - } - - public CreateTableResult CreateTable() - { - return _db.CreateTable(); - } - - public int Insert(object model) - { - return _db.Insert(model); - } - - public int InsertAll(IEnumerable models) - { - lock (objLock) - { - return _db.InsertAll(models); - } - } - - public async Task InsertAsync(object model) - { - return await _dbAsync.InsertAsync(model); - } - - public int Replace(object model) - { - lock (objLock) - { - return _db.InsertOrReplace(model); - } - } - - public async Task ReplaceAsync(object model) - { - return await _dbAsync.InsertOrReplaceAsync(model); - } - - public int Update(object model) - { - lock (objLock) - { - return _db.Update(model); - } - } - - public async Task UpdateAsync(object model) - { - return await _dbAsync.UpdateAsync(model); - } - - public int UpdateAll(IEnumerable models) - { - lock (objLock) - { - return _db.UpdateAll(models); - } - } - - public int Delete(object model) - { - lock (objLock) - { - return _db.Delete(model); - } - } - - public async Task DeleteAsync(object model) - { - return await _dbAsync.DeleteAsync(model); - } - - public List Query(string sql) where T : new() - { - return _db.Query(sql); - } - - public async Task> QueryAsync(string sql) where T : new() - { - return await _dbAsync.QueryAsync(sql); - } - - public int Execute(string sql) - { - return _db.Execute(sql); - } - - public async Task ExecuteAsync(string sql) - { - return await _dbAsync.ExecuteAsync(sql); - } - - public TableQuery Table() where T : new() - { - return _db.Table(); - } - - public AsyncTableQuery TableAsync() where T : new() - { - return _dbAsync.Table(); - } + return _db.InsertAll(models); } + } + + public async Task InsertAsync(object model) + { + return await _dbAsync.InsertAsync(model); + } + + public int Replace(object model) + { + lock (objLock) + { + return _db.InsertOrReplace(model); + } + } + + public async Task ReplaceAsync(object model) + { + return await _dbAsync.InsertOrReplaceAsync(model); + } + + public int Update(object model) + { + lock (objLock) + { + return _db.Update(model); + } + } + + public async Task UpdateAsync(object model) + { + return await _dbAsync.UpdateAsync(model); + } + + public int UpdateAll(IEnumerable models) + { + lock (objLock) + { + return _db.UpdateAll(models); + } + } + + public int Delete(object model) + { + lock (objLock) + { + return _db.Delete(model); + } + } + + public async Task DeleteAsync(object model) + { + return await _dbAsync.DeleteAsync(model); + } + + public List Query(string sql) where T : new() + { + return _db.Query(sql); + } + + public async Task> QueryAsync(string sql) where T : new() + { + return await _dbAsync.QueryAsync(sql); + } + + public int Execute(string sql) + { + return _db.Execute(sql); + } + + public async Task ExecuteAsync(string sql) + { + return await _dbAsync.ExecuteAsync(sql); + } + + public TableQuery Table() where T : new() + { + return _db.Table(); + } + + public AsyncTableQuery TableAsync() where T : new() + { + return _dbAsync.Table(); + } } \ No newline at end of file diff --git a/v2rayN/v2rayN/Common/StringEx.cs b/v2rayN/v2rayN/Common/StringEx.cs index 9a751ce9..2be34bf4 100644 --- a/v2rayN/v2rayN/Common/StringEx.cs +++ b/v2rayN/v2rayN/Common/StringEx.cs @@ -1,94 +1,93 @@ using System.Diagnostics.CodeAnalysis; using System.IO; -namespace v2rayN +namespace v2rayN; + +internal static class StringEx { - internal static class StringEx + public static bool IsNullOrEmpty([NotNullWhen(false)] this string? value) + { + return string.IsNullOrEmpty(value); + } + + public static bool IsNullOrWhiteSpace([NotNullWhen(false)] this string? value) + { + return string.IsNullOrWhiteSpace(value); + } + + public static bool BeginWithAny(this string s, IEnumerable chars) + { + if (s.IsNullOrEmpty()) return false; + return chars.Contains(s[0]); + } + + public static bool IsWhiteSpace(this string value) + { + foreach (char c in value) { - public static bool IsNullOrEmpty([NotNullWhen(false)] this string? value) - { - return string.IsNullOrEmpty(value); - } + if (char.IsWhiteSpace(c)) continue; - public static bool IsNullOrWhiteSpace([NotNullWhen(false)] this string? value) - { - return string.IsNullOrWhiteSpace(value); - } - - public static bool BeginWithAny(this string s, IEnumerable chars) - { - if (s.IsNullOrEmpty()) return false; - return chars.Contains(s[0]); - } - - public static bool IsWhiteSpace(this string value) - { - foreach (char c in value) - { - if (char.IsWhiteSpace(c)) continue; - - return false; - } - return true; - } - - public static IEnumerable NonWhiteSpaceLines(this TextReader reader) - { - string? line; - while ((line = reader.ReadLine()) != null) - { - if (line.IsWhiteSpace()) continue; - yield return line; - } - } - - public static string TrimEx(this string? value) - { - return value == null ? string.Empty : value.Trim(); - } - - public static string RemovePrefix(this string value, char prefix) - { - if (value.StartsWith(prefix)) - { - return value.Substring(1); - } - else - { - return value; - } - } - - public static string RemovePrefix(this string value, string prefix) - { - if (value.StartsWith(prefix)) - { - return value.Substring(prefix.Length); - } - else - { - return value; - } - } - - public static string UpperFirstChar(this string value) - { - if (string.IsNullOrEmpty(value)) - { - return string.Empty; - } - - return char.ToUpper(value[0]) + value.Substring(1); - } - - public static string AppendQuotes(this string value) - { - if (string.IsNullOrEmpty(value)) - { - return string.Empty; - } - - return $"\"{value}\""; - } + return false; } + return true; + } + + public static IEnumerable NonWhiteSpaceLines(this TextReader reader) + { + string? line; + while ((line = reader.ReadLine()) != null) + { + if (line.IsWhiteSpace()) continue; + yield return line; + } + } + + public static string TrimEx(this string? value) + { + return value == null ? string.Empty : value.Trim(); + } + + public static string RemovePrefix(this string value, char prefix) + { + if (value.StartsWith(prefix)) + { + return value.Substring(1); + } + else + { + return value; + } + } + + public static string RemovePrefix(this string value, string prefix) + { + if (value.StartsWith(prefix)) + { + return value.Substring(prefix.Length); + } + else + { + return value; + } + } + + public static string UpperFirstChar(this string value) + { + if (string.IsNullOrEmpty(value)) + { + return string.Empty; + } + + return char.ToUpper(value[0]) + value.Substring(1); + } + + public static string AppendQuotes(this string value) + { + if (string.IsNullOrEmpty(value)) + { + return string.Empty; + } + + return $"\"{value}\""; + } } \ No newline at end of file diff --git a/v2rayN/v2rayN/Common/UI.cs b/v2rayN/v2rayN/Common/UI.cs index 7b608e96..6ccdba22 100644 --- a/v2rayN/v2rayN/Common/UI.cs +++ b/v2rayN/v2rayN/Common/UI.cs @@ -1,39 +1,38 @@ using Microsoft.Win32; using System.Windows; -namespace v2rayN +namespace v2rayN; + +internal class UI { - internal class UI + private static readonly string caption = "v2rayN"; + + public static void Show(string msg) + { + MessageBox.Show(msg, caption, MessageBoxButton.OK, MessageBoxImage.Information, MessageBoxResult.OK); + } + + public static MessageBoxResult ShowYesNo(string msg) + { + return MessageBox.Show(msg, caption, MessageBoxButton.YesNo, MessageBoxImage.Question); + } + + public static bool? OpenFileDialog(out string fileName, string filter) + { + fileName = string.Empty; + + var fileDialog = new OpenFileDialog { - private static readonly string caption = "v2rayN"; + Multiselect = false, + Filter = filter + }; - public static void Show(string msg) - { - MessageBox.Show(msg, caption, MessageBoxButton.OK, MessageBoxImage.Information, MessageBoxResult.OK); - } - - public static MessageBoxResult ShowYesNo(string msg) - { - return MessageBox.Show(msg, caption, MessageBoxButton.YesNo, MessageBoxImage.Question); - } - - public static bool? OpenFileDialog(out string fileName, string filter) - { - fileName = string.Empty; - - var fileDialog = new OpenFileDialog - { - Multiselect = false, - Filter = filter - }; - - if (fileDialog.ShowDialog() != true) - { - return false; - } - fileName = fileDialog.FileName; - - return true; - } + if (fileDialog.ShowDialog() != true) + { + return false; } + fileName = fileDialog.FileName; + + return true; + } } \ No newline at end of file diff --git a/v2rayN/v2rayN/Common/Utils.cs b/v2rayN/v2rayN/Common/Utils.cs index 39f2f9a8..00786b8b 100644 --- a/v2rayN/v2rayN/Common/Utils.cs +++ b/v2rayN/v2rayN/Common/Utils.cs @@ -19,1112 +19,1111 @@ using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Imaging; -namespace v2rayN +namespace v2rayN; + +internal class Utils { - internal class Utils + #region 资源Json操作 + + /// + /// 获取嵌入文本资源 + /// + /// + /// + public static string GetEmbedText(string res) + { + string result = string.Empty; + + try { - #region 资源Json操作 - - /// - /// 获取嵌入文本资源 - /// - /// - /// - public static string GetEmbedText(string res) - { - string result = string.Empty; - - try - { - Assembly assembly = Assembly.GetExecutingAssembly(); - using Stream? stream = assembly.GetManifestResourceStream(res); - ArgumentNullException.ThrowIfNull(stream); - using StreamReader reader = new(stream); - result = reader.ReadToEnd(); - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - } - return result; - } - - /// - /// 取得存储资源 - /// - /// - public static string? LoadResource(string? res) - { - try - { - if (!File.Exists(res)) - { - return null; - } - return File.ReadAllText(res); - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - } - return null; - } - - #endregion 资源Json操作 - - #region 转换函数 - - /// - /// List转逗号分隔的字符串 - /// - /// - /// - public static string List2String(List? lst, bool wrap = false) - { - try - { - if (lst == null) - { - return string.Empty; - } - if (wrap) - { - return string.Join("," + Environment.NewLine, lst); - } - else - { - return string.Join(",", lst); - } - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - return string.Empty; - } - } - - /// - /// 逗号分隔的字符串,转List - /// - /// - /// - public static List String2List(string str) - { - try - { - str = str.Replace(Environment.NewLine, ""); - return new List(str.Split(',', StringSplitOptions.RemoveEmptyEntries)); - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - return new List(); - } - } - - /// - /// 逗号分隔的字符串,先排序后转List - /// - /// - /// - public static List String2ListSorted(string str) - { - try - { - str = str.Replace(Environment.NewLine, ""); - List list = new(str.Split(',', StringSplitOptions.RemoveEmptyEntries)); - list.Sort(); - return list; - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - return new List(); - } - } - - /// - /// Base64编码 - /// - /// - /// - public static string Base64Encode(string plainText) - { - try - { - byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText); - return Convert.ToBase64String(plainTextBytes); - } - catch (Exception ex) - { - Logging.SaveLog("Base64Encode", ex); - return string.Empty; - } - } - - /// - /// Base64解码 - /// - /// - /// - public static string Base64Decode(string plainText) - { - try - { - plainText = plainText.Trim() - .Replace(Environment.NewLine, "") - .Replace("\n", "") - .Replace("\r", "") - .Replace('_', '/') - .Replace('-', '+') - .Replace(" ", ""); - - if (plainText.Length % 4 > 0) - { - plainText = plainText.PadRight(plainText.Length + 4 - plainText.Length % 4, '='); - } - - byte[] data = Convert.FromBase64String(plainText); - return Encoding.UTF8.GetString(data); - } - catch (Exception ex) - { - Logging.SaveLog("Base64Decode", ex); - return string.Empty; - } - } - - /// - /// 转Int - /// - /// - /// - public static int ToInt(object? obj) - { - try - { - return Convert.ToInt32(obj ?? string.Empty); - } - catch //(Exception ex) - { - //SaveLog(ex.Message, ex); - return 0; - } - } - - public static bool ToBool(object obj) - { - try - { - return Convert.ToBoolean(obj); - } - catch //(Exception ex) - { - //SaveLog(ex.Message, ex); - return false; - } - } - - public static string ToString(object obj) - { - try - { - return obj?.ToString() ?? string.Empty; - } - catch// (Exception ex) - { - //SaveLog(ex.Message, ex); - return string.Empty; - } - } - - /// - /// byte 转成 有两位小数点的 方便阅读的数据 - /// 比如 2.50 MB - /// - /// bytes - /// 转换之后的数据 - /// 单位 - public static void ToHumanReadable(long amount, out double result, out string unit) - { - uint factor = 1024u; - //long KBs = amount / factor; - long KBs = amount; - if (KBs > 0) - { - // multi KB - long MBs = KBs / factor; - if (MBs > 0) - { - // multi MB - long GBs = MBs / factor; - if (GBs > 0) - { - // multi GB - long TBs = GBs / factor; - if (TBs > 0) - { - result = TBs + ((GBs % factor) / (factor + 0.0)); - unit = "TB"; - return; - } - result = GBs + ((MBs % factor) / (factor + 0.0)); - unit = "GB"; - return; - } - result = MBs + ((KBs % factor) / (factor + 0.0)); - unit = "MB"; - return; - } - result = KBs + ((amount % factor) / (factor + 0.0)); - unit = "KB"; - return; - } - else - { - result = amount; - unit = "B"; - } - } - - public static string HumanFy(long amount) - { - ToHumanReadable(amount, out double result, out string unit); - return $"{string.Format("{0:f1}", result)} {unit}"; - } - - public static string UrlEncode(string url) - { - return Uri.EscapeDataString(url); - //return HttpUtility.UrlEncode(url); - } - - public static string UrlDecode(string url) - { - return Uri.UnescapeDataString(url); - //return HttpUtility.UrlDecode(url); - } - - public static NameValueCollection ParseQueryString(string query) - { - var result = new NameValueCollection(StringComparer.OrdinalIgnoreCase); - if (IsNullOrEmpty(query)) - { - return result; - } - - var parts = query[1..].Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries); - foreach (var part in parts) - { - var keyValue = part.Split(['=']); - if (keyValue.Length != 2) - { - continue; - } - var key = Uri.UnescapeDataString(keyValue[0]); - var val = Uri.UnescapeDataString(keyValue[1]); - - if (result[key] is null) - { - result.Add(key, val); - } - } - - return result; - } - - public static string GetMD5(string str) - { - byte[] byteOld = Encoding.UTF8.GetBytes(str); - byte[] byteNew = MD5.HashData(byteOld); - StringBuilder sb = new(32); - foreach (byte b in byteNew) - { - sb.Append(b.ToString("x2")); - } - return sb.ToString(); - } - - public static ImageSource IconToImageSource(Icon icon) - { - return Imaging.CreateBitmapSourceFromHIcon( - icon.Handle, - new System.Windows.Int32Rect(0, 0, icon.Width, icon.Height), - BitmapSizeOptions.FromEmptyOptions()); - } - - /// - /// idn to idc - /// - /// - /// - public static string GetPunycode(string url) - { - if (Utils.IsNullOrEmpty(url)) - { - return url; - } - try - { - Uri uri = new(url); - if (uri.Host == uri.IdnHost || uri.Host == $"[{uri.IdnHost}]") - { - return url; - } - else - { - return url.Replace(uri.Host, uri.IdnHost); - } - } - catch - { - return url; - } - } - - public static bool IsBase64String(string plainText) - { - var buffer = new Span(new byte[plainText.Length]); - return Convert.TryFromBase64String(plainText, buffer, out int _); - } - - public static string Convert2Comma(string text) - { - if (Utils.IsNullOrEmpty(text)) - { - return text; - } - return text.Replace(",", ",").Replace(Environment.NewLine, ","); - } - - #endregion 转换函数 - - #region 数据检查 - - /// - /// 判断输入的是否是数字 - /// - /// - /// - public static bool IsNumeric(string oText) - { - try - { - int var1 = ToInt(oText); - return true; - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - return false; - } - } - - /// - /// 文本 - /// - /// - /// - public static bool IsNullOrEmpty(string? text) - { - if (string.IsNullOrWhiteSpace(text)) - { - return true; - } - if (text == "null") - { - return true; - } - return false; - } - - /// - /// 验证IP地址是否合法 - /// - /// - public static bool IsIP(string ip) - { - //如果为空 - if (IsNullOrEmpty(ip)) - { - return false; - } - - //清除要验证字符串中的空格 - //ip = ip.TrimEx(); - //可能是CIDR - if (ip.IndexOf(@"/") > 0) - { - string[] cidr = ip.Split('/'); - if (cidr.Length == 2) - { - if (!IsNumeric(cidr[0])) - { - return false; - } - ip = cidr[0]; - } - } - - //模式字符串 - string pattern = @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$"; - - //验证 - return IsMatch(ip, pattern); - } - - /// - /// 验证Domain地址是否合法 - /// - /// - public static bool IsDomain(string? domain) - { - //如果为空 - if (IsNullOrEmpty(domain)) - { - return false; - } - - return Uri.CheckHostName(domain) == UriHostNameType.Dns; - } - - /// - /// 验证输入字符串是否与模式字符串匹配,匹配返回true - /// - /// 输入字符串 - /// 模式字符串 - public static bool IsMatch(string input, string pattern) - { - return Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase); - } - - public static bool IsIpv6(string ip) - { - if (IPAddress.TryParse(ip, out IPAddress? address)) - { - return address.AddressFamily switch - { - AddressFamily.InterNetwork => false, - AddressFamily.InterNetworkV6 => true, - _ => false, - }; - } - return false; - } - - #endregion 数据检查 - - #region 测速 - - /// - /// 取得本机 IP Address - /// - /// - //public static List GetHostIPAddress() - //{ - // List lstIPAddress = new List(); - // try - // { - // IPHostEntry IpEntry = Dns.GetHostEntry(Dns.GetHostName()); - // foreach (IPAddress ipa in IpEntry.AddressList) - // { - // if (ipa.AddressFamily == AddressFamily.InterNetwork) - // lstIPAddress.Add(ipa.ToString()); - // } - // } - // catch (Exception ex) - // { - // SaveLog(ex.Message, ex); - // } - // return lstIPAddress; - //} - - public static void SetSecurityProtocol(bool enableSecurityProtocolTls13) - { - if (enableSecurityProtocolTls13) - { - ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13; - } - else - { - ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12; - } - ServicePointManager.DefaultConnectionLimit = 256; - } - - public static bool PortInUse(int port) - { - bool inUse = false; - try - { - IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties(); - IPEndPoint[] ipEndPoints = ipProperties.GetActiveTcpListeners(); - - var lstIpEndPoints = new List(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners()); - - foreach (IPEndPoint endPoint in ipEndPoints) - { - if (endPoint.Port == port) - { - inUse = true; - break; - } - } - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - } - return inUse; - } - - public static int GetFreePort(int defaultPort = 9090) - { - try - { - if (!Utils.PortInUse(defaultPort)) - { - return defaultPort; - } - - TcpListener l = new(IPAddress.Loopback, 0); - l.Start(); - int port = ((IPEndPoint)l.LocalEndpoint).Port; - l.Stop(); - return port; - } - catch - { - } - return 59090; - } - - #endregion 测速 - - #region 杂项 - - /// - /// 取得版本 - /// - /// - public static string GetVersion(bool blFull = true) - { - try - { - string location = GetExePath(); - if (blFull) - { - return string.Format("v2rayN - V{0} - {1}", - FileVersionInfo.GetVersionInfo(location).FileVersion?.ToString(), - File.GetLastWriteTime(location).ToString("yyyy/MM/dd")); - } - else - { - return string.Format("v2rayN/{0}", - FileVersionInfo.GetVersionInfo(location).FileVersion?.ToString()); - } - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - return string.Empty; - } - } - - /// - /// 获取剪贴板数 - /// - /// - public static string? GetClipboardData() - { - string? strData = string.Empty; - try - { - IDataObject data = Clipboard.GetDataObject(); - if (data.GetDataPresent(DataFormats.UnicodeText)) - { - strData = data.GetData(DataFormats.UnicodeText)?.ToString(); - } - return strData; - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - } - return strData; - } - - /// - /// 拷贝至剪贴板 - /// - /// - public static void SetClipboardData(string strData) - { - try - { - Clipboard.SetText(strData); - } - catch - { - } - } - - /// - /// 取得GUID - /// - /// - public static string GetGUID(bool full = true) - { - try - { - if (full) - { - return Guid.NewGuid().ToString("D"); - } - else - { - return BitConverter.ToInt64(Guid.NewGuid().ToByteArray(), 0).ToString(); - } - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - } - return string.Empty; - } - - /// - /// IsAdministrator - /// - /// - public static bool IsAdministrator() - { - try - { - WindowsIdentity current = WindowsIdentity.GetCurrent(); - WindowsPrincipal windowsPrincipal = new WindowsPrincipal(current); - //WindowsBuiltInRole可以枚举出很多权限,例如系统用户、User、Guest等等 - return windowsPrincipal.IsInRole(WindowsBuiltInRole.Administrator); - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - return false; - } - } - - public static string GetDownloadFileName(string url) - { - var fileName = Path.GetFileName(url); - fileName += "_temp"; - - return fileName; - } - - public static IPAddress? GetDefaultGateway() - { - return NetworkInterface - .GetAllNetworkInterfaces() - .Where(n => n.OperationalStatus == OperationalStatus.Up) - .Where(n => n.NetworkInterfaceType != NetworkInterfaceType.Loopback) - .SelectMany(n => n.GetIPProperties()?.GatewayAddresses) - .Select(g => g?.Address) - .Where(a => a != null) - // .Where(a => a.AddressFamily == AddressFamily.InterNetwork) - // .Where(a => Array.FindIndex(a.GetAddressBytes(), b => b != 0) >= 0) - .FirstOrDefault(); - } - - public static bool IsGuidByParse(string strSrc) - { - return Guid.TryParse(strSrc, out Guid g); - } - - public static void ProcessStart(string fileName, string arguments = "") - { - try - { - Process.Start(new ProcessStartInfo(fileName, arguments) { UseShellExecute = true }); - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - } - } - - 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(); - int attribute = dark ? 1 : 0; - uint attributeSize = (uint)Marshal.SizeOf(attribute); - DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1, ref attribute, attributeSize); - DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, ref attribute, attributeSize); - } - - public static bool IsLightTheme() - { - using var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"); - var value = key?.GetValue("AppsUseLightTheme"); - return value is int i && i > 0; - } - - /// - /// 获取系统hosts - /// - /// - public static Dictionary GetSystemHosts() - { - var systemHosts = new Dictionary(); - var hostfile = @"C:\Windows\System32\drivers\etc\hosts"; - try - { - if (File.Exists(hostfile)) - { - var hosts = File.ReadAllText(hostfile).Replace("\r", ""); - var hostsList = hosts.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); - - foreach (var host in hostsList) - { - if (host.StartsWith("#")) continue; - var hostItem = host.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); - if (hostItem.Length < 2) continue; - systemHosts.Add(hostItem[1], hostItem[0]); - } - } - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - } - return systemHosts; - } - - #endregion 杂项 - - #region TempPath - - /// - /// 获取启动了应用程序的可执行文件的路径 - /// - /// - public static string GetPath(string fileName) - { - string startupPath = StartupPath(); - if (IsNullOrEmpty(fileName)) - { - return startupPath; - } - return Path.Combine(startupPath, fileName); - } - - /// - /// 获取启动了应用程序的可执行文件的路径及文件名 - /// - /// - public static string GetExePath() - { - return Environment.ProcessPath ?? string.Empty; - } - - public static string StartupPath() - { - return AppDomain.CurrentDomain.BaseDirectory; - } - - public static string GetTempPath(string filename = "") - { - string _tempPath = Path.Combine(StartupPath(), "guiTemps"); - if (!Directory.Exists(_tempPath)) - { - Directory.CreateDirectory(_tempPath); - } - if (Utils.IsNullOrEmpty(filename)) - { - return _tempPath; - } - else - { - return Path.Combine(_tempPath, filename); - } - } - - public static string UnGzip(byte[] buf) - { - using MemoryStream sb = new(); - using GZipStream input = new(new MemoryStream(buf), CompressionMode.Decompress, false); - input.CopyTo(sb); - sb.Position = 0; - return new StreamReader(sb, Encoding.UTF8).ReadToEnd(); - } - - public static string GetBackupPath(string filename) - { - string _tempPath = Path.Combine(StartupPath(), "guiBackups"); - if (!Directory.Exists(_tempPath)) - { - Directory.CreateDirectory(_tempPath); - } - return Path.Combine(_tempPath, filename); - } - - public static string GetConfigPath(string filename = "") - { - string _tempPath = Path.Combine(StartupPath(), "guiConfigs"); - if (!Directory.Exists(_tempPath)) - { - Directory.CreateDirectory(_tempPath); - } - if (Utils.IsNullOrEmpty(filename)) - { - return _tempPath; - } - else - { - return Path.Combine(_tempPath, filename); - } - } - - public static string GetBinPath(string filename, string? coreType = null) - { - string _tempPath = Path.Combine(StartupPath(), "bin"); - if (!Directory.Exists(_tempPath)) - { - Directory.CreateDirectory(_tempPath); - } - if (coreType != null) - { - _tempPath = Path.Combine(_tempPath, coreType.ToString()!); - if (!Directory.Exists(_tempPath)) - { - Directory.CreateDirectory(_tempPath); - } - } - if (Utils.IsNullOrEmpty(filename)) - { - return _tempPath; - } - else - { - return Path.Combine(_tempPath, filename); - } - } - - public static string GetLogPath(string filename = "") - { - string _tempPath = Path.Combine(StartupPath(), "guiLogs"); - if (!Directory.Exists(_tempPath)) - { - Directory.CreateDirectory(_tempPath); - } - if (Utils.IsNullOrEmpty(filename)) - { - return _tempPath; - } - else - { - return Path.Combine(_tempPath, filename); - } - } - - public static string GetFontsPath(string filename = "") - { - string _tempPath = Path.Combine(StartupPath(), "guiFonts"); - if (!Directory.Exists(_tempPath)) - { - Directory.CreateDirectory(_tempPath); - } - if (Utils.IsNullOrEmpty(filename)) - { - return _tempPath; - } - else - { - return Path.Combine(_tempPath, filename); - } - } - - #endregion TempPath - - #region 开机自动启动等 - - /// - /// 开机自动启动 - /// - /// - /// - public static void SetAutoRun(string AutoRunRegPath, string AutoRunName, bool run) - { - try - { - var autoRunName = $"{AutoRunName}_{GetMD5(StartupPath())}"; - - //delete first - RegWriteValue(AutoRunRegPath, autoRunName, ""); - if (IsAdministrator()) - { - AutoStart(autoRunName, "", ""); - } - - if (run) - { - string exePath = GetExePath(); - if (IsAdministrator()) - { - AutoStart(autoRunName, exePath, ""); - } - else - { - RegWriteValue(AutoRunRegPath, autoRunName, exePath.AppendQuotes()); - } - } - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - } - } - - public static string? RegReadValue(string path, string name, string def) - { - RegistryKey? regKey = null; - try - { - regKey = Registry.CurrentUser.OpenSubKey(path, false); - string? value = regKey?.GetValue(name) as string; - if (IsNullOrEmpty(value)) - { - return def; - } - else - { - return value; - } - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - } - finally - { - regKey?.Close(); - } - return def; - } - - public static void RegWriteValue(string path, string name, object value) - { - RegistryKey? regKey = null; - try - { - regKey = Registry.CurrentUser.CreateSubKey(path); - if (IsNullOrEmpty(value.ToString())) - { - regKey?.DeleteValue(name, false); - } - else - { - regKey?.SetValue(name, value); - } - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - } - finally - { - regKey?.Close(); - } - } - - /// - /// Auto Start via TaskService - /// - /// - /// - /// - /// - public static void AutoStart(string taskName, string fileName, string description) - { - if (Utils.IsNullOrEmpty(taskName)) - { - return; - } - string TaskName = taskName; - var logonUser = WindowsIdentity.GetCurrent().Name; - string taskDescription = description; - string deamonFileName = fileName; - - using var taskService = new TaskService(); - var tasks = taskService.RootFolder.GetTasks(new Regex(TaskName)); - foreach (var t in tasks) - { - taskService.RootFolder.DeleteTask(t.Name); - } - if (Utils.IsNullOrEmpty(fileName)) - { - return; - } - - var task = taskService.NewTask(); - task.RegistrationInfo.Description = taskDescription; - task.Settings.DisallowStartIfOnBatteries = false; - task.Settings.StopIfGoingOnBatteries = false; - task.Settings.RunOnlyIfIdle = false; - task.Settings.IdleSettings.StopOnIdleEnd = false; - task.Settings.ExecutionTimeLimit = TimeSpan.Zero; - task.Triggers.Add(new LogonTrigger { UserId = logonUser, Delay = TimeSpan.FromSeconds(10) }); - task.Principal.RunLevel = TaskRunLevel.Highest; - task.Actions.Add(new ExecAction(deamonFileName.AppendQuotes(), null, Path.GetDirectoryName(deamonFileName))); - - taskService.RootFolder.RegisterTaskDefinition(TaskName, task); - } - - public static void RemoveTunDevice() - { - try - { - var sum = MD5.HashData(Encoding.UTF8.GetBytes("wintunsingbox_tun")); - var guid = new Guid(sum); - string pnputilPath = @"C:\Windows\System32\pnputil.exe"; - string arg = $$""" /remove-device "SWD\Wintun\{{{guid}}}" """; - - // Try to remove the device - Process proc = new() - { - StartInfo = new() - { - FileName = pnputilPath, - Arguments = arg, - RedirectStandardOutput = true, - UseShellExecute = false, - CreateNoWindow = true - } - }; - - proc.Start(); - var output = proc.StandardOutput.ReadToEnd(); - proc.WaitForExit(); - } - catch - { - } - } - - #endregion 开机自动启动等 - - #region Windows API - - [Flags] - public enum DWMWINDOWATTRIBUTE : uint - { - DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19, - DWMWA_USE_IMMERSIVE_DARK_MODE = 20, - } - - [DllImport("dwmapi.dll")] - public static extern int DwmSetWindowAttribute(IntPtr hwnd, DWMWINDOWATTRIBUTE attribute, ref int attributeValue, uint attributeSize); - - #endregion Windows API + Assembly assembly = Assembly.GetExecutingAssembly(); + using Stream? stream = assembly.GetManifestResourceStream(res); + ArgumentNullException.ThrowIfNull(stream); + using StreamReader reader = new(stream); + result = reader.ReadToEnd(); } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + } + return result; + } + + /// + /// 取得存储资源 + /// + /// + public static string? LoadResource(string? res) + { + try + { + if (!File.Exists(res)) + { + return null; + } + return File.ReadAllText(res); + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + } + return null; + } + + #endregion 资源Json操作 + + #region 转换函数 + + /// + /// List转逗号分隔的字符串 + /// + /// + /// + public static string List2String(List? lst, bool wrap = false) + { + try + { + if (lst == null) + { + return string.Empty; + } + if (wrap) + { + return string.Join("," + Environment.NewLine, lst); + } + else + { + return string.Join(",", lst); + } + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + return string.Empty; + } + } + + /// + /// 逗号分隔的字符串,转List + /// + /// + /// + public static List String2List(string str) + { + try + { + str = str.Replace(Environment.NewLine, ""); + return new List(str.Split(',', StringSplitOptions.RemoveEmptyEntries)); + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + return new List(); + } + } + + /// + /// 逗号分隔的字符串,先排序后转List + /// + /// + /// + public static List String2ListSorted(string str) + { + try + { + str = str.Replace(Environment.NewLine, ""); + List list = new(str.Split(',', StringSplitOptions.RemoveEmptyEntries)); + list.Sort(); + return list; + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + return new List(); + } + } + + /// + /// Base64编码 + /// + /// + /// + public static string Base64Encode(string plainText) + { + try + { + byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText); + return Convert.ToBase64String(plainTextBytes); + } + catch (Exception ex) + { + Logging.SaveLog("Base64Encode", ex); + return string.Empty; + } + } + + /// + /// Base64解码 + /// + /// + /// + public static string Base64Decode(string plainText) + { + try + { + plainText = plainText.Trim() + .Replace(Environment.NewLine, "") + .Replace("\n", "") + .Replace("\r", "") + .Replace('_', '/') + .Replace('-', '+') + .Replace(" ", ""); + + if (plainText.Length % 4 > 0) + { + plainText = plainText.PadRight(plainText.Length + 4 - plainText.Length % 4, '='); + } + + byte[] data = Convert.FromBase64String(plainText); + return Encoding.UTF8.GetString(data); + } + catch (Exception ex) + { + Logging.SaveLog("Base64Decode", ex); + return string.Empty; + } + } + + /// + /// 转Int + /// + /// + /// + public static int ToInt(object? obj) + { + try + { + return Convert.ToInt32(obj ?? string.Empty); + } + catch //(Exception ex) + { + //SaveLog(ex.Message, ex); + return 0; + } + } + + public static bool ToBool(object obj) + { + try + { + return Convert.ToBoolean(obj); + } + catch //(Exception ex) + { + //SaveLog(ex.Message, ex); + return false; + } + } + + public static string ToString(object obj) + { + try + { + return obj?.ToString() ?? string.Empty; + } + catch// (Exception ex) + { + //SaveLog(ex.Message, ex); + return string.Empty; + } + } + + /// + /// byte 转成 有两位小数点的 方便阅读的数据 + /// 比如 2.50 MB + /// + /// bytes + /// 转换之后的数据 + /// 单位 + public static void ToHumanReadable(long amount, out double result, out string unit) + { + uint factor = 1024u; + //long KBs = amount / factor; + long KBs = amount; + if (KBs > 0) + { + // multi KB + long MBs = KBs / factor; + if (MBs > 0) + { + // multi MB + long GBs = MBs / factor; + if (GBs > 0) + { + // multi GB + long TBs = GBs / factor; + if (TBs > 0) + { + result = TBs + ((GBs % factor) / (factor + 0.0)); + unit = "TB"; + return; + } + result = GBs + ((MBs % factor) / (factor + 0.0)); + unit = "GB"; + return; + } + result = MBs + ((KBs % factor) / (factor + 0.0)); + unit = "MB"; + return; + } + result = KBs + ((amount % factor) / (factor + 0.0)); + unit = "KB"; + return; + } + else + { + result = amount; + unit = "B"; + } + } + + public static string HumanFy(long amount) + { + ToHumanReadable(amount, out double result, out string unit); + return $"{string.Format("{0:f1}", result)} {unit}"; + } + + public static string UrlEncode(string url) + { + return Uri.EscapeDataString(url); + //return HttpUtility.UrlEncode(url); + } + + public static string UrlDecode(string url) + { + return Uri.UnescapeDataString(url); + //return HttpUtility.UrlDecode(url); + } + + public static NameValueCollection ParseQueryString(string query) + { + var result = new NameValueCollection(StringComparer.OrdinalIgnoreCase); + if (IsNullOrEmpty(query)) + { + return result; + } + + var parts = query[1..].Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries); + foreach (var part in parts) + { + var keyValue = part.Split(['=']); + if (keyValue.Length != 2) + { + continue; + } + var key = Uri.UnescapeDataString(keyValue[0]); + var val = Uri.UnescapeDataString(keyValue[1]); + + if (result[key] is null) + { + result.Add(key, val); + } + } + + return result; + } + + public static string GetMD5(string str) + { + byte[] byteOld = Encoding.UTF8.GetBytes(str); + byte[] byteNew = MD5.HashData(byteOld); + StringBuilder sb = new(32); + foreach (byte b in byteNew) + { + sb.Append(b.ToString("x2")); + } + return sb.ToString(); + } + + public static ImageSource IconToImageSource(Icon icon) + { + return Imaging.CreateBitmapSourceFromHIcon( + icon.Handle, + new System.Windows.Int32Rect(0, 0, icon.Width, icon.Height), + BitmapSizeOptions.FromEmptyOptions()); + } + + /// + /// idn to idc + /// + /// + /// + public static string GetPunycode(string url) + { + if (Utils.IsNullOrEmpty(url)) + { + return url; + } + try + { + Uri uri = new(url); + if (uri.Host == uri.IdnHost || uri.Host == $"[{uri.IdnHost}]") + { + return url; + } + else + { + return url.Replace(uri.Host, uri.IdnHost); + } + } + catch + { + return url; + } + } + + public static bool IsBase64String(string plainText) + { + var buffer = new Span(new byte[plainText.Length]); + return Convert.TryFromBase64String(plainText, buffer, out int _); + } + + public static string Convert2Comma(string text) + { + if (Utils.IsNullOrEmpty(text)) + { + return text; + } + return text.Replace(",", ",").Replace(Environment.NewLine, ","); + } + + #endregion 转换函数 + + #region 数据检查 + + /// + /// 判断输入的是否是数字 + /// + /// + /// + public static bool IsNumeric(string oText) + { + try + { + int var1 = ToInt(oText); + return true; + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + return false; + } + } + + /// + /// 文本 + /// + /// + /// + public static bool IsNullOrEmpty(string? text) + { + if (string.IsNullOrWhiteSpace(text)) + { + return true; + } + if (text == "null") + { + return true; + } + return false; + } + + /// + /// 验证IP地址是否合法 + /// + /// + public static bool IsIP(string ip) + { + //如果为空 + if (IsNullOrEmpty(ip)) + { + return false; + } + + //清除要验证字符串中的空格 + //ip = ip.TrimEx(); + //可能是CIDR + if (ip.IndexOf(@"/") > 0) + { + string[] cidr = ip.Split('/'); + if (cidr.Length == 2) + { + if (!IsNumeric(cidr[0])) + { + return false; + } + ip = cidr[0]; + } + } + + //模式字符串 + string pattern = @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$"; + + //验证 + return IsMatch(ip, pattern); + } + + /// + /// 验证Domain地址是否合法 + /// + /// + public static bool IsDomain(string? domain) + { + //如果为空 + if (IsNullOrEmpty(domain)) + { + return false; + } + + return Uri.CheckHostName(domain) == UriHostNameType.Dns; + } + + /// + /// 验证输入字符串是否与模式字符串匹配,匹配返回true + /// + /// 输入字符串 + /// 模式字符串 + public static bool IsMatch(string input, string pattern) + { + return Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase); + } + + public static bool IsIpv6(string ip) + { + if (IPAddress.TryParse(ip, out IPAddress? address)) + { + return address.AddressFamily switch + { + AddressFamily.InterNetwork => false, + AddressFamily.InterNetworkV6 => true, + _ => false, + }; + } + return false; + } + + #endregion 数据检查 + + #region 测速 + + /// + /// 取得本机 IP Address + /// + /// + //public static List GetHostIPAddress() + //{ + // List lstIPAddress = new List(); + // try + // { + // IPHostEntry IpEntry = Dns.GetHostEntry(Dns.GetHostName()); + // foreach (IPAddress ipa in IpEntry.AddressList) + // { + // if (ipa.AddressFamily == AddressFamily.InterNetwork) + // lstIPAddress.Add(ipa.ToString()); + // } + // } + // catch (Exception ex) + // { + // SaveLog(ex.Message, ex); + // } + // return lstIPAddress; + //} + + public static void SetSecurityProtocol(bool enableSecurityProtocolTls13) + { + if (enableSecurityProtocolTls13) + { + ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13; + } + else + { + ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12; + } + ServicePointManager.DefaultConnectionLimit = 256; + } + + public static bool PortInUse(int port) + { + bool inUse = false; + try + { + IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties(); + IPEndPoint[] ipEndPoints = ipProperties.GetActiveTcpListeners(); + + var lstIpEndPoints = new List(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners()); + + foreach (IPEndPoint endPoint in ipEndPoints) + { + if (endPoint.Port == port) + { + inUse = true; + break; + } + } + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + } + return inUse; + } + + public static int GetFreePort(int defaultPort = 9090) + { + try + { + if (!Utils.PortInUse(defaultPort)) + { + return defaultPort; + } + + TcpListener l = new(IPAddress.Loopback, 0); + l.Start(); + int port = ((IPEndPoint)l.LocalEndpoint).Port; + l.Stop(); + return port; + } + catch + { + } + return 59090; + } + + #endregion 测速 + + #region 杂项 + + /// + /// 取得版本 + /// + /// + public static string GetVersion(bool blFull = true) + { + try + { + string location = GetExePath(); + if (blFull) + { + return string.Format("v2rayN - V{0} - {1}", + FileVersionInfo.GetVersionInfo(location).FileVersion?.ToString(), + File.GetLastWriteTime(location).ToString("yyyy/MM/dd")); + } + else + { + return string.Format("v2rayN/{0}", + FileVersionInfo.GetVersionInfo(location).FileVersion?.ToString()); + } + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + return string.Empty; + } + } + + /// + /// 获取剪贴板数 + /// + /// + public static string? GetClipboardData() + { + string? strData = string.Empty; + try + { + IDataObject data = Clipboard.GetDataObject(); + if (data.GetDataPresent(DataFormats.UnicodeText)) + { + strData = data.GetData(DataFormats.UnicodeText)?.ToString(); + } + return strData; + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + } + return strData; + } + + /// + /// 拷贝至剪贴板 + /// + /// + public static void SetClipboardData(string strData) + { + try + { + Clipboard.SetText(strData); + } + catch + { + } + } + + /// + /// 取得GUID + /// + /// + public static string GetGUID(bool full = true) + { + try + { + if (full) + { + return Guid.NewGuid().ToString("D"); + } + else + { + return BitConverter.ToInt64(Guid.NewGuid().ToByteArray(), 0).ToString(); + } + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + } + return string.Empty; + } + + /// + /// IsAdministrator + /// + /// + public static bool IsAdministrator() + { + try + { + WindowsIdentity current = WindowsIdentity.GetCurrent(); + WindowsPrincipal windowsPrincipal = new WindowsPrincipal(current); + //WindowsBuiltInRole可以枚举出很多权限,例如系统用户、User、Guest等等 + return windowsPrincipal.IsInRole(WindowsBuiltInRole.Administrator); + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + return false; + } + } + + public static string GetDownloadFileName(string url) + { + var fileName = Path.GetFileName(url); + fileName += "_temp"; + + return fileName; + } + + public static IPAddress? GetDefaultGateway() + { + return NetworkInterface + .GetAllNetworkInterfaces() + .Where(n => n.OperationalStatus == OperationalStatus.Up) + .Where(n => n.NetworkInterfaceType != NetworkInterfaceType.Loopback) + .SelectMany(n => n.GetIPProperties()?.GatewayAddresses) + .Select(g => g?.Address) + .Where(a => a != null) + // .Where(a => a.AddressFamily == AddressFamily.InterNetwork) + // .Where(a => Array.FindIndex(a.GetAddressBytes(), b => b != 0) >= 0) + .FirstOrDefault(); + } + + public static bool IsGuidByParse(string strSrc) + { + return Guid.TryParse(strSrc, out Guid g); + } + + public static void ProcessStart(string fileName, string arguments = "") + { + try + { + Process.Start(new ProcessStartInfo(fileName, arguments) { UseShellExecute = true }); + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + } + } + + 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(); + int attribute = dark ? 1 : 0; + uint attributeSize = (uint)Marshal.SizeOf(attribute); + DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1, ref attribute, attributeSize); + DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, ref attribute, attributeSize); + } + + public static bool IsLightTheme() + { + using var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"); + var value = key?.GetValue("AppsUseLightTheme"); + return value is int i && i > 0; + } + + /// + /// 获取系统hosts + /// + /// + public static Dictionary GetSystemHosts() + { + var systemHosts = new Dictionary(); + var hostfile = @"C:\Windows\System32\drivers\etc\hosts"; + try + { + if (File.Exists(hostfile)) + { + var hosts = File.ReadAllText(hostfile).Replace("\r", ""); + var hostsList = hosts.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); + + foreach (var host in hostsList) + { + if (host.StartsWith("#")) continue; + var hostItem = host.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); + if (hostItem.Length < 2) continue; + systemHosts.Add(hostItem[1], hostItem[0]); + } + } + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + } + return systemHosts; + } + + #endregion 杂项 + + #region TempPath + + /// + /// 获取启动了应用程序的可执行文件的路径 + /// + /// + public static string GetPath(string fileName) + { + string startupPath = StartupPath(); + if (IsNullOrEmpty(fileName)) + { + return startupPath; + } + return Path.Combine(startupPath, fileName); + } + + /// + /// 获取启动了应用程序的可执行文件的路径及文件名 + /// + /// + public static string GetExePath() + { + return Environment.ProcessPath ?? string.Empty; + } + + public static string StartupPath() + { + return AppDomain.CurrentDomain.BaseDirectory; + } + + public static string GetTempPath(string filename = "") + { + string _tempPath = Path.Combine(StartupPath(), "guiTemps"); + if (!Directory.Exists(_tempPath)) + { + Directory.CreateDirectory(_tempPath); + } + if (Utils.IsNullOrEmpty(filename)) + { + return _tempPath; + } + else + { + return Path.Combine(_tempPath, filename); + } + } + + public static string UnGzip(byte[] buf) + { + using MemoryStream sb = new(); + using GZipStream input = new(new MemoryStream(buf), CompressionMode.Decompress, false); + input.CopyTo(sb); + sb.Position = 0; + return new StreamReader(sb, Encoding.UTF8).ReadToEnd(); + } + + public static string GetBackupPath(string filename) + { + string _tempPath = Path.Combine(StartupPath(), "guiBackups"); + if (!Directory.Exists(_tempPath)) + { + Directory.CreateDirectory(_tempPath); + } + return Path.Combine(_tempPath, filename); + } + + public static string GetConfigPath(string filename = "") + { + string _tempPath = Path.Combine(StartupPath(), "guiConfigs"); + if (!Directory.Exists(_tempPath)) + { + Directory.CreateDirectory(_tempPath); + } + if (Utils.IsNullOrEmpty(filename)) + { + return _tempPath; + } + else + { + return Path.Combine(_tempPath, filename); + } + } + + public static string GetBinPath(string filename, string? coreType = null) + { + string _tempPath = Path.Combine(StartupPath(), "bin"); + if (!Directory.Exists(_tempPath)) + { + Directory.CreateDirectory(_tempPath); + } + if (coreType != null) + { + _tempPath = Path.Combine(_tempPath, coreType.ToString()!); + if (!Directory.Exists(_tempPath)) + { + Directory.CreateDirectory(_tempPath); + } + } + if (Utils.IsNullOrEmpty(filename)) + { + return _tempPath; + } + else + { + return Path.Combine(_tempPath, filename); + } + } + + public static string GetLogPath(string filename = "") + { + string _tempPath = Path.Combine(StartupPath(), "guiLogs"); + if (!Directory.Exists(_tempPath)) + { + Directory.CreateDirectory(_tempPath); + } + if (Utils.IsNullOrEmpty(filename)) + { + return _tempPath; + } + else + { + return Path.Combine(_tempPath, filename); + } + } + + public static string GetFontsPath(string filename = "") + { + string _tempPath = Path.Combine(StartupPath(), "guiFonts"); + if (!Directory.Exists(_tempPath)) + { + Directory.CreateDirectory(_tempPath); + } + if (Utils.IsNullOrEmpty(filename)) + { + return _tempPath; + } + else + { + return Path.Combine(_tempPath, filename); + } + } + + #endregion TempPath + + #region 开机自动启动等 + + /// + /// 开机自动启动 + /// + /// + /// + public static void SetAutoRun(string AutoRunRegPath, string AutoRunName, bool run) + { + try + { + var autoRunName = $"{AutoRunName}_{GetMD5(StartupPath())}"; + + //delete first + RegWriteValue(AutoRunRegPath, autoRunName, ""); + if (IsAdministrator()) + { + AutoStart(autoRunName, "", ""); + } + + if (run) + { + string exePath = GetExePath(); + if (IsAdministrator()) + { + AutoStart(autoRunName, exePath, ""); + } + else + { + RegWriteValue(AutoRunRegPath, autoRunName, exePath.AppendQuotes()); + } + } + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + } + } + + public static string? RegReadValue(string path, string name, string def) + { + RegistryKey? regKey = null; + try + { + regKey = Registry.CurrentUser.OpenSubKey(path, false); + string? value = regKey?.GetValue(name) as string; + if (IsNullOrEmpty(value)) + { + return def; + } + else + { + return value; + } + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + } + finally + { + regKey?.Close(); + } + return def; + } + + public static void RegWriteValue(string path, string name, object value) + { + RegistryKey? regKey = null; + try + { + regKey = Registry.CurrentUser.CreateSubKey(path); + if (IsNullOrEmpty(value.ToString())) + { + regKey?.DeleteValue(name, false); + } + else + { + regKey?.SetValue(name, value); + } + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + } + finally + { + regKey?.Close(); + } + } + + /// + /// Auto Start via TaskService + /// + /// + /// + /// + /// + public static void AutoStart(string taskName, string fileName, string description) + { + if (Utils.IsNullOrEmpty(taskName)) + { + return; + } + string TaskName = taskName; + var logonUser = WindowsIdentity.GetCurrent().Name; + string taskDescription = description; + string deamonFileName = fileName; + + using var taskService = new TaskService(); + var tasks = taskService.RootFolder.GetTasks(new Regex(TaskName)); + foreach (var t in tasks) + { + taskService.RootFolder.DeleteTask(t.Name); + } + if (Utils.IsNullOrEmpty(fileName)) + { + return; + } + + var task = taskService.NewTask(); + task.RegistrationInfo.Description = taskDescription; + task.Settings.DisallowStartIfOnBatteries = false; + task.Settings.StopIfGoingOnBatteries = false; + task.Settings.RunOnlyIfIdle = false; + task.Settings.IdleSettings.StopOnIdleEnd = false; + task.Settings.ExecutionTimeLimit = TimeSpan.Zero; + task.Triggers.Add(new LogonTrigger { UserId = logonUser, Delay = TimeSpan.FromSeconds(10) }); + task.Principal.RunLevel = TaskRunLevel.Highest; + task.Actions.Add(new ExecAction(deamonFileName.AppendQuotes(), null, Path.GetDirectoryName(deamonFileName))); + + taskService.RootFolder.RegisterTaskDefinition(TaskName, task); + } + + public static void RemoveTunDevice() + { + try + { + var sum = MD5.HashData(Encoding.UTF8.GetBytes("wintunsingbox_tun")); + var guid = new Guid(sum); + string pnputilPath = @"C:\Windows\System32\pnputil.exe"; + string arg = $$""" /remove-device "SWD\Wintun\{{{guid}}}" """; + + // Try to remove the device + Process proc = new() + { + StartInfo = new() + { + FileName = pnputilPath, + Arguments = arg, + RedirectStandardOutput = true, + UseShellExecute = false, + CreateNoWindow = true + } + }; + + proc.Start(); + var output = proc.StandardOutput.ReadToEnd(); + proc.WaitForExit(); + } + catch + { + } + } + + #endregion 开机自动启动等 + + #region Windows API + + [Flags] + public enum DWMWINDOWATTRIBUTE : uint + { + DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19, + DWMWA_USE_IMMERSIVE_DARK_MODE = 20, + } + + [DllImport("dwmapi.dll")] + public static extern int DwmSetWindowAttribute(IntPtr hwnd, DWMWINDOWATTRIBUTE attribute, ref int attributeValue, uint attributeSize); + + #endregion Windows API } \ No newline at end of file diff --git a/v2rayN/v2rayN/Common/YamlUtils.cs b/v2rayN/v2rayN/Common/YamlUtils.cs index 3a4f9387..e5b210ee 100644 --- a/v2rayN/v2rayN/Common/YamlUtils.cs +++ b/v2rayN/v2rayN/Common/YamlUtils.cs @@ -1,58 +1,57 @@ using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; -namespace v2rayN.Common +namespace v2rayN.Common; + +internal class YamlUtils { - internal class YamlUtils + #region YAML + + /// + /// 反序列化成对象 + /// + /// + /// + /// + public static T FromYaml(string str) + { + var deserializer = new DeserializerBuilder() + .WithNamingConvention(PascalCaseNamingConvention.Instance) + .Build(); + try { - #region YAML - - /// - /// 反序列化成对象 - /// - /// - /// - /// - public static T FromYaml(string str) - { - var deserializer = new DeserializerBuilder() - .WithNamingConvention(PascalCaseNamingConvention.Instance) - .Build(); - try - { - T obj = deserializer.Deserialize(str); - return obj; - } - catch (Exception ex) - { - Logging.SaveLog("FromYaml", ex); - return deserializer.Deserialize(""); - } - } - - /// - /// 序列化 - /// - /// - /// - public static string ToYaml(Object obj) - { - var serializer = new SerializerBuilder() - .WithNamingConvention(HyphenatedNamingConvention.Instance) - .Build(); - - string result = string.Empty; - try - { - result = serializer.Serialize(obj); - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - } - return result; - } - - #endregion YAML + T obj = deserializer.Deserialize(str); + return obj; } + catch (Exception ex) + { + Logging.SaveLog("FromYaml", ex); + return deserializer.Deserialize(""); + } + } + + /// + /// 序列化 + /// + /// + /// + public static string ToYaml(Object obj) + { + var serializer = new SerializerBuilder() + .WithNamingConvention(HyphenatedNamingConvention.Instance) + .Build(); + + string result = string.Empty; + try + { + result = serializer.Serialize(obj); + } + catch (Exception ex) + { + Logging.SaveLog(ex.Message, ex); + } + return result; + } + + #endregion YAML } \ No newline at end of file diff --git a/v2rayN/v2rayN/Converters/DelayColorConverter.cs b/v2rayN/v2rayN/Converters/DelayColorConverter.cs index d65c67da..566987a3 100644 --- a/v2rayN/v2rayN/Converters/DelayColorConverter.cs +++ b/v2rayN/v2rayN/Converters/DelayColorConverter.cs @@ -1,25 +1,24 @@ using System.Windows.Data; using System.Windows.Media; -namespace v2rayN.Converters +namespace v2rayN.Converters; + +public class DelayColorConverter : IValueConverter { - public class DelayColorConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - int.TryParse(value.ToString(), out var delay); + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + int.TryParse(value.ToString(), out var delay); - if (delay <= 0) - return new SolidColorBrush(Colors.Red); - if (delay <= 500) - return new SolidColorBrush(Colors.Green); - else - return new SolidColorBrush(Colors.IndianRed); - } + if (delay <= 0) + return new SolidColorBrush(Colors.Red); + if (delay <= 500) + return new SolidColorBrush(Colors.Green); + else + return new SolidColorBrush(Colors.IndianRed); + } - public object? ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - return null; - } - } + public object? ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + return null; + } } \ No newline at end of file diff --git a/v2rayN/v2rayN/Converters/InverseBooleanConverter.cs b/v2rayN/v2rayN/Converters/InverseBooleanConverter.cs index d5809a37..5a3c688f 100644 --- a/v2rayN/v2rayN/Converters/InverseBooleanConverter.cs +++ b/v2rayN/v2rayN/Converters/InverseBooleanConverter.cs @@ -1,24 +1,23 @@ using System.Globalization; using System.Windows.Data; -namespace v2rayN.Converters +namespace v2rayN.Converters; + +[ValueConversion(typeof(bool), typeof(bool))] +public class InverseBooleanConverter : IValueConverter { - [ValueConversion(typeof(bool), typeof(bool))] - public class InverseBooleanConverter : IValueConverter + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (targetType != typeof(bool)) { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - if (targetType != typeof(bool)) - { - throw new InvalidOperationException("The target must be a boolean"); - } - - return !(bool)value; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } + throw new InvalidOperationException("The target must be a boolean"); } + + return !(bool)value; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } } \ No newline at end of file diff --git a/v2rayN/v2rayN/Converters/MaterialDesignFonts.cs b/v2rayN/v2rayN/Converters/MaterialDesignFonts.cs index 5ce03286..a9e1ad8b 100644 --- a/v2rayN/v2rayN/Converters/MaterialDesignFonts.cs +++ b/v2rayN/v2rayN/Converters/MaterialDesignFonts.cs @@ -1,27 +1,26 @@ using System.Windows.Media; using v2rayN.Handler; -namespace v2rayN.Converters -{ - public class MaterialDesignFonts - { - public static FontFamily MyFont { get; } +namespace v2rayN.Converters; - static MaterialDesignFonts() - { - try - { - var fontFamily = LazyConfig.Instance.GetConfig().uiItem.currentFontFamily; - if (!Utils.IsNullOrEmpty(fontFamily)) - { - var fontPath = Utils.GetFontsPath(); - MyFont = new FontFamily(new Uri(@$"file:///{fontPath}\"), $"./#{fontFamily}"); - } - } - catch - { - } - MyFont ??= new FontFamily("Microsoft YaHei"); - } +public class MaterialDesignFonts +{ + public static FontFamily MyFont { get; } + + static MaterialDesignFonts() + { + try + { + var fontFamily = LazyConfig.Instance.GetConfig().uiItem.currentFontFamily; + if (!Utils.IsNullOrEmpty(fontFamily)) + { + var fontPath = Utils.GetFontsPath(); + MyFont = new FontFamily(new Uri(@$"file:///{fontPath}\"), $"./#{fontFamily}"); + } } + catch + { + } + MyFont ??= new FontFamily("Microsoft YaHei"); + } } \ No newline at end of file diff --git a/v2rayN/v2rayN/Enums/EConfigType.cs b/v2rayN/v2rayN/Enums/EConfigType.cs index 60ef796a..f112e557 100644 --- a/v2rayN/v2rayN/Enums/EConfigType.cs +++ b/v2rayN/v2rayN/Enums/EConfigType.cs @@ -1,16 +1,15 @@ -namespace v2rayN.Enums +namespace v2rayN.Enums; + +public enum EConfigType { - public enum EConfigType - { - VMess = 1, - Custom = 2, - Shadowsocks = 3, - Socks = 4, - VLESS = 5, - Trojan = 6, - Hysteria2 = 7, - Tuic = 8, - Wireguard = 9, - Http = 10 - } + VMess = 1, + Custom = 2, + Shadowsocks = 3, + Socks = 4, + VLESS = 5, + Trojan = 6, + Hysteria2 = 7, + Tuic = 8, + Wireguard = 9, + Http = 10 } \ No newline at end of file diff --git a/v2rayN/v2rayN/Enums/ECoreType.cs b/v2rayN/v2rayN/Enums/ECoreType.cs index 54c07887..770c053d 100644 --- a/v2rayN/v2rayN/Enums/ECoreType.cs +++ b/v2rayN/v2rayN/Enums/ECoreType.cs @@ -1,20 +1,19 @@ -namespace v2rayN.Enums +namespace v2rayN.Enums; + +public enum ECoreType { - public enum ECoreType - { - v2fly = 1, - Xray = 2, - SagerNet = 3, - v2fly_v5 = 4, - clash = 11, - clash_meta = 12, - mihomo = 13, - hysteria = 21, - naiveproxy = 22, - tuic = 23, - sing_box = 24, - juicity = 25, - hysteria2 = 26, - v2rayN = 99 - } + v2fly = 1, + Xray = 2, + SagerNet = 3, + v2fly_v5 = 4, + clash = 11, + clash_meta = 12, + mihomo = 13, + hysteria = 21, + naiveproxy = 22, + tuic = 23, + sing_box = 24, + juicity = 25, + hysteria2 = 26, + v2rayN = 99 } \ No newline at end of file diff --git a/v2rayN/v2rayN/Enums/EGlobalHotkey.cs b/v2rayN/v2rayN/Enums/EGlobalHotkey.cs index f4a92bdb..4633d3df 100644 --- a/v2rayN/v2rayN/Enums/EGlobalHotkey.cs +++ b/v2rayN/v2rayN/Enums/EGlobalHotkey.cs @@ -1,11 +1,10 @@ -namespace v2rayN.Enums +namespace v2rayN.Enums; + +public enum EGlobalHotkey { - public enum EGlobalHotkey - { - ShowForm = 0, - SystemProxyClear = 1, - SystemProxySet = 2, - SystemProxyUnchanged = 3, - SystemProxyPac = 4, - } + ShowForm = 0, + SystemProxyClear = 1, + SystemProxySet = 2, + SystemProxyUnchanged = 3, + SystemProxyPac = 4, } \ No newline at end of file diff --git a/v2rayN/v2rayN/Enums/EInboundProtocol.cs b/v2rayN/v2rayN/Enums/EInboundProtocol.cs index 07cd1369..c483fb6e 100644 --- a/v2rayN/v2rayN/Enums/EInboundProtocol.cs +++ b/v2rayN/v2rayN/Enums/EInboundProtocol.cs @@ -1,14 +1,13 @@ -namespace v2rayN.Enums +namespace v2rayN.Enums; + +public enum EInboundProtocol { - public enum EInboundProtocol - { - socks = 0, - http, - socks2, - http2, - pac, - api, - api2, - speedtest = 21 - } + socks = 0, + http, + socks2, + http2, + pac, + api, + api2, + speedtest = 21 } \ No newline at end of file diff --git a/v2rayN/v2rayN/Enums/EMove.cs b/v2rayN/v2rayN/Enums/EMove.cs index fcbc23dc..5e77f447 100644 --- a/v2rayN/v2rayN/Enums/EMove.cs +++ b/v2rayN/v2rayN/Enums/EMove.cs @@ -1,11 +1,10 @@ -namespace v2rayN.Enums +namespace v2rayN.Enums; + +public enum EMove { - public enum EMove - { - Top = 1, - Up = 2, - Down = 3, - Bottom = 4, - Position = 5 - } + Top = 1, + Up = 2, + Down = 3, + Bottom = 4, + Position = 5 } \ No newline at end of file diff --git a/v2rayN/v2rayN/Enums/ERuleMode.cs b/v2rayN/v2rayN/Enums/ERuleMode.cs index 59a01430..c36811ca 100644 --- a/v2rayN/v2rayN/Enums/ERuleMode.cs +++ b/v2rayN/v2rayN/Enums/ERuleMode.cs @@ -1,10 +1,9 @@ -namespace v2rayN.Enums +namespace v2rayN.Enums; + +public enum ERuleMode { - public enum ERuleMode - { - Rule = 0, - Global = 1, - Direct = 2, - Unchanged = 3 - } + Rule = 0, + Global = 1, + Direct = 2, + Unchanged = 3 } \ No newline at end of file diff --git a/v2rayN/v2rayN/Enums/EServerColName.cs b/v2rayN/v2rayN/Enums/EServerColName.cs index 453dbe88..537efc84 100644 --- a/v2rayN/v2rayN/Enums/EServerColName.cs +++ b/v2rayN/v2rayN/Enums/EServerColName.cs @@ -1,21 +1,20 @@ -namespace v2rayN.Enums -{ - public enum EServerColName - { - def = 0, - configType, - remarks, - address, - port, - network, - streamSecurity, - subRemarks, - delayVal, - speedVal, +namespace v2rayN.Enums; - todayDown, - todayUp, - totalDown, - totalUp - } +public enum EServerColName +{ + def = 0, + configType, + remarks, + address, + port, + network, + streamSecurity, + subRemarks, + delayVal, + speedVal, + + todayDown, + todayUp, + totalDown, + totalUp } \ No newline at end of file diff --git a/v2rayN/v2rayN/Enums/ESpeedActionType.cs b/v2rayN/v2rayN/Enums/ESpeedActionType.cs index e0663d92..6479037c 100644 --- a/v2rayN/v2rayN/Enums/ESpeedActionType.cs +++ b/v2rayN/v2rayN/Enums/ESpeedActionType.cs @@ -1,10 +1,9 @@ -namespace v2rayN.Enums +namespace v2rayN.Enums; + +public enum ESpeedActionType { - public enum ESpeedActionType - { - Tcping, - Realping, - Speedtest, - Mixedtest - } + Tcping, + Realping, + Speedtest, + Mixedtest } \ No newline at end of file diff --git a/v2rayN/v2rayN/Enums/ESysProxyType.cs b/v2rayN/v2rayN/Enums/ESysProxyType.cs index b0857612..f41a7d6f 100644 --- a/v2rayN/v2rayN/Enums/ESysProxyType.cs +++ b/v2rayN/v2rayN/Enums/ESysProxyType.cs @@ -1,10 +1,9 @@ -namespace v2rayN.Enums +namespace v2rayN.Enums; + +public enum ESysProxyType { - public enum ESysProxyType - { - ForcedClear = 0, - ForcedChange = 1, - Unchanged = 2, - Pac = 3 - } + ForcedClear = 0, + ForcedChange = 1, + Unchanged = 2, + Pac = 3 } \ No newline at end of file diff --git a/v2rayN/v2rayN/Enums/ETransport.cs b/v2rayN/v2rayN/Enums/ETransport.cs index 349d68e7..111b76e3 100644 --- a/v2rayN/v2rayN/Enums/ETransport.cs +++ b/v2rayN/v2rayN/Enums/ETransport.cs @@ -1,15 +1,14 @@ -namespace v2rayN.Enums +namespace v2rayN.Enums; + +public enum ETransport { - public enum ETransport - { - tcp, - kcp, - ws, - httpupgrade, - splithttp, - h2, - http, - quic, - grpc - } + tcp, + kcp, + ws, + httpupgrade, + splithttp, + h2, + http, + quic, + grpc } \ No newline at end of file diff --git a/v2rayN/v2rayN/Enums/EViewAction.cs b/v2rayN/v2rayN/Enums/EViewAction.cs index 8a5a4641..1f9cde6c 100644 --- a/v2rayN/v2rayN/Enums/EViewAction.cs +++ b/v2rayN/v2rayN/Enums/EViewAction.cs @@ -1,8 +1,7 @@ -namespace v2rayN.Enums +namespace v2rayN.Enums; + +public enum EViewAction { - public enum EViewAction - { - AdjustMainLvColWidth, - ProfilesFocus - } + AdjustMainLvColWidth, + ProfilesFocus } \ No newline at end of file diff --git a/v2rayN/v2rayN/Global.cs b/v2rayN/v2rayN/Global.cs index 1bbd9fef..2100deb0 100644 --- a/v2rayN/v2rayN/Global.cs +++ b/v2rayN/v2rayN/Global.cs @@ -1,197 +1,196 @@ using v2rayN.Enums; -namespace v2rayN +namespace v2rayN; + +internal class Global { - internal class Global - { - #region const + #region const - public const string GithubUrl = "https://github.com"; - public const string GithubApiUrl = "https://api.github.com/repos"; - public const string V2flyCoreUrl = "https://github.com/v2fly/v2ray-core/releases"; - public const string XrayCoreUrl = "https://github.com/XTLS/Xray-core/releases"; - public const string SagerNetCoreUrl = "https://github.com/SagerNet/v2ray-core/releases"; - public const string NUrl = @"https://github.com/2dust/v2rayN/releases"; - public const string ClashCoreUrl = "https://github.com/Dreamacro/clash/releases"; - public const string ClashMetaCoreUrl = "https://github.com/MetaCubeX/Clash.Meta/releases"; - public const string MihomoCoreUrl = "https://github.com/MetaCubeX/mihomo/releases"; - public const string HysteriaCoreUrl = "https://github.com/apernet/hysteria/releases"; - public const string NaiveproxyCoreUrl = "https://github.com/klzgrad/naiveproxy/releases"; - public const string TuicCoreUrl = "https://github.com/EAimTY/tuic/releases"; - public const string SingboxCoreUrl = "https://github.com/SagerNet/sing-box/releases"; - public const string GeoUrl = "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/{0}.dat"; - public const string SpeedPingTestUrl = @"https://www.google.com/generate_204"; - public const string JuicityCoreUrl = "https://github.com/juicity/juicity/releases"; - public const string CustomRoutingListUrl = @"https://raw.githubusercontent.com/2dust/v2rayCustomRoutingList/master/"; - public const string SingboxRulesetUrl = @"https://raw.githubusercontent.com/2dust/sing-box-rules/rule-set-{0}/{1}.srs"; + public const string GithubUrl = "https://github.com"; + public const string GithubApiUrl = "https://api.github.com/repos"; + public const string V2flyCoreUrl = "https://github.com/v2fly/v2ray-core/releases"; + public const string XrayCoreUrl = "https://github.com/XTLS/Xray-core/releases"; + public const string SagerNetCoreUrl = "https://github.com/SagerNet/v2ray-core/releases"; + public const string NUrl = @"https://github.com/2dust/v2rayN/releases"; + public const string ClashCoreUrl = "https://github.com/Dreamacro/clash/releases"; + public const string ClashMetaCoreUrl = "https://github.com/MetaCubeX/Clash.Meta/releases"; + public const string MihomoCoreUrl = "https://github.com/MetaCubeX/mihomo/releases"; + public const string HysteriaCoreUrl = "https://github.com/apernet/hysteria/releases"; + public const string NaiveproxyCoreUrl = "https://github.com/klzgrad/naiveproxy/releases"; + public const string TuicCoreUrl = "https://github.com/EAimTY/tuic/releases"; + public const string SingboxCoreUrl = "https://github.com/SagerNet/sing-box/releases"; + public const string GeoUrl = "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/{0}.dat"; + public const string SpeedPingTestUrl = @"https://www.google.com/generate_204"; + public const string JuicityCoreUrl = "https://github.com/juicity/juicity/releases"; + public const string CustomRoutingListUrl = @"https://raw.githubusercontent.com/2dust/v2rayCustomRoutingList/master/"; + public const string SingboxRulesetUrl = @"https://raw.githubusercontent.com/2dust/sing-box-rules/rule-set-{0}/{1}.srs"; - public const string PromotionUrl = @"aHR0cHM6Ly85LjIzNDQ1Ni54eXovYWJjLmh0bWw="; - public const string ConfigFileName = "guiNConfig.json"; - public const string CoreConfigFileName = "config.json"; - public const string CorePreConfigFileName = "configPre.json"; - public const string CoreSpeedtestConfigFileName = "configSpeedtest.json"; - public const string CoreMultipleLoadConfigFileName = "configMultipleLoad.json"; - public const string ClashMixinConfigFileName = "Mixin.yaml"; - public const string V2raySampleClient = "v2rayN.Sample.SampleClientConfig"; - public const string SingboxSampleClient = "v2rayN.Sample.SingboxSampleClientConfig"; - public const string V2raySampleHttpRequestFileName = "v2rayN.Sample.SampleHttpRequest"; - public const string V2raySampleHttpResponseFileName = "v2rayN.Sample.SampleHttpResponse"; - public const string V2raySampleInbound = "v2rayN.Sample.SampleInbound"; - public const string V2raySampleOutbound = "v2rayN.Sample.SampleOutbound"; - public const string SingboxSampleOutbound = "v2rayN.Sample.SingboxSampleOutbound"; - public const string CustomRoutingFileName = "v2rayN.Sample.custom_routing_"; - public const string TunSingboxDNSFileName = "v2rayN.Sample.tun_singbox_dns"; - public const string TunSingboxInboundFileName = "v2rayN.Sample.tun_singbox_inbound"; - public const string TunSingboxRulesFileName = "v2rayN.Sample.tun_singbox_rules"; - public const string DNSV2rayNormalFileName = "v2rayN.Sample.dns_v2ray_normal"; - public const string DNSSingboxNormalFileName = "v2rayN.Sample.dns_singbox_normal"; - public const string ClashMixinYaml = "v2rayN.Sample.clash_mixin_yaml"; - public const string ClashTunYaml = "v2rayN.Sample.clash_tun_yaml"; + public const string PromotionUrl = @"aHR0cHM6Ly85LjIzNDQ1Ni54eXovYWJjLmh0bWw="; + public const string ConfigFileName = "guiNConfig.json"; + public const string CoreConfigFileName = "config.json"; + public const string CorePreConfigFileName = "configPre.json"; + public const string CoreSpeedtestConfigFileName = "configSpeedtest.json"; + public const string CoreMultipleLoadConfigFileName = "configMultipleLoad.json"; + public const string ClashMixinConfigFileName = "Mixin.yaml"; + public const string V2raySampleClient = "v2rayN.Sample.SampleClientConfig"; + public const string SingboxSampleClient = "v2rayN.Sample.SingboxSampleClientConfig"; + public const string V2raySampleHttpRequestFileName = "v2rayN.Sample.SampleHttpRequest"; + public const string V2raySampleHttpResponseFileName = "v2rayN.Sample.SampleHttpResponse"; + public const string V2raySampleInbound = "v2rayN.Sample.SampleInbound"; + public const string V2raySampleOutbound = "v2rayN.Sample.SampleOutbound"; + public const string SingboxSampleOutbound = "v2rayN.Sample.SingboxSampleOutbound"; + public const string CustomRoutingFileName = "v2rayN.Sample.custom_routing_"; + public const string TunSingboxDNSFileName = "v2rayN.Sample.tun_singbox_dns"; + public const string TunSingboxInboundFileName = "v2rayN.Sample.tun_singbox_inbound"; + public const string TunSingboxRulesFileName = "v2rayN.Sample.tun_singbox_rules"; + public const string DNSV2rayNormalFileName = "v2rayN.Sample.dns_v2ray_normal"; + public const string DNSSingboxNormalFileName = "v2rayN.Sample.dns_singbox_normal"; + public const string ClashMixinYaml = "v2rayN.Sample.clash_mixin_yaml"; + public const string ClashTunYaml = "v2rayN.Sample.clash_tun_yaml"; - public const string DefaultSecurity = "auto"; - public const string DefaultNetwork = "tcp"; - public const string TcpHeaderHttp = "http"; - public const string None = "none"; - public const string ProxyTag = "proxy"; - public const string DirectTag = "direct"; - public const string BlockTag = "block"; - public const string StreamSecurity = "tls"; - public const string StreamSecurityReality = "reality"; - public const string Loopback = "127.0.0.1"; - public const string InboundAPIProtocol = "dokodemo-door"; - public const string HttpProtocol = "http://"; - public const string HttpsProtocol = "https://"; + public const string DefaultSecurity = "auto"; + public const string DefaultNetwork = "tcp"; + public const string TcpHeaderHttp = "http"; + public const string None = "none"; + public const string ProxyTag = "proxy"; + public const string DirectTag = "direct"; + public const string BlockTag = "block"; + public const string StreamSecurity = "tls"; + public const string StreamSecurityReality = "reality"; + public const string Loopback = "127.0.0.1"; + public const string InboundAPIProtocol = "dokodemo-door"; + public const string HttpProtocol = "http://"; + public const string HttpsProtocol = "https://"; - public const string UserEMail = "t@t.tt"; - public const string AutoRunRegPath = @"Software\Microsoft\Windows\CurrentVersion\Run"; - public const string AutoRunName = "v2rayNAutoRun"; - public const string CustomIconName = "v2rayN.ico"; - public const string IEProxyExceptions = "localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*"; - public const string RoutingRuleComma = ""; - public const string GrpcGunMode = "gun"; - public const string GrpcMultiMode = "multi"; - public const int MaxPort = 65536; - public const string CommandClearMsg = "CommandClearMsg"; - public const string CommandSendMsgView = "CommandSendMsgView"; - public const string CommandStopSpeedTest = "CommandStopSpeedTest"; - public const string CommandRefreshProfiles = "CommandRefreshProfiles"; - public const string DelayUnit = ""; - public const string SpeedUnit = ""; - public const int MinFontSize = 10; - public const string RebootAs = "rebootas"; + public const string UserEMail = "t@t.tt"; + public const string AutoRunRegPath = @"Software\Microsoft\Windows\CurrentVersion\Run"; + public const string AutoRunName = "v2rayNAutoRun"; + public const string CustomIconName = "v2rayN.ico"; + public const string IEProxyExceptions = "localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*"; + public const string RoutingRuleComma = ""; + public const string GrpcGunMode = "gun"; + public const string GrpcMultiMode = "multi"; + public const int MaxPort = 65536; + public const string CommandClearMsg = "CommandClearMsg"; + public const string CommandSendMsgView = "CommandSendMsgView"; + public const string CommandStopSpeedTest = "CommandStopSpeedTest"; + public const string CommandRefreshProfiles = "CommandRefreshProfiles"; + public const string DelayUnit = ""; + public const string SpeedUnit = ""; + public const int MinFontSize = 10; + public const string RebootAs = "rebootas"; - public static readonly List IEProxyProtocols = new() { - "{ip}:{http_port}", - "socks={ip}:{socks_port}", - "http={ip}:{http_port};https={ip}:{http_port};ftp={ip}:{http_port};socks={ip}:{socks_port}", - "http=http://{ip}:{http_port};https=http://{ip}:{http_port}", - "" - }; + public static readonly List IEProxyProtocols = new() { + "{ip}:{http_port}", + "socks={ip}:{socks_port}", + "http={ip}:{http_port};https={ip}:{http_port};ftp={ip}:{http_port};socks={ip}:{socks_port}", + "http=http://{ip}:{http_port};https=http://{ip}:{http_port}", + "" + }; - public static readonly List SubConvertUrls = new List { - @"https://sub.xeton.dev/sub?url={0}", - @"https://api.dler.io/sub?url={0}", - @"http://127.0.0.1:25500/sub?url={0}", - "" - }; + public static readonly List SubConvertUrls = new List { + @"https://sub.xeton.dev/sub?url={0}", + @"https://api.dler.io/sub?url={0}", + @"http://127.0.0.1:25500/sub?url={0}", + "" + }; - public static readonly List SubConvertConfig = new List { - @"https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online.ini" - }; + public static readonly List SubConvertConfig = new List { + @"https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online.ini" + }; - public static readonly List SubConvertTargets = new List { - "", - "mixed", - "v2ray", - "clash", - "ss", - }; + public static readonly List SubConvertTargets = new List { + "", + "mixed", + "v2ray", + "clash", + "ss", + }; - public static readonly List SpeedTestUrls = new() { - @"https://speed.cloudflare.com/__down?bytes=100000000", - @"https://speed.cloudflare.com/__down?bytes=10000000", - @"http://cachefly.cachefly.net/50mb.test", - @"http://cachefly.cachefly.net/10mb.test" - }; + public static readonly List SpeedTestUrls = new() { + @"https://speed.cloudflare.com/__down?bytes=100000000", + @"https://speed.cloudflare.com/__down?bytes=10000000", + @"http://cachefly.cachefly.net/50mb.test", + @"http://cachefly.cachefly.net/10mb.test" + }; - public static readonly List SpeedPingTestUrls = new() { - @"https://www.google.com/generate_204", - @"https://www.apple.com/library/test/success.html", - @"http://www.msftconnecttest.com/connecttest.txt", - }; + public static readonly List SpeedPingTestUrls = new() { + @"https://www.google.com/generate_204", + @"https://www.apple.com/library/test/success.html", + @"http://www.msftconnecttest.com/connecttest.txt", + }; - public static readonly Dictionary UserAgentTexts = new() - { - {"chrome","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36" }, - {"firefox","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0" }, - {"safari","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15" }, - {"edge","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.70" }, - {"none",""} - }; + public static readonly Dictionary UserAgentTexts = new() + { + {"chrome","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36" }, + {"firefox","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0" }, + {"safari","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15" }, + {"edge","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.70" }, + {"none",""} + }; - public const string Hysteria2ProtocolShare = "hy2://"; + public const string Hysteria2ProtocolShare = "hy2://"; - public static readonly Dictionary ProtocolShares = new() - { - {EConfigType.VMess,"vmess://"}, - {EConfigType.Shadowsocks,"ss://"}, - {EConfigType.Socks,"socks://"}, - {EConfigType.VLESS,"vless://"}, - {EConfigType.Trojan,"trojan://"}, - {EConfigType.Hysteria2,"hysteria2://"}, - {EConfigType.Tuic,"tuic://"}, - {EConfigType.Wireguard,"wireguard://"} - }; + public static readonly Dictionary ProtocolShares = new() + { + {EConfigType.VMess,"vmess://"}, + {EConfigType.Shadowsocks,"ss://"}, + {EConfigType.Socks,"socks://"}, + {EConfigType.VLESS,"vless://"}, + {EConfigType.Trojan,"trojan://"}, + {EConfigType.Hysteria2,"hysteria2://"}, + {EConfigType.Tuic,"tuic://"}, + {EConfigType.Wireguard,"wireguard://"} + }; - public static readonly Dictionary ProtocolTypes = new() - { - {EConfigType.VMess,"vmess"}, - {EConfigType.Shadowsocks,"shadowsocks"}, - {EConfigType.Socks,"socks"}, - {EConfigType.Http,"http"}, - {EConfigType.VLESS,"vless"}, - {EConfigType.Trojan,"trojan"}, - {EConfigType.Hysteria2,"hysteria2"}, - {EConfigType.Tuic,"tuic"}, - {EConfigType.Wireguard,"wireguard"} - }; + public static readonly Dictionary ProtocolTypes = new() + { + {EConfigType.VMess,"vmess"}, + {EConfigType.Shadowsocks,"shadowsocks"}, + {EConfigType.Socks,"socks"}, + {EConfigType.Http,"http"}, + {EConfigType.VLESS,"vless"}, + {EConfigType.Trojan,"trojan"}, + {EConfigType.Hysteria2,"hysteria2"}, + {EConfigType.Tuic,"tuic"}, + {EConfigType.Wireguard,"wireguard"} + }; - public static readonly List VmessSecurities = new() { "aes-128-gcm", "chacha20-poly1305", "auto", "none", "zero" }; - public static readonly List SsSecurities = new() { "aes-256-gcm", "aes-128-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305", "none", "plain" }; - public static readonly List SsSecuritiesInSagerNet = new() { "none", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305", "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", "xchacha20-ietf-poly1305", "rc4", "rc4-md5", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "aes-128-cfb8", "aes-192-cfb8", "aes-256-cfb8", "aes-128-ofb", "aes-192-ofb", "aes-256-ofb", "bf-cfb", "cast5-cfb", "des-cfb", "idea-cfb", "rc2-cfb", "seed-cfb", "camellia-128-cfb", "camellia-192-cfb", "camellia-256-cfb", "camellia-128-cfb8", "camellia-192-cfb8", "camellia-256-cfb8", "salsa20", "chacha20", "chacha20-ietf", "xchacha20" }; - public static readonly List SsSecuritiesInXray = new() { "aes-256-gcm", "aes-128-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305", "xchacha20-poly1305", "xchacha20-ietf-poly1305", "none", "plain", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305" }; - public static readonly List SsSecuritiesInSingbox = new() { "aes-256-gcm", "aes-192-gcm", "aes-128-gcm", "chacha20-ietf-poly1305", "xchacha20-ietf-poly1305", "none", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "rc4-md5", "chacha20-ietf", "xchacha20" }; - public static readonly List Flows = new() { "", "xtls-rprx-vision", "xtls-rprx-vision-udp443" }; - public static readonly List Networks = new() { "tcp", "kcp", "ws", "httpupgrade", "splithttp", "h2", "quic", "grpc" }; - public static readonly List KcpHeaderTypes = new() { "srtp", "utp", "wechat-video", "dtls", "wireguard" }; - public static readonly List CoreTypes = new() { "v2fly", "SagerNet", "Xray", "sing_box" }; - public static readonly List CoreTypes4VLESS = new() { "Xray", "sing_box" }; - public static readonly List DomainStrategies = new() { "AsIs", "IPIfNonMatch", "IPOnDemand" }; - public static readonly List DomainStrategies4Singbox = new() { "ipv4_only", "ipv6_only", "prefer_ipv4", "prefer_ipv6", "" }; - public static readonly List DomainMatchers = new() { "linear", "mph", "" }; - public static readonly List Fingerprints = new() { "chrome", "firefox", "safari", "ios", "android", "edge", "360", "qq", "random", "randomized", "" }; - public static readonly List UserAgent = new() { "chrome", "firefox", "safari", "edge", "none" }; + public static readonly List VmessSecurities = new() { "aes-128-gcm", "chacha20-poly1305", "auto", "none", "zero" }; + public static readonly List SsSecurities = new() { "aes-256-gcm", "aes-128-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305", "none", "plain" }; + public static readonly List SsSecuritiesInSagerNet = new() { "none", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305", "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", "xchacha20-ietf-poly1305", "rc4", "rc4-md5", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "aes-128-cfb8", "aes-192-cfb8", "aes-256-cfb8", "aes-128-ofb", "aes-192-ofb", "aes-256-ofb", "bf-cfb", "cast5-cfb", "des-cfb", "idea-cfb", "rc2-cfb", "seed-cfb", "camellia-128-cfb", "camellia-192-cfb", "camellia-256-cfb", "camellia-128-cfb8", "camellia-192-cfb8", "camellia-256-cfb8", "salsa20", "chacha20", "chacha20-ietf", "xchacha20" }; + public static readonly List SsSecuritiesInXray = new() { "aes-256-gcm", "aes-128-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305", "xchacha20-poly1305", "xchacha20-ietf-poly1305", "none", "plain", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305" }; + public static readonly List SsSecuritiesInSingbox = new() { "aes-256-gcm", "aes-192-gcm", "aes-128-gcm", "chacha20-ietf-poly1305", "xchacha20-ietf-poly1305", "none", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "rc4-md5", "chacha20-ietf", "xchacha20" }; + public static readonly List Flows = new() { "", "xtls-rprx-vision", "xtls-rprx-vision-udp443" }; + public static readonly List Networks = new() { "tcp", "kcp", "ws", "httpupgrade", "splithttp", "h2", "quic", "grpc" }; + public static readonly List KcpHeaderTypes = new() { "srtp", "utp", "wechat-video", "dtls", "wireguard" }; + public static readonly List CoreTypes = new() { "v2fly", "SagerNet", "Xray", "sing_box" }; + public static readonly List CoreTypes4VLESS = new() { "Xray", "sing_box" }; + public static readonly List DomainStrategies = new() { "AsIs", "IPIfNonMatch", "IPOnDemand" }; + public static readonly List DomainStrategies4Singbox = new() { "ipv4_only", "ipv6_only", "prefer_ipv4", "prefer_ipv6", "" }; + public static readonly List DomainMatchers = new() { "linear", "mph", "" }; + public static readonly List Fingerprints = new() { "chrome", "firefox", "safari", "ios", "android", "edge", "360", "qq", "random", "randomized", "" }; + public static readonly List UserAgent = new() { "chrome", "firefox", "safari", "edge", "none" }; - public static readonly List AllowInsecure = new() { "true", "false", "" }; - public static readonly List DomainStrategy4Freedoms = new() { "AsIs", "UseIP", "UseIPv4", "UseIPv6", "" }; - public static readonly List SingboxDomainStrategy4Out = new() { "ipv4_only", "prefer_ipv4", "prefer_ipv6", "ipv6_only", "" }; - public static readonly List Languages = new() { "zh-Hans", "zh-Hant", "en", "fa-Ir", "ru" }; - public static readonly List Alpns = new() { "h3", "h2", "http/1.1", "h3,h2,http/1.1", "h3,h2", "h2,http/1.1", "" }; - public static readonly List LogLevels = new() { "debug", "info", "warning", "error", "none" }; - public static readonly List InboundTags = new() { "socks", "http", "socks2", "http2" }; - public static readonly List RuleProtocols = new() { "http", "tls", "bittorrent" }; - public static readonly List RuleNetworks = new() { "", "tcp", "udp", "tcp,udp" }; - public static readonly List destOverrideProtocols = ["http", "tls", "quic", "fakedns", "fakedns+others"]; - public static readonly List TunMtus = new() { "1280", "1408", "1500", "9000" }; - public static readonly List TunStacks = new() { "gvisor", "system" }; - public static readonly List PresetMsgFilters = new() { "proxy", "direct", "block", "" }; - public static readonly List SingboxMuxs = new() { "h2mux", "smux", "yamux", "" }; - public static readonly List TuicCongestionControls = new() { "cubic", "new_reno", "bbr" }; + public static readonly List AllowInsecure = new() { "true", "false", "" }; + public static readonly List DomainStrategy4Freedoms = new() { "AsIs", "UseIP", "UseIPv4", "UseIPv6", "" }; + public static readonly List SingboxDomainStrategy4Out = new() { "ipv4_only", "prefer_ipv4", "prefer_ipv6", "ipv6_only", "" }; + public static readonly List Languages = new() { "zh-Hans", "zh-Hant", "en", "fa-Ir", "ru" }; + public static readonly List Alpns = new() { "h3", "h2", "http/1.1", "h3,h2,http/1.1", "h3,h2", "h2,http/1.1", "" }; + public static readonly List LogLevels = new() { "debug", "info", "warning", "error", "none" }; + public static readonly List InboundTags = new() { "socks", "http", "socks2", "http2" }; + public static readonly List RuleProtocols = new() { "http", "tls", "bittorrent" }; + public static readonly List RuleNetworks = new() { "", "tcp", "udp", "tcp,udp" }; + public static readonly List destOverrideProtocols = ["http", "tls", "quic", "fakedns", "fakedns+others"]; + public static readonly List TunMtus = new() { "1280", "1408", "1500", "9000" }; + public static readonly List TunStacks = new() { "gvisor", "system" }; + public static readonly List PresetMsgFilters = new() { "proxy", "direct", "block", "" }; + public static readonly List SingboxMuxs = new() { "h2mux", "smux", "yamux", "" }; + public static readonly List TuicCongestionControls = new() { "cubic", "new_reno", "bbr" }; - public static readonly List allowSelectType = new List { "selector", "urltest", "loadbalance", "fallback" }; - public static readonly List notAllowTestType = new List { "selector", "urltest", "direct", "reject", "compatible", "pass", "loadbalance", "fallback" }; - public static readonly List proxyVehicleType = new List { "file", "http" }; + public static readonly List allowSelectType = new List { "selector", "urltest", "loadbalance", "fallback" }; + public static readonly List notAllowTestType = new List { "selector", "urltest", "direct", "reject", "compatible", "pass", "loadbalance", "fallback" }; + public static readonly List proxyVehicleType = new List { "file", "http" }; - #endregion const - } + #endregion const } \ No newline at end of file diff --git a/v2rayN/v2rayN/Properties/Resources.Designer.cs b/v2rayN/v2rayN/Properties/Resources.Designer.cs index 24b5f9dd..18205e8d 100644 --- a/v2rayN/v2rayN/Properties/Resources.Designer.cs +++ b/v2rayN/v2rayN/Properties/Resources.Designer.cs @@ -8,216 +8,214 @@ // //------------------------------------------------------------------------------ -namespace v2rayN.Properties { - using System; - - - /// - /// 一个强类型的资源类,用于查找本地化的字符串等。 - /// - // 此类是由 StronglyTypedResourceBuilder - // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 - // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen - // (以 /str 作为命令选项),或重新生成 VS 项目。 - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// 返回此类使用的缓存的 ResourceManager 实例。 - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("v2rayN.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// 重写当前线程的 CurrentUICulture 属性,对 - /// 使用此强类型资源类的所有资源查找执行重写。 - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// 查找 System.Drawing.Bitmap 类型的本地化资源。 - /// - internal static System.Drawing.Bitmap about { - get { - object obj = ResourceManager.GetObject("about", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// 查找 System.Drawing.Bitmap 类型的本地化资源。 - /// - internal static System.Drawing.Bitmap active { - get { - object obj = ResourceManager.GetObject("active", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// 查找 System.Drawing.Bitmap 类型的本地化资源。 - /// - internal static System.Drawing.Bitmap checkupdate { - get { - object obj = ResourceManager.GetObject("checkupdate", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// 查找 System.Drawing.Bitmap 类型的本地化资源。 - /// - internal static System.Drawing.Bitmap help { - get { - object obj = ResourceManager.GetObject("help", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// 查找 System.Drawing.Bitmap 类型的本地化资源。 - /// - internal static System.Drawing.Bitmap minimize { - get { - object obj = ResourceManager.GetObject("minimize", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// 查找 System.Drawing.Bitmap 类型的本地化资源。 - /// - internal static System.Drawing.Bitmap notify { - get { - object obj = ResourceManager.GetObject("notify", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// 查找类似于 (图标) 的 System.Drawing.Icon 类型的本地化资源。 - /// - internal static System.Drawing.Icon NotifyIcon1 { - get { - object obj = ResourceManager.GetObject("NotifyIcon1", resourceCulture); - return ((System.Drawing.Icon)(obj)); - } - } - - /// - /// 查找类似于 (图标) 的 System.Drawing.Icon 类型的本地化资源。 - /// - internal static System.Drawing.Icon NotifyIcon2 { - get { - object obj = ResourceManager.GetObject("NotifyIcon2", resourceCulture); - return ((System.Drawing.Icon)(obj)); - } - } - - /// - /// 查找类似于 (图标) 的 System.Drawing.Icon 类型的本地化资源。 - /// - internal static System.Drawing.Icon NotifyIcon3 { - get { - object obj = ResourceManager.GetObject("NotifyIcon3", resourceCulture); - return ((System.Drawing.Icon)(obj)); - } - } - - /// - /// 查找 System.Drawing.Bitmap 类型的本地化资源。 - /// - internal static System.Drawing.Bitmap option { - get { - object obj = ResourceManager.GetObject("option", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// 查找 System.Drawing.Bitmap 类型的本地化资源。 - /// - internal static System.Drawing.Bitmap promotion { - get { - object obj = ResourceManager.GetObject("promotion", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// 查找 System.Drawing.Bitmap 类型的本地化资源。 - /// - internal static System.Drawing.Bitmap restart { - get { - object obj = ResourceManager.GetObject("restart", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// 查找 System.Drawing.Bitmap 类型的本地化资源。 - /// - internal static System.Drawing.Bitmap server { - get { - object obj = ResourceManager.GetObject("server", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// 查找 System.Drawing.Bitmap 类型的本地化资源。 - /// - internal static System.Drawing.Bitmap share { - get { - object obj = ResourceManager.GetObject("share", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// 查找 System.Drawing.Bitmap 类型的本地化资源。 - /// - internal static System.Drawing.Bitmap speedtest { - get { - object obj = ResourceManager.GetObject("speedtest", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// 查找 System.Drawing.Bitmap 类型的本地化资源。 - /// - internal static System.Drawing.Bitmap sub { - get { - object obj = ResourceManager.GetObject("sub", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } +namespace v2rayN.Properties; + + +/// +/// 一个强类型的资源类,用于查找本地化的字符串等。 +/// +// 此类是由 StronglyTypedResourceBuilder +// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 +// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen +// (以 /str 作为命令选项),或重新生成 VS 项目。 +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] +[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] +[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] +internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("v2rayN.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性,对 + /// 使用此强类型资源类的所有资源查找执行重写。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap about { + get { + object obj = ResourceManager.GetObject("about", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap active { + get { + object obj = ResourceManager.GetObject("active", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap checkupdate { + get { + object obj = ResourceManager.GetObject("checkupdate", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap help { + get { + object obj = ResourceManager.GetObject("help", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap minimize { + get { + object obj = ResourceManager.GetObject("minimize", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap notify { + get { + object obj = ResourceManager.GetObject("notify", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找类似于 (图标) 的 System.Drawing.Icon 类型的本地化资源。 + /// + internal static System.Drawing.Icon NotifyIcon1 { + get { + object obj = ResourceManager.GetObject("NotifyIcon1", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + + /// + /// 查找类似于 (图标) 的 System.Drawing.Icon 类型的本地化资源。 + /// + internal static System.Drawing.Icon NotifyIcon2 { + get { + object obj = ResourceManager.GetObject("NotifyIcon2", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + + /// + /// 查找类似于 (图标) 的 System.Drawing.Icon 类型的本地化资源。 + /// + internal static System.Drawing.Icon NotifyIcon3 { + get { + object obj = ResourceManager.GetObject("NotifyIcon3", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap option { + get { + object obj = ResourceManager.GetObject("option", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap promotion { + get { + object obj = ResourceManager.GetObject("promotion", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap restart { + get { + object obj = ResourceManager.GetObject("restart", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap server { + get { + object obj = ResourceManager.GetObject("server", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap share { + get { + object obj = ResourceManager.GetObject("share", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap speedtest { + get { + object obj = ResourceManager.GetObject("speedtest", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap sub { + get { + object obj = ResourceManager.GetObject("sub", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } } diff --git a/v2rayN/v2rayUpgrade/MainForm.cs b/v2rayN/v2rayUpgrade/MainForm.cs index 39f8196c..9a2361b2 100644 --- a/v2rayN/v2rayUpgrade/MainForm.cs +++ b/v2rayN/v2rayUpgrade/MainForm.cs @@ -5,143 +5,142 @@ using System.IO.Compression; using System.Text; using System.Windows.Forms; -namespace v2rayUpgrade +namespace v2rayUpgrade; + +public partial class MainForm : Form { - public partial class MainForm : Form + private readonly string defaultFilename = "v2ray-windows.zip"; + private string? fileName; + + public MainForm(string[] args) + { + InitializeComponent(); + if (args.Length > 0) { - private readonly string defaultFilename = "v2ray-windows.zip"; - private string? fileName; - - public MainForm(string[] args) - { - InitializeComponent(); - if (args.Length > 0) - { - fileName = Uri.UnescapeDataString(string.Join(" ", args)); - } - else - { - fileName = defaultFilename; - } - } - - private void ShowWarn(string message) - { - MessageBox.Show(message, "", MessageBoxButtons.OK, MessageBoxIcon.Warning); - } - - private void btnOK_Click(object sender, EventArgs e) - { - try - { - Process[] existing = Process.GetProcessesByName("v2rayN"); - foreach (Process p in existing) - { - string? path = p.MainModule?.FileName; - if (path == GetPath("v2rayN.exe")) - { - p.Kill(); - p.WaitForExit(100); - } - } - } - catch (Exception ex) - { - // Access may be denied without admin right. The user may not be an administrator. - ShowWarn("Failed to close v2rayN(关闭v2rayN失败).\n" + - "Close it manually, or the upgrade may fail.(请手动关闭正在运行的v2rayN,否则可能升级失败。\n\n" + ex.StackTrace); - } - - if (!File.Exists(fileName)) - { - if (File.Exists(defaultFilename)) - { - fileName = defaultFilename; - } - else - { - ShowWarn("Upgrade Failed, File Not Exist(升级失败,文件不存在)."); - return; - } - } - - StringBuilder sb = new(); - try - { - string thisAppOldFile = $"{Application.ExecutablePath}.tmp"; - File.Delete(thisAppOldFile); - string startKey = "v2rayN/"; - - using ZipArchive archive = ZipFile.OpenRead(fileName); - foreach (ZipArchiveEntry entry in archive.Entries) - { - try - { - if (entry.Length == 0) - { - continue; - } - string fullName = entry.FullName; - if (fullName.StartsWith(startKey)) - { - fullName = fullName[startKey.Length..]; - } - if (string.Equals(Application.ExecutablePath, GetPath(fullName), StringComparison.OrdinalIgnoreCase)) - { - File.Move(Application.ExecutablePath, thisAppOldFile); - } - - string entryOutputPath = GetPath(fullName); - Directory.CreateDirectory(Path.GetDirectoryName(entryOutputPath)!); - entry.ExtractToFile(entryOutputPath, true); - } - catch (Exception ex) - { - sb.Append(ex.StackTrace); - } - } - } - catch (Exception ex) - { - ShowWarn("Upgrade Failed(升级失败)." + ex.StackTrace); - return; - } - if (sb.Length > 0) - { - ShowWarn("Upgrade Failed,Hold ctrl + c to copy to clipboard.\n" + - "(升级失败,按住ctrl+c可以复制到剪贴板)." + sb.ToString()); - return; - } - - Process.Start("v2rayN.exe"); - MessageBox.Show("Upgrade successed(升级成功)", "", MessageBoxButtons.OK, MessageBoxIcon.Information); - - Close(); - } - - private void btnClose_Click(object sender, EventArgs e) - { - Close(); - } - - public static string GetExePath() - { - return Application.ExecutablePath; - } - - public static string StartupPath() - { - return Application.StartupPath; - } - - public static string GetPath(string fileName) - { - string startupPath = StartupPath(); - if (string.IsNullOrEmpty(fileName)) - { - return startupPath; - } - return Path.Combine(startupPath, fileName); - } + fileName = Uri.UnescapeDataString(string.Join(" ", args)); } -} + else + { + fileName = defaultFilename; + } + } + + private void ShowWarn(string message) + { + MessageBox.Show(message, "", MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + + private void btnOK_Click(object sender, EventArgs e) + { + try + { + Process[] existing = Process.GetProcessesByName("v2rayN"); + foreach (Process p in existing) + { + string? path = p.MainModule?.FileName; + if (path == GetPath("v2rayN.exe")) + { + p.Kill(); + p.WaitForExit(100); + } + } + } + catch (Exception ex) + { + // Access may be denied without admin right. The user may not be an administrator. + ShowWarn("Failed to close v2rayN(关闭v2rayN失败).\n" + + "Close it manually, or the upgrade may fail.(请手动关闭正在运行的v2rayN,否则可能升级失败。\n\n" + ex.StackTrace); + } + + if (!File.Exists(fileName)) + { + if (File.Exists(defaultFilename)) + { + fileName = defaultFilename; + } + else + { + ShowWarn("Upgrade Failed, File Not Exist(升级失败,文件不存在)."); + return; + } + } + + StringBuilder sb = new(); + try + { + string thisAppOldFile = $"{Application.ExecutablePath}.tmp"; + File.Delete(thisAppOldFile); + string startKey = "v2rayN/"; + + using ZipArchive archive = ZipFile.OpenRead(fileName); + foreach (ZipArchiveEntry entry in archive.Entries) + { + try + { + if (entry.Length == 0) + { + continue; + } + string fullName = entry.FullName; + if (fullName.StartsWith(startKey)) + { + fullName = fullName[startKey.Length..]; + } + if (string.Equals(Application.ExecutablePath, GetPath(fullName), StringComparison.OrdinalIgnoreCase)) + { + File.Move(Application.ExecutablePath, thisAppOldFile); + } + + string entryOutputPath = GetPath(fullName); + Directory.CreateDirectory(Path.GetDirectoryName(entryOutputPath)!); + entry.ExtractToFile(entryOutputPath, true); + } + catch (Exception ex) + { + sb.Append(ex.StackTrace); + } + } + } + catch (Exception ex) + { + ShowWarn("Upgrade Failed(升级失败)." + ex.StackTrace); + return; + } + if (sb.Length > 0) + { + ShowWarn("Upgrade Failed,Hold ctrl + c to copy to clipboard.\n" + + "(升级失败,按住ctrl+c可以复制到剪贴板)." + sb.ToString()); + return; + } + + Process.Start("v2rayN.exe"); + MessageBox.Show("Upgrade successed(升级成功)", "", MessageBoxButtons.OK, MessageBoxIcon.Information); + + Close(); + } + + private void btnClose_Click(object sender, EventArgs e) + { + Close(); + } + + public static string GetExePath() + { + return Application.ExecutablePath; + } + + public static string StartupPath() + { + return Application.StartupPath; + } + + public static string GetPath(string fileName) + { + string startupPath = StartupPath(); + if (string.IsNullOrEmpty(fileName)) + { + return startupPath; + } + return Path.Combine(startupPath, fileName); + } +} \ No newline at end of file diff --git a/v2rayN/v2rayUpgrade/Program.cs b/v2rayN/v2rayUpgrade/Program.cs index bc4303de..e95663db 100644 --- a/v2rayN/v2rayUpgrade/Program.cs +++ b/v2rayN/v2rayUpgrade/Program.cs @@ -1,21 +1,20 @@ using System; using System.Windows.Forms; -namespace v2rayUpgrade +namespace v2rayUpgrade; + +internal static class Program { - internal static class Program - { - /// - /// 应用程序的主入口点。 - /// - [STAThread] - private static void Main(string[] args) - { - Application.EnableVisualStyles(); - Application.SetHighDpiMode(HighDpiMode.SystemAware); - Application.SetHighDpiMode(HighDpiMode.PerMonitorV2); - Application.SetCompatibleTextRenderingDefault(false); - Application.Run(new MainForm(args)); - } - } + /// + /// 应用程序的主入口点。 + /// + [STAThread] + private static void Main(string[] args) + { + Application.EnableVisualStyles(); + Application.SetHighDpiMode(HighDpiMode.SystemAware); + Application.SetHighDpiMode(HighDpiMode.PerMonitorV2); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm(args)); + } } \ No newline at end of file