Compare commits

...

22 Commits
6.12 ... 6.13

Author SHA1 Message Date
2dust
aac2b4aaf0 up 6.13 2023-02-19 15:44:52 +08:00
2dust
fe070b306f Merge pull request #3309 from ilyfairy/master
改为可空类型, 简化代码
2023-02-19 15:33:25 +08:00
2dust
ecfadf8a23 Merge branch 'master' into master 2023-02-19 15:23:04 +08:00
2dust
653af71596 Add log switch in tun mode 2023-02-19 14:55:44 +08:00
小仙女
6a89be2e89 简化代码 2023-02-19 13:34:22 +08:00
小仙女
b84bad4e1a 改为可空类型 2023-02-19 12:18:08 +08:00
2dust
0f8d86f081 Refactoring sorting and delayed storage 2023-02-19 11:23:45 +08:00
2dust
d44f311ba1 Refactoring sorting and delayed storage 2023-02-19 10:43:42 +08:00
2dust
6f5428ca61 Merge pull request #3306 from Weltolk/master
语句更通顺
2023-02-19 09:59:47 +08:00
2dust
b0bee3ca1a Merge pull request #3305 from ilyfairy/master
优化, 改成使用语法糖
2023-02-19 09:59:30 +08:00
2dust
7908194d27 Merge pull request #3301 from meaqese/add-russian-language
full-russian-support
2023-02-18 20:07:57 +08:00
小仙女
b27c7fb2dd string.Join的第二个参数(List<string>)改成ToArray 2023-02-17 22:06:17 +08:00
小仙女
a23cb95a10 性能优化 2023-02-17 15:17:01 +08:00
小仙女
fc137f9b1c 语句更通顺 2023-02-17 15:09:26 +08:00
Weltolk
84780bf9ef Update ResUI.zh-Hans.resx 2023-02-17 14:39:59 +08:00
小仙女
1321037c52 优化, 改成使用语法糖 2023-02-17 14:36:28 +08:00
meaqese
de1da12d45 full-russian-support 2023-02-17 03:18:41 +03:00
2dust
6d4cbacd50 GenerateSatelliteAssembliesForCore 2023-02-15 20:48:56 +08:00
2dust
bf9f7ca990 Adjust the group style 2023-02-15 20:47:17 +08:00
2dust
ca334104d7 bug fixes 2023-02-15 20:37:51 +08:00
2dust
c3e00ba31b bug fixes 2023-02-15 20:37:27 +08:00
2dust
ea3a9cc70e ShowInTaskbar = false 2023-02-15 20:36:50 +08:00
58 changed files with 1297 additions and 1194 deletions

View File

@@ -6,14 +6,10 @@ namespace v2rayN.Base
{
internal class DownloaderHelper
{
private static readonly Lazy<DownloaderHelper> _instance = new Lazy<DownloaderHelper>(() => new());
private static readonly Lazy<DownloaderHelper> _instance = new(() => new());
public static DownloaderHelper Instance => _instance.Value;
public DownloaderHelper()
{
}
public async Task<string> DownloadStringAsync(IWebProxy webProxy, string url, string? userAgent, int timeout)
public async Task<string?> DownloadStringAsync(IWebProxy webProxy, string url, string? userAgent, int timeout)
{
if (string.IsNullOrEmpty(url))
{
@@ -23,7 +19,7 @@ namespace v2rayN.Base
var cancellationToken = new CancellationTokenSource();
cancellationToken.CancelAfter(timeout * 1000);
Uri uri = new Uri(url);
Uri uri = new(url);
//Authorization Header
var headers = new WebHeaderCollection();
if (!Utils.IsNullOrEmpty(uri.UserInfo))
@@ -44,28 +40,20 @@ namespace v2rayN.Base
}
};
string text = string.Empty;
using (var downloader = new DownloadService(downloadOpt))
using var downloader = new DownloadService(downloadOpt);
downloader.DownloadFileCompleted += (sender, value) =>
{
downloader.DownloadFileCompleted += (sender, value) =>
if (value.Error != null)
{
if (value.Error != null)
{
throw new Exception(string.Format("{0}", value.Error.Message));
}
};
using (var stream = await downloader.DownloadFileTaskAsync(address: url, cancellationToken: cancellationToken.Token))
{
using (StreamReader reader = new StreamReader(stream))
{
text = reader.ReadToEnd();
}
throw new Exception(string.Format("{0}", value.Error.Message));
}
}
};
using var stream = await downloader.DownloadFileTaskAsync(address: url, cancellationToken: cancellationToken.Token);
using StreamReader reader = new(stream);
downloadOpt = null;
return text;
return reader.ReadToEnd();
}
@@ -73,7 +61,7 @@ namespace v2rayN.Base
{
if (string.IsNullOrEmpty(url))
{
throw new ArgumentNullException("url");
throw new ArgumentNullException(nameof(url));
}
var cancellationToken = new CancellationTokenSource();
@@ -94,44 +82,42 @@ namespace v2rayN.Base
int totalSecond = 0;
var hasValue = false;
double maxSpeed = 0;
using (var downloader = new DownloadService(downloadOpt))
using var downloader = new DownloadService(downloadOpt);
//downloader.DownloadStarted += (sender, value) =>
//{
// if (progress != null)
// {
// progress.Report("Start download data...");
// }
//};
downloader.DownloadProgressChanged += (sender, value) =>
{
//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)
{
TimeSpan ts = (DateTime.Now - totalDatetime);
if (progress != null && ts.Seconds > totalSecond)
hasValue = true;
totalSecond = ts.Seconds;
if (value.BytesPerSecondSpeed > maxSpeed)
{
hasValue = true;
totalSecond = ts.Seconds;
if (value.BytesPerSecondSpeed > maxSpeed)
{
maxSpeed = value.BytesPerSecondSpeed;
var speed = (maxSpeed / 1000 / 1000).ToString("#0.0");
progress.Report(speed);
}
maxSpeed = value.BytesPerSecondSpeed;
var speed = (maxSpeed / 1000 / 1000).ToString("#0.0");
progress.Report(speed);
}
};
downloader.DownloadFileCompleted += (sender, value) =>
}
};
downloader.DownloadFileCompleted += (sender, value) =>
{
if (progress != null)
{
if (progress != null)
if (!hasValue && value.Error != null)
{
if (!hasValue && value.Error != null)
{
progress.Report(value.Error?.Message);
}
progress.Report(value.Error?.Message);
}
};
progress.Report("......");
}
};
progress.Report("......");
await downloader.DownloadFileTaskAsync(address: url, cancellationToken: cancellationToken.Token);
}
await downloader.DownloadFileTaskAsync(address: url, cancellationToken: cancellationToken.Token);
downloadOpt = null;
}
@@ -140,11 +126,11 @@ namespace v2rayN.Base
{
if (string.IsNullOrEmpty(url))
{
throw new ArgumentNullException("url");
throw new ArgumentNullException(nameof(url));
}
if (string.IsNullOrEmpty(fileName))
{
throw new ArgumentNullException("fileName");
throw new ArgumentNullException(nameof(fileName));
}
if (File.Exists(fileName))
{
@@ -167,38 +153,33 @@ namespace v2rayN.Base
var progressPercentage = 0;
var hasValue = false;
using (var downloader = new DownloadService(downloadOpt))
using var downloader = new DownloadService(downloadOpt);
downloader.DownloadStarted += (sender, value) =>
{
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)
{
if (progress != null)
{
progress.Report(0);
}
};
downloader.DownloadProgressChanged += (sender, value) =>
progressPercentage = percent;
progress.Report(percent);
}
};
downloader.DownloadFileCompleted += (sender, value) =>
{
if (progress != null)
{
hasValue = true;
var percent = (int)value.ProgressPercentage;// Convert.ToInt32((totalRead * 1d) / (total * 1d) * 100);
if (progressPercentage != percent && percent % 10 == 0)
if (hasValue && value.Error == null)
{
progressPercentage = percent;
progress.Report(percent);
progress.Report(101);
}
};
downloader.DownloadFileCompleted += (sender, value) =>
{
if (progress != null)
{
if (hasValue && value.Error == null)
{
progress.Report(101);
}
}
};
}
};
await downloader.DownloadFileTaskAsync(url, fileName, cancellationToken: cancellationToken.Token);
}
await downloader.DownloadFileTaskAsync(url, fileName, cancellationToken: cancellationToken.Token);
downloadOpt = null;
}

View File

@@ -26,14 +26,14 @@ namespace v2rayN.Base
}
else
{
HttpClientHelper httpClientHelper = new HttpClientHelper();
HttpClientHelper httpClientHelper = new();
HttpClientHandler handler = new HttpClientHandler() { UseCookies = false };
HttpClientHandler handler = new() { UseCookies = false };
httpClientHelper.httpClient = new HttpClient(handler);
return httpClientHelper;
}
}
public async Task<string> GetAsync(string url)
public async Task<string?> GetAsync(string url)
{
if (string.IsNullOrEmpty(url))
{
@@ -43,7 +43,7 @@ namespace v2rayN.Base
return await response.Content.ReadAsStringAsync();
}
public async Task<string> GetAsync(HttpClient client, string url, CancellationToken token)
public async Task<string?> GetAsync(HttpClient client, string url, CancellationToken token)
{
if (string.IsNullOrEmpty(url))
{
@@ -54,7 +54,7 @@ namespace v2rayN.Base
{
throw new Exception(string.Format("{0}", response.StatusCode));
}
return await response.Content.ReadAsStringAsync();
return await response.Content.ReadAsStringAsync(token);
}
public async Task PutAsync(string url, Dictionary<string, string> headers)
@@ -71,11 +71,11 @@ namespace v2rayN.Base
{
if (string.IsNullOrEmpty(url))
{
throw new ArgumentNullException("url");
throw new ArgumentNullException(nameof(url));
}
if (string.IsNullOrEmpty(fileName))
{
throw new ArgumentNullException("fileName");
throw new ArgumentNullException(nameof(fileName));
}
if (File.Exists(fileName))
{
@@ -89,56 +89,51 @@ namespace v2rayN.Base
throw new Exception(string.Format("{0}", response.StatusCode));
}
var total = response.Content.Headers.ContentLength.HasValue ? response.Content.Headers.ContentLength.Value : -1L;
var total = response.Content.Headers.ContentLength ?? -1L;
var canReportProgress = total != -1 && progress != null;
using (var stream = await response.Content.ReadAsStreamAsync())
using var stream = await response.Content.ReadAsStreamAsync(token);
using var file = File.Create(fileName);
var totalRead = 0L;
var buffer = new byte[1024 * 1024];
var isMoreToRead = true;
var progressPercentage = 0;
do
{
using (var file = File.Create(fileName))
token.ThrowIfCancellationRequested();
var read = await stream.ReadAsync(buffer, token);
if (read == 0)
{
var totalRead = 0L;
var buffer = new byte[1024 * 1024];
var isMoreToRead = true;
var progressPercentage = 0;
isMoreToRead = false;
}
else
{
var data = new byte[read];
buffer.ToList().CopyTo(0, data, 0, read);
do
{
token.ThrowIfCancellationRequested();
// TODO: put here the code to write the file to disk
file.Write(data, 0, read);
var read = await stream.ReadAsync(buffer, 0, buffer.Length, token);
totalRead += read;
if (read == 0)
{
isMoreToRead = false;
}
else
{
var data = new byte[read];
buffer.ToList().CopyTo(0, data, 0, read);
// TODO: put here the code to write the file to disk
file.Write(data, 0, read);
totalRead += read;
if (canReportProgress)
{
var percent = Convert.ToInt32((totalRead * 1d) / (total * 1d) * 100);
if (progressPercentage != percent && percent % 10 == 0)
{
progressPercentage = percent;
progress.Report(percent);
}
}
}
} while (isMoreToRead);
file.Close();
if (canReportProgress)
{
progress.Report(101);
var percent = Convert.ToInt32((totalRead * 1d) / (total * 1d) * 100);
if (progressPercentage != percent && percent % 10 == 0)
{
progressPercentage = percent;
progress.Report(percent);
}
}
}
} while (isMoreToRead);
if (canReportProgress)
{
progress.Report(101);
}
}
@@ -146,7 +141,7 @@ namespace v2rayN.Base
{
if (string.IsNullOrEmpty(url))
{
throw new ArgumentNullException("url");
throw new ArgumentNullException(nameof(url));
}
var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token);
@@ -159,57 +154,55 @@ namespace v2rayN.Base
//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())
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
{
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 (token.IsCancellationRequested)
if (totalRead > 0)
{
if (totalRead > 0)
{
return;
}
else
{
token.ThrowIfCancellationRequested();
}
}
var read = await stream.ReadAsync(buffer, 0, buffer.Length, token);
if (read == 0)
{
isMoreToRead = false;
return;
}
else
{
var data = new byte[read];
buffer.ToList().CopyTo(0, data, 0, read);
token.ThrowIfCancellationRequested();
}
}
// TODO:
totalRead += read;
var read = await stream.ReadAsync(buffer, token);
TimeSpan ts = (DateTime.Now - totalDatetime);
if (progress != null && ts.Seconds > totalSecond)
if (read == 0)
{
isMoreToRead = false;
}
else
{
var data = new byte[read];
buffer.ToList().CopyTo(0, data, 0, read);
// TODO:
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)
{
totalSecond = ts.Seconds;
var speed = (totalRead * 1d / ts.TotalMilliseconds / 1000).ToString("#0.0");
if (progressSpeed != speed)
{
progressSpeed = speed;
progress.Report(speed);
}
progressSpeed = speed;
progress.Report(speed);
}
}
} while (isMoreToRead);
}
}
} while (isMoreToRead);
}
}

View File

@@ -6,7 +6,7 @@ namespace v2rayN.Base
{
public sealed class SqliteHelper
{
private static readonly Lazy<SqliteHelper> _instance = new Lazy<SqliteHelper>(() => new());
private static readonly Lazy<SqliteHelper> _instance = new(() => new());
public static SqliteHelper Instance => _instance.Value;
private string _connstr;
public SQLiteConnection _db;

View File

@@ -34,7 +34,7 @@ namespace v2rayN.Base
public static IEnumerable<string> NonWhiteSpaceLines(this TextReader reader)
{
string line;
string? line;
while ((line = reader.ReadLine()) != null)
{
if (line.IsWhiteSpace()) continue;

View File

@@ -17,7 +17,7 @@ namespace v2rayN.Converters
return new SolidColorBrush(Colors.IndianRed);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
public object? ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}

View File

@@ -21,10 +21,7 @@ namespace v2rayN.Converters
catch
{
}
if (MyFont is null)
{
MyFont = new FontFamily("Microsoft YaHei");
}
MyFont ??= new FontFamily("Microsoft YaHei");
}
}
}

View File

@@ -80,26 +80,26 @@
public const string SpeedUnit = "";
public const int MinFontSize = 10;
public static readonly List<string> IEProxyProtocols = new List<string> {
public static readonly List<string> 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<string> vmessSecuritys = new List<string> { "aes-128-gcm", "chacha20-poly1305", "auto", "none", "zero" };
public static readonly List<string> ssSecuritys = new List<string> { "aes-256-gcm", "aes-128-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305", "none", "plain" };
public static readonly List<string> ssSecuritysInSagerNet = new List<string> { "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<string> ssSecuritysInXray = new List<string> { "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<string> xtlsFlows = new List<string> { "", "xtls-rprx-origin", "xtls-rprx-origin-udp443", "xtls-rprx-direct", "xtls-rprx-direct-udp443", "xtls-rprx-vision", "xtls-rprx-vision-udp443" };
public static readonly List<string> networks = new List<string> { "tcp", "kcp", "ws", "h2", "quic", "grpc" };
public static readonly List<string> kcpHeaderTypes = new List<string> { "srtp", "utp", "wechat-video", "dtls", "wireguard" };
public static readonly List<string> coreTypes = new List<string> { "v2fly", "SagerNet", "Xray", "v2fly_v5" };
public static readonly List<string> domainStrategys = new List<string> { "AsIs", "IPIfNonMatch", "IPOnDemand" };
public static readonly List<string> domainMatchers = new List<string> { "linear", "mph", "" };
public static readonly List<string> fingerprints = new List<string> { "chrome", "firefox", "safari", "ios", "android", "edge", "360", "qq", "random", "randomized", "" };
public static readonly List<string> userAgent = new List<string> { "chrome", "firefox", "safari", "edge", "none" };
public static readonly Dictionary<string, string> userAgentTxt = new Dictionary<string, string>
public static readonly List<string> vmessSecuritys = new() { "aes-128-gcm", "chacha20-poly1305", "auto", "none", "zero" };
public static readonly List<string> ssSecuritys = new() { "aes-256-gcm", "aes-128-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305", "none", "plain" };
public static readonly List<string> ssSecuritysInSagerNet = 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<string> ssSecuritysInXray = 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<string> xtlsFlows = new() { "", "xtls-rprx-origin", "xtls-rprx-origin-udp443", "xtls-rprx-direct", "xtls-rprx-direct-udp443", "xtls-rprx-vision", "xtls-rprx-vision-udp443" };
public static readonly List<string> networks = new() { "tcp", "kcp", "ws", "h2", "quic", "grpc" };
public static readonly List<string> kcpHeaderTypes = new() { "srtp", "utp", "wechat-video", "dtls", "wireguard" };
public static readonly List<string> coreTypes = new() { "v2fly", "SagerNet", "Xray", "v2fly_v5" };
public static readonly List<string> domainStrategys = new() { "AsIs", "IPIfNonMatch", "IPOnDemand" };
public static readonly List<string> domainMatchers = new() { "linear", "mph", "" };
public static readonly List<string> fingerprints = new() { "chrome", "firefox", "safari", "ios", "android", "edge", "360", "qq", "random", "randomized", "" };
public static readonly List<string> userAgent = new() { "chrome", "firefox", "safari", "edge", "none" };
public static readonly Dictionary<string, string> userAgentTxt = 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" },
@@ -107,17 +107,17 @@
{"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 List<string> allowInsecures = new List<string> { "true", "false", "" };
public static readonly List<string> domainStrategy4Freedoms = new List<string> { "AsIs", "UseIP", "UseIPv4", "UseIPv6", "" };
public static readonly List<string> Languages = new List<string> { "zh-Hans", "en", "fa-Ir", "ru" };
public static readonly List<string> alpns = new List<string> { "h2", "http/1.1", "h2,http/1.1", "" };
public static readonly List<string> LogLevel = new List<string> { "debug", "info", "warning", "error", "none" };
public static readonly List<string> InboundTags = new List<string> { "socks", "http", "socks2", "http2" };
public static readonly List<string> Protocols = new List<string> { "http", "tls", "bittorrent" };
public static readonly List<string> TunMtus = new List<string> { "9000", "1500" };
public static readonly List<string> TunStacks = new List<string> { "gvisor", "system" };
public static readonly List<string> PresetMsgFilters = new List<string> { "proxy", "direct", "block", "" };
public static readonly List<string> SpeedTestUrls = new List<string> { @"http://cachefly.cachefly.net/100mb.test", @"http://cachefly.cachefly.net/10mb.test" };
public static readonly List<string> allowInsecures = new() { "true", "false", "" };
public static readonly List<string> domainStrategy4Freedoms = new() { "AsIs", "UseIP", "UseIPv4", "UseIPv6", "" };
public static readonly List<string> Languages = new() { "zh-Hans", "en", "fa-Ir", "ru" };
public static readonly List<string> alpns = new() { "h2", "http/1.1", "h2,http/1.1", "" };
public static readonly List<string> LogLevel = new() { "debug", "info", "warning", "error", "none" };
public static readonly List<string> InboundTags = new() { "socks", "http", "socks2", "http2" };
public static readonly List<string> Protocols = new() { "http", "tls", "bittorrent" };
public static readonly List<string> TunMtus = new() { "9000", "1500" };
public static readonly List<string> TunStacks = new() { "gvisor", "system" };
public static readonly List<string> PresetMsgFilters = new() { "proxy", "direct", "block", "" };
public static readonly List<string> SpeedTestUrls = new() { @"http://cachefly.cachefly.net/100mb.test", @"http://cachefly.cachefly.net/10mb.test" };
#endregion

View File

@@ -13,7 +13,7 @@ namespace v2rayN.Handler
class ConfigHandler
{
private static string configRes = Global.ConfigFileName;
private static readonly object objLock = new object();
private static readonly object objLock = new();
#region ConfigHandler
@@ -61,7 +61,7 @@ namespace v2rayN.Handler
if (config.inbound == null)
{
config.inbound = new List<InItem>();
InItem inItem = new InItem
InItem inItem = new()
{
protocol = Global.InboundSocks,
localPort = 10808,
@@ -190,7 +190,7 @@ namespace v2rayN.Handler
config.speedTestItem.speedPingTestUrl = Global.SpeedPingTestUrl;
}
if (config.guiItem.statisticsFreshRate > 100 || config.guiItem.statisticsFreshRate < 1)
if (config.guiItem.statisticsFreshRate is > 100 or < 1)
{
config.guiItem.statisticsFreshRate = 1;
}
@@ -205,7 +205,7 @@ namespace v2rayN.Handler
}
LazyConfig.Instance.SetConfig(ref config);
LazyConfig.Instance.SetConfig(config);
return 0;
}
/// <summary>
@@ -438,14 +438,14 @@ namespace v2rayN.Handler
/// <param name="config"></param>
/// <param name="item"></param>
/// <returns></returns>
public static int SetDefaultServer(ref Config config, ProfileItem item)
public static int SetDefaultServerIndex(ref Config config, string? indexId)
{
if (item == null)
if (Utils.IsNullOrEmpty(indexId))
{
return -1;
}
config.indexId = item.indexId;
config.indexId = indexId;
Global.reloadCore = true;
ToJsonFile(config);
@@ -453,34 +453,34 @@ namespace v2rayN.Handler
return 0;
}
public static int SetDefaultServer(Config config, List<ProfileItem> lstProfile)
public static int SetDefaultServer(Config config, List<ProfileItemModel> lstProfile)
{
if (lstProfile.Exists(t => t.indexId == config.indexId))
{
return 0;
}
if (SqliteHelper.Instance.Table<ProfileItem>().Where(t => t.indexId == config.indexId).Count() > 0)
var allItems = LazyConfig.Instance.ProfileItemIndexs("");
if (allItems.Where(t => t == config.indexId).Any())
{
return 0;
}
if (lstProfile.Count > 0)
{
return SetDefaultServer(ref config, lstProfile[0]);
return SetDefaultServerIndex(ref config, lstProfile[0].indexId);
}
if (SqliteHelper.Instance.Table<ProfileItem>().Count() > 0)
if (allItems.Count > 0)
{
return SetDefaultServer(ref config, SqliteHelper.Instance.Table<ProfileItem>().FirstOrDefault());
return SetDefaultServerIndex(ref config, allItems.FirstOrDefault());
}
return -1;
}
public static ProfileItem GetDefaultServer(ref Config config)
public static ProfileItem? GetDefaultServer(ref Config config)
{
var item = LazyConfig.Instance.GetProfileItem(config.indexId);
if (item is null)
{
var item2 = SqliteHelper.Instance.Table<ProfileItem>().FirstOrDefault();
SetDefaultServer(ref config, item2);
SetDefaultServerIndex(ref config, item2?.indexId);
return item2;
}
@@ -505,9 +505,10 @@ namespace v2rayN.Handler
for (int i = 0; i < lstProfile.Count; i++)
{
lstProfile[i].sort = (i + 1) * 10;
ProfileExHandler.Instance.SetSort(lstProfile[i].indexId, (i + 1) * 10);
}
var sort = 0;
switch (eMove)
{
case EMove.Top:
@@ -516,7 +517,7 @@ namespace v2rayN.Handler
{
return 0;
}
lstProfile[index].sort = lstProfile[0].sort - 1;
sort = ProfileExHandler.Instance.GetSort(lstProfile[0].indexId) - 1;
break;
}
@@ -526,7 +527,7 @@ namespace v2rayN.Handler
{
return 0;
}
lstProfile[index].sort = lstProfile[index - 1].sort - 1;
sort = ProfileExHandler.Instance.GetSort(lstProfile[index - 1].indexId) - 1;
break;
}
@@ -537,7 +538,7 @@ namespace v2rayN.Handler
{
return 0;
}
lstProfile[index].sort = lstProfile[index + 1].sort + 1;
sort = ProfileExHandler.Instance.GetSort(lstProfile[index + 1].indexId) + 1;
break;
}
@@ -547,18 +548,16 @@ namespace v2rayN.Handler
{
return 0;
}
lstProfile[index].sort = lstProfile[lstProfile.Count - 1].sort + 1;
sort = ProfileExHandler.Instance.GetSort(lstProfile[^1].indexId) + 1;
break;
}
case EMove.Position:
lstProfile[index].sort = pos * 10 + 1;
sort = pos * 10 + 1;
break;
}
SqliteHelper.Instance.UpdateAll(lstProfile);
ProfileExHandler.Instance.SetSort(lstProfile[index].indexId, sort);
return 0;
}
@@ -698,11 +697,29 @@ namespace v2rayN.Handler
public static int SortServers(ref Config config, string subId, EServerColName name, bool asc)
{
var lstModel = LazyConfig.Instance.ProfileItems(subId, "");
var lstProfile = Utils.FromJson<List<ProfileItem>>(Utils.ToJson(lstModel));
if (lstProfile.Count <= 0)
if (lstModel.Count <= 0)
{
return -1;
}
var lstProfileExs = ProfileExHandler.Instance.ProfileExs;
var lstProfile = (from t in lstModel
join t3 in lstProfileExs on t.indexId equals t3.indexId into t3b
from t33 in t3b.DefaultIfEmpty()
select new ProfileItemModel
{
indexId = t.indexId,
configType = t.configType,
remarks = t.remarks,
address = t.address,
port = t.port,
security = t.security,
network = t.network,
streamSecurity = t.streamSecurity,
delay = t33 == null ? 0 : t33.delay,
speed = t33 == null ? 0 : t33.speed,
sort = t33 == null ? 0 : t33.sort
}).ToList();
var propertyName = string.Empty;
switch (name)
{
@@ -736,7 +753,7 @@ namespace v2rayN.Handler
}
for (int i = 0; i < lstProfile.Count; i++)
{
lstProfile[i].sort = (i + 1) * 10;
ProfileExHandler.Instance.SetSort(lstProfile[i].indexId, (i + 1) * 10);
}
if (name == EServerColName.delay)
{
@@ -745,7 +762,7 @@ namespace v2rayN.Handler
{
if (item.delay <= 0)
{
item.sort = maxSort;
ProfileExHandler.Instance.SetSort(item.indexId, maxSort);
}
}
}
@@ -756,13 +773,11 @@ namespace v2rayN.Handler
{
if (item.speed <= 0)
{
item.sort = maxSort;
ProfileExHandler.Instance.SetSort(item.indexId, maxSort);
}
}
}
SqliteHelper.Instance.UpdateAll(lstProfile);
return 0;
}
@@ -795,7 +810,7 @@ namespace v2rayN.Handler
List<ProfileItem> source = lstProfile;
bool keepOlder = config.guiItem.keepOlderDedupl;
List<ProfileItem> list = new List<ProfileItem>();
List<ProfileItem> list = new();
if (!keepOlder) source.Reverse(); // Remove the early items first
foreach (ProfileItem item in source)
@@ -830,15 +845,8 @@ namespace v2rayN.Handler
if (Utils.IsNullOrEmpty(profileItem.indexId))
{
profileItem.indexId = Utils.GetGUID(false);
if (profileItem.sort <= 0)
{
var maxSort = 0;
if (SqliteHelper.Instance.Table<ProfileItem>().Count() > 0)
{
maxSort = SqliteHelper.Instance.Table<ProfileItem>().Max(t => t == null ? 0 : t.sort);
}
profileItem.sort = maxSort + 1;
}
var maxSort = ProfileExHandler.Instance.GetMaxSort();
ProfileExHandler.Instance.SetSort(profileItem.indexId, maxSort + 1);
}
else if (profileItem.indexId == config.indexId)
{
@@ -929,11 +937,11 @@ namespace v2rayN.Handler
}
int countServers = 0;
var maxSort = 0;
if (SqliteHelper.Instance.Table<ProfileItem>().Count() > 0)
{
maxSort = SqliteHelper.Instance.Table<ProfileItem>().Max(t => t.sort);
}
//var maxSort = 0;
//if (SqliteHelper.Instance.Table<ProfileItem>().Count() > 0)
//{
// maxSort = SqliteHelper.Instance.Table<ProfileItem>().Max(t => t.sort);
//}
string[] arrData = clipboardData.Split(Environment.NewLine.ToCharArray());
foreach (string str in arrData)
{
@@ -971,7 +979,7 @@ namespace v2rayN.Handler
}
profileItem.subid = subid;
profileItem.isSub = isSub;
profileItem.sort = maxSort + countServers + 1;
//profileItem.sort = maxSort + countServers + 1;
if (profileItem.configType == EConfigType.VMess)
{
@@ -1021,9 +1029,19 @@ namespace v2rayN.Handler
return -1;
}
ProfileItem profileItem = new ProfileItem();
//判断str是否包含s的任意一个字符串
static bool Containss(string str, params string[] s)
{
foreach (var item in s)
{
if (str.Contains(item, StringComparison.OrdinalIgnoreCase)) return true;
}
return false;
}
ProfileItem profileItem = new();
//Is v2ray configuration
V2rayConfig v2rayConfig = Utils.FromJson<V2rayConfig>(clipboardData);
V2rayConfig? v2rayConfig = Utils.FromJson<V2rayConfig>(clipboardData);
if (v2rayConfig != null
&& v2rayConfig.inbounds != null
&& v2rayConfig.inbounds.Count > 0
@@ -1038,9 +1056,7 @@ namespace v2rayN.Handler
profileItem.remarks = "v2ray_custom";
}
//Is Clash configuration
else if (clipboardData.IndexOf("port") >= 0
&& clipboardData.IndexOf("socks-port") >= 0
&& clipboardData.IndexOf("proxies") >= 0)
else if (Containss(clipboardData, "port", "socks-port", "proxies"))
{
var fileName = Utils.GetTempPath($"{Utils.GetGUID(false)}.yaml");
File.WriteAllText(fileName, clipboardData);
@@ -1050,12 +1066,7 @@ namespace v2rayN.Handler
profileItem.remarks = "clash_custom";
}
//Is hysteria configuration
else if (clipboardData.IndexOf("server") >= 0
&& clipboardData.IndexOf("up") >= 0
&& clipboardData.IndexOf("down") >= 0
&& clipboardData.IndexOf("listen") >= 0
&& clipboardData.IndexOf("<html>") < 0
&& clipboardData.IndexOf("<body>") < 0)
else if (Containss(clipboardData, "server", "up", "down", "listen", "<html>", "<body>"))
{
var fileName = Utils.GetTempPath($"{Utils.GetGUID(false)}.json");
File.WriteAllText(fileName, clipboardData);
@@ -1065,10 +1076,7 @@ namespace v2rayN.Handler
profileItem.remarks = "hysteria_custom";
}
//Is naiveproxy configuration
else if (clipboardData.IndexOf("listen") >= 0
&& clipboardData.IndexOf("proxy") >= 0
&& clipboardData.IndexOf("<html>") < 0
&& clipboardData.IndexOf("<body>") < 0)
else if (Containss(clipboardData, "listen", "proxy", "<html>", "<body>"))
{
var fileName = Utils.GetTempPath($"{Utils.GetGUID(false)}.json");
File.WriteAllText(fileName, clipboardData);
@@ -1168,7 +1176,7 @@ namespace v2rayN.Handler
public static int AddBatchServers(ref Config config, string clipboardData, string subid, bool isSub)
{
List<ProfileItem> lstOriSub = null;
List<ProfileItem>? lstOriSub = null;
if (isSub && !Utils.IsNullOrEmpty(subid))
{
lstOriSub = LazyConfig.Instance.ProfileItems(subid);
@@ -1213,7 +1221,7 @@ namespace v2rayN.Handler
return 0;
}
SubItem subItem = new SubItem
SubItem subItem = new()
{
id = string.Empty,
remarks = "import_sub",

View File

@@ -25,7 +25,7 @@ namespace v2rayN.Handler
/// <param name="msg"></param>
/// <param name="content"></param>
/// <returns></returns>
public static int GenerateClientConfig(ProfileItem node, string fileName, out string msg, out string content)
public static int GenerateClientConfig(ProfileItem node, string? fileName, out string msg, out string content)
{
content = string.Empty;
try
@@ -43,7 +43,7 @@ namespace v2rayN.Handler
}
else
{
V2rayConfig v2rayConfig = null;
V2rayConfig? v2rayConfig = null;
if (GenerateClientConfigContent(node, false, ref v2rayConfig, out msg) != 0)
{
return -1;
@@ -90,8 +90,8 @@ namespace v2rayN.Handler
{
var dtNow = DateTime.Now;
v2rayConfig.log.loglevel = config.coreBasicItem.loglevel;
v2rayConfig.log.access = Utils.GetLogPath($"Vaccess_{dtNow.ToString("yyyy-MM-dd")}.txt");
v2rayConfig.log.error = Utils.GetLogPath($"Verror_{dtNow.ToString("yyyy-MM-dd")}.txt");
v2rayConfig.log.access = Utils.GetLogPath($"Vaccess_{dtNow:yyyy-MM-dd}.txt");
v2rayConfig.log.error = Utils.GetLogPath($"Verror_{dtNow:yyyy-MM-dd}.txt");
}
else
{
@@ -114,11 +114,11 @@ namespace v2rayN.Handler
{
v2rayConfig.inbounds = new List<Inbounds>();
Inbounds inbound = GetInbound(config.inbound[0], Global.InboundSocks, 0, true);
Inbounds? inbound = GetInbound(config.inbound[0], Global.InboundSocks, 0, true);
v2rayConfig.inbounds.Add(inbound);
//http
Inbounds inbound2 = GetInbound(config.inbound[0], Global.InboundHttp, 1, false);
Inbounds? inbound2 = GetInbound(config.inbound[0], Global.InboundHttp, 1, false);
v2rayConfig.inbounds.Add(inbound2);
if (config.inbound[0].allowLANConn)
@@ -157,7 +157,7 @@ namespace v2rayN.Handler
return 0;
}
private static Inbounds GetInbound(InItem inItem, string tag, int offset, bool bSocks)
private static Inbounds? GetInbound(InItem inItem, string tag, int offset, bool bSocks)
{
string result = Utils.GetEmbedText(Global.v2raySampleInbound);
if (Utils.IsNullOrEmpty(result))
@@ -405,7 +405,7 @@ namespace v2rayN.Handler
if (!Utils.IsNullOrEmpty(node.security)
&& !Utils.IsNullOrEmpty(node.id))
{
SocksUsersItem socksUsersItem = new SocksUsersItem
SocksUsersItem socksUsersItem = new()
{
user = node.security,
pass = node.id,
@@ -565,7 +565,7 @@ namespace v2rayN.Handler
{
streamSettings.security = node.streamSecurity;
TlsSettings tlsSettings = new TlsSettings
TlsSettings tlsSettings = new()
{
allowInsecure = Utils.ToBool(node.allowInsecure.IsNullOrEmpty() ? config.coreBasicItem.defAllowInsecure.ToString().ToLower() : node.allowInsecure),
alpn = node.GetAlpn(),
@@ -587,7 +587,7 @@ namespace v2rayN.Handler
{
streamSettings.security = node.streamSecurity;
TlsSettings xtlsSettings = new TlsSettings
TlsSettings xtlsSettings = new()
{
allowInsecure = Utils.ToBool(node.allowInsecure.IsNullOrEmpty() ? config.coreBasicItem.defAllowInsecure.ToString().ToLower() : node.allowInsecure),
alpn = node.GetAlpn(),
@@ -608,7 +608,7 @@ namespace v2rayN.Handler
switch (node.GetNetwork())
{
case "kcp":
KcpSettings kcpSettings = new KcpSettings
KcpSettings kcpSettings = new()
{
mtu = config.kcpItem.mtu,
tti = config.kcpItem.tti
@@ -644,12 +644,8 @@ namespace v2rayN.Handler
break;
//ws
case "ws":
WsSettings wsSettings = new WsSettings
{
};
wsSettings.headers = new Headers
{
};
WsSettings wsSettings = new();
wsSettings.headers = new Headers();
string path = node.path;
if (!string.IsNullOrWhiteSpace(host))
{
@@ -675,7 +671,7 @@ namespace v2rayN.Handler
break;
//h2
case "h2":
HttpSettings httpSettings = new HttpSettings();
HttpSettings httpSettings = new();
if (!string.IsNullOrWhiteSpace(host))
{
@@ -691,7 +687,7 @@ namespace v2rayN.Handler
break;
//quic
case "quic":
QuicSettings quicsettings = new QuicSettings
QuicSettings quicsettings = new()
{
security = host,
key = node.path,
@@ -714,7 +710,7 @@ namespace v2rayN.Handler
}
break;
case "grpc":
var grpcSettings = new GrpcSettings
GrpcSettings grpcSettings = new()
{
serviceName = node.path,
multiMode = (node.headerType == Global.GrpcmultiMode),
@@ -730,7 +726,7 @@ namespace v2rayN.Handler
//tcp
if (node.headerType.Equals(Global.TcpHeaderHttp))
{
TcpSettings tcpSettings = new TcpSettings
TcpSettings tcpSettings = new()
{
header = new Header
{
@@ -799,7 +795,7 @@ namespace v2rayN.Handler
}
else
{
List<string> servers = new List<string>();
List<string> servers = new();
string[] arrDNS = config.remoteDNS.Split(',');
foreach (string str in arrDNS)
@@ -828,9 +824,9 @@ namespace v2rayN.Handler
if (config.guiItem.enableStatistics)
{
string tag = Global.InboundAPITagName;
API apiObj = new API();
Policy policyObj = new Policy();
SystemPolicy policySystemSetting = new SystemPolicy();
API apiObj = new();
Policy policyObj = new();
SystemPolicy policySystemSetting = new();
string[] services = { "StatsService" };
@@ -847,8 +843,8 @@ namespace v2rayN.Handler
if (!v2rayConfig.inbounds.Exists(item => item.tag == tag))
{
Inbounds apiInbound = new Inbounds();
Inboundsettings apiInboundSettings = new Inboundsettings();
Inbounds apiInbound = new();
Inboundsettings apiInboundSettings = new();
apiInbound.tag = tag;
apiInbound.listen = Global.Loopback;
apiInbound.port = Global.statePort;
@@ -860,7 +856,7 @@ namespace v2rayN.Handler
if (!v2rayConfig.routing.rules.Exists(item => item.outboundTag == tag))
{
RulesItem apiRoutingRule = new RulesItem
RulesItem apiRoutingRule = new()
{
inboundTag = new List<string> { tag },
outboundTag = tag,
@@ -957,7 +953,7 @@ namespace v2rayN.Handler
return 0;
}
public static int GenerateClientConfigContent(ProfileItem node, bool blExport, ref V2rayConfig v2rayConfig, out string msg)
public static int GenerateClientConfigContent(ProfileItem node, bool blExport, ref V2rayConfig? v2rayConfig, out string msg)
{
try
{
@@ -1034,7 +1030,7 @@ namespace v2rayN.Handler
return -1;
}
V2rayConfig v2rayConfig = Utils.FromJson<V2rayConfig>(result);
V2rayConfig? v2rayConfig = Utils.FromJson<V2rayConfig>(result);
if (v2rayConfig == null)
{
msg = ResUI.FailedGenDefaultConfiguration;
@@ -1123,10 +1119,10 @@ namespace v2rayN.Handler
#region Import (export) client/server configuration
public static ProfileItem ImportFromClientConfig(string fileName, out string msg)
public static ProfileItem? ImportFromClientConfig(string fileName, out string msg)
{
msg = string.Empty;
ProfileItem profileItem = new ProfileItem();
ProfileItem profileItem = new();
try
{
@@ -1137,7 +1133,7 @@ namespace v2rayN.Handler
return null;
}
V2rayConfig v2rayConfig = Utils.FromJson<V2rayConfig>(result);
V2rayConfig? v2rayConfig = Utils.FromJson<V2rayConfig>(result);
if (v2rayConfig == null)
{
msg = ResUI.FailedConversionConfiguration;
@@ -1262,10 +1258,10 @@ namespace v2rayN.Handler
return profileItem;
}
public static ProfileItem ImportFromServerConfig(string fileName, out string msg)
public static ProfileItem? ImportFromServerConfig(string fileName, out string msg)
{
msg = string.Empty;
ProfileItem profileItem = new ProfileItem();
ProfileItem profileItem = new();
try
{
@@ -1276,7 +1272,7 @@ namespace v2rayN.Handler
return null;
}
V2rayConfig v2rayConfig = Utils.FromJson<V2rayConfig>(result);
V2rayConfig? v2rayConfig = Utils.FromJson<V2rayConfig>(result);
if (v2rayConfig == null)
{
msg = ResUI.FailedConversionConfiguration;
@@ -1401,7 +1397,7 @@ namespace v2rayN.Handler
public static int Export2ClientConfig(ProfileItem node, string fileName, out string msg)
{
V2rayConfig v2rayConfig = null;
V2rayConfig? v2rayConfig = null;
if (GenerateClientConfigContent(node, true, ref v2rayConfig, out msg) != 0)
{
return -1;
@@ -1440,14 +1436,14 @@ namespace v2rayN.Handler
return "";
}
V2rayConfig v2rayConfig = Utils.FromJson<V2rayConfig>(result);
V2rayConfig? v2rayConfig = Utils.FromJson<V2rayConfig>(result);
if (v2rayConfig == null)
{
msg = ResUI.FailedGenDefaultConfiguration;
return "";
}
List<IPEndPoint> lstIpEndPoints = new List<IPEndPoint>();
List<TcpConnectionInformation> lstTcpConns = new List<TcpConnectionInformation>();
List<IPEndPoint> lstIpEndPoints = new();
List<TcpConnectionInformation> lstTcpConns = new();
try
{
lstIpEndPoints.AddRange(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners());
@@ -1477,7 +1473,7 @@ namespace v2rayN.Handler
{
continue;
}
if (it.configType == EConfigType.VMess || it.configType == EConfigType.VLESS)
if (it.configType is EConfigType.VMess or EConfigType.VLESS)
{
var item2 = LazyConfig.Instance.GetProfileItem(it.indexId);
if (item2 is null || Utils.IsNullOrEmpty(item2.id) || !Utils.IsGuidByParse(item2.id))
@@ -1513,7 +1509,7 @@ namespace v2rayN.Handler
it.allowTest = true;
//inbound
Inbounds inbound = new Inbounds
Inbounds inbound = new()
{
listen = Global.Loopback,
port = port,
@@ -1523,7 +1519,7 @@ namespace v2rayN.Handler
v2rayConfig.inbounds.Add(inbound);
//outbound
V2rayConfig v2rayConfigCopy = Utils.FromJson<V2rayConfig>(result);
V2rayConfig? v2rayConfigCopy = Utils.FromJson<V2rayConfig>(result);
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
if (item is null)
{
@@ -1540,7 +1536,7 @@ namespace v2rayN.Handler
v2rayConfig.outbounds.Add(v2rayConfigCopy.outbounds[0]);
//rule
RulesItem rule = new RulesItem
RulesItem rule = new()
{
inboundTag = new List<string> { inbound.tag },
outboundTag = v2rayConfigCopy.outbounds[0].tag,

View File

@@ -12,9 +12,9 @@ namespace v2rayN.Handler
class CoreHandler
{
private static string _coreCConfigRes = Global.coreConfigFileName;
private CoreInfo _coreInfo;
private CoreInfo? _coreInfo;
private int _processId = 0;
private Process _process;
private Process? _process;
Action<bool, string> _updateFunc;
public CoreHandler(Action<bool, string> update)
@@ -108,7 +108,7 @@ namespace v2rayN.Handler
Process[] existing = Process.GetProcessesByName(vName);
foreach (Process p in existing)
{
string path = p.MainModule.FileName;
string? path = p.MainModule?.FileName;
if (path == $"{Utils.GetBinPath(vName, _coreInfo.coreType)}.exe")
{
KillProcess(p);
@@ -173,7 +173,8 @@ namespace v2rayN.Handler
string fileName = CoreFindexe(_coreInfo);
if (fileName == "") return;
Process p = new Process
var displayLog = node.configType != EConfigType.Custom || node.displayLog;
Process p = new()
{
StartInfo = new ProcessStartInfo
{
@@ -181,18 +182,18 @@ namespace v2rayN.Handler
Arguments = _coreInfo.arguments,
WorkingDirectory = Utils.GetConfigPath(),
UseShellExecute = false,
RedirectStandardOutput = node.displayLog,
RedirectStandardError = node.displayLog,
RedirectStandardOutput = displayLog,
RedirectStandardError = displayLog,
CreateNoWindow = true,
StandardOutputEncoding = node.displayLog ? Encoding.UTF8 : null,
StandardErrorEncoding = node.displayLog ? Encoding.UTF8 : null,
StandardOutputEncoding = displayLog ? Encoding.UTF8 : null,
StandardErrorEncoding = displayLog ? Encoding.UTF8 : null,
}
};
if (node.displayLog)
if (displayLog)
{
p.OutputDataReceived += (sender, e) =>
{
if (!String.IsNullOrEmpty(e.Data))
if (!string.IsNullOrEmpty(e.Data))
{
string msg = e.Data + Environment.NewLine;
ShowMsg(false, msg);
@@ -200,7 +201,7 @@ namespace v2rayN.Handler
};
}
p.Start();
if (node.displayLog)
if (displayLog)
{
p.BeginOutputReadLine();
}
@@ -208,7 +209,7 @@ namespace v2rayN.Handler
if (p.WaitForExit(1000))
{
throw new Exception(node.displayLog ? p.StandardError.ReadToEnd() : "启动进程失败并退出 (Failed to start the process and exited)");
throw new Exception(displayLog ? p.StandardError.ReadToEnd() : "启动进程失败并退出 (Failed to start the process and exited)");
}
Global.processJob.AddProcess(p.Handle);
@@ -231,7 +232,7 @@ namespace v2rayN.Handler
string fileName = CoreFindexe(coreInfo);
if (fileName == "") return -1;
Process p = new Process
Process p = new()
{
StartInfo = new ProcessStartInfo
{

View File

@@ -16,7 +16,7 @@ namespace v2rayN.Handler
{
public event EventHandler<ResultEventArgs> UpdateCompleted;
public event ErrorEventHandler Error;
public event ErrorEventHandler? Error;
public class ResultEventArgs : EventArgs
@@ -76,7 +76,7 @@ namespace v2rayN.Handler
if (UpdateCompleted != null)
{
string msg = $"...{value}%";
UpdateCompleted(this, new ResultEventArgs(value > 100 ? true : false, msg));
UpdateCompleted(this, new ResultEventArgs(value > 100, msg));
}
};
@@ -99,7 +99,7 @@ namespace v2rayN.Handler
}
}
public async Task<string> UrlRedirectAsync(string url, bool blProxy)
public async Task<string?> UrlRedirectAsync(string url, bool blProxy)
{
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().guiItem.enableSecurityProtocolTls13);
var webRequestHandler = new SocketsHttpHandler
@@ -107,12 +107,12 @@ namespace v2rayN.Handler
AllowAutoRedirect = false,
Proxy = GetWebProxy(blProxy)
};
HttpClient client = new HttpClient(webRequestHandler);
HttpClient client = new(webRequestHandler);
HttpResponseMessage response = await client.GetAsync(url);
if (response.StatusCode.ToString() == "Redirect")
{
return response.Headers.Location.ToString();
return response.Headers.Location?.ToString();
}
else
{
@@ -121,7 +121,7 @@ namespace v2rayN.Handler
}
}
public async Task<string> TryDownloadString(string url, bool blProxy, string userAgent)
public async Task<string?> TryDownloadString(string url, bool blProxy, string userAgent)
{
try
{
@@ -161,14 +161,12 @@ namespace v2rayN.Handler
try
{
using (var wc = new WebClient())
using var wc = new WebClient();
wc.Proxy = GetWebProxy(blProxy);
var result3 = await wc.DownloadStringTaskAsync(url);
if (!Utils.IsNullOrEmpty(result3))
{
wc.Proxy = GetWebProxy(blProxy);
var result3 = await wc.DownloadStringTaskAsync(url);
if (!Utils.IsNullOrEmpty(result3))
{
return result3;
}
return result3;
}
}
catch (Exception ex)
@@ -181,7 +179,7 @@ namespace v2rayN.Handler
}
}
return null;
}
@@ -189,7 +187,7 @@ namespace v2rayN.Handler
/// DownloadString
/// </summary>
/// <param name="url"></param>
public async Task<string> DownloadStringAsync(string url, bool blProxy, string userAgent)
public async Task<string?> DownloadStringAsync(string url, bool blProxy, string userAgent)
{
try
{
@@ -205,7 +203,7 @@ namespace v2rayN.Handler
}
client.DefaultRequestHeaders.UserAgent.TryParseAdd(userAgent);
Uri uri = new Uri(url);
Uri uri = new(url);
//Authorization Header
if (!Utils.IsNullOrEmpty(uri.UserInfo))
{
@@ -234,7 +232,7 @@ namespace v2rayN.Handler
/// DownloadString
/// </summary>
/// <param name="url"></param>
public async Task<string> DownloadStringViaDownloader(string url, bool blProxy, string userAgent)
public async Task<string?> DownloadStringViaDownloader(string url, bool blProxy, string userAgent)
{
try
{
@@ -262,7 +260,7 @@ namespace v2rayN.Handler
}
public int RunAvailabilityCheck(WebProxy webProxy)
public int RunAvailabilityCheck(WebProxy? webProxy)
{
try
{
@@ -302,12 +300,11 @@ namespace v2rayN.Handler
myHttpWebRequest.Timeout = downloadTimeout * 1000;
myHttpWebRequest.Proxy = webProxy;
Stopwatch timer = new Stopwatch();
Stopwatch timer = new();
timer.Start();
HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
if (myHttpWebResponse.StatusCode != HttpStatusCode.OK
&& myHttpWebResponse.StatusCode != HttpStatusCode.NoContent)
if (myHttpWebResponse.StatusCode is not HttpStatusCode.OK and not HttpStatusCode.NoContent)
{
msg = myHttpWebResponse.StatusDescription;
}
@@ -324,7 +321,7 @@ namespace v2rayN.Handler
return msg;
}
private WebProxy GetWebProxy(bool blProxy)
private WebProxy? GetWebProxy(bool blProxy)
{
if (!blProxy)
{
@@ -341,11 +338,11 @@ namespace v2rayN.Handler
private bool SocketCheck(string ip, int port)
{
Socket sock = null;
Socket? sock = null;
try
{
IPAddress ipa = IPAddress.Parse(ip);
IPEndPoint point = new IPEndPoint(ipa, port);
IPEndPoint point = new(ipa, port);
sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sock.Connect(point);
return true;

View File

@@ -5,7 +5,7 @@ namespace v2rayN.Handler
{
public sealed class LazyConfig
{
private static readonly Lazy<LazyConfig> _instance = new Lazy<LazyConfig>(() => new());
private static readonly Lazy<LazyConfig> _instance = new(() => new());
private Config _config;
private List<CoreInfo> coreInfos;
@@ -17,11 +17,12 @@ namespace v2rayN.Handler
SqliteHelper.Instance.CreateTable<ProfileItem>();
SqliteHelper.Instance.CreateTable<ServerStatItem>();
SqliteHelper.Instance.CreateTable<RoutingItem>();
SqliteHelper.Instance.CreateTable<ProfileExItem>();
}
#region Config
public void SetConfig(ref Config config)
public void SetConfig(Config config)
{
_config = config;
}
@@ -81,6 +82,18 @@ namespace v2rayN.Handler
return SqliteHelper.Instance.Table<ProfileItem>().Where(t => t.subid == subid).ToList();
}
}
public List<string> ProfileItemIndexs(string subid)
{
if (Utils.IsNullOrEmpty(subid))
{
return SqliteHelper.Instance.Table<ProfileItem>().Select(t => t.indexId).ToList();
}
else
{
return SqliteHelper.Instance.Table<ProfileItem>().Where(t => t.subid == subid).Select(t => t.indexId).ToList();
}
}
public List<ProfileItemModel> ProfileItems(string subid, string filter)
{
@@ -101,12 +114,11 @@ namespace v2rayN.Handler
}
sql += $" and a.remarks like '%{filter}%'";
}
sql += " order by a.sort";
return SqliteHelper.Instance.Query<ProfileItemModel>(sql).ToList();
}
public ProfileItem GetProfileItem(string indexId)
public ProfileItem? GetProfileItem(string indexId)
{
if (Utils.IsNullOrEmpty(indexId))
{
@@ -115,28 +127,6 @@ namespace v2rayN.Handler
return SqliteHelper.Instance.Table<ProfileItem>().FirstOrDefault(it => it.indexId == indexId);
}
public Task SetTestResult(string indexId, string delayVal, string speedVal)
{
string sql = string.Empty;
if (!Utils.IsNullOrEmpty(delayVal) && !Utils.IsNullOrEmpty(speedVal))
{
int.TryParse(delayVal, out int delay);
decimal.TryParse(speedVal, out decimal speed);
sql = $"update ProfileItem set delay={delay},speed={speed} where indexId = '{indexId}'";
}
else if (!Utils.IsNullOrEmpty(delayVal))
{
int.TryParse(delayVal, out int delay);
sql = $"update ProfileItem set delay={delay} where indexId = '{indexId}'";
}
else if (!Utils.IsNullOrEmpty(speedVal))
{
decimal.TryParse(speedVal, out decimal speed);
sql = $"update ProfileItem set speed={speed} where indexId = '{indexId}'";
}
return SqliteHelper.Instance.ExecuteAsync(sql);
}
public List<RoutingItem> RoutingItems()
{
return SqliteHelper.Instance.Table<RoutingItem>().Where(it => it.locked == false).OrderBy(t => t.sort).ToList();
@@ -183,7 +173,7 @@ namespace v2rayN.Handler
return item.coreType;
}
public CoreInfo GetCoreInfo(ECoreType coreType)
public CoreInfo? GetCoreInfo(ECoreType coreType)
{
if (coreInfos == null)
{
@@ -192,7 +182,7 @@ namespace v2rayN.Handler
return coreInfos.Where(t => t.coreType == coreType).FirstOrDefault();
}
public List<CoreInfo> GetCoreInfos()
public List<CoreInfo>? GetCoreInfos()
{
if (coreInfos == null)
{
@@ -203,7 +193,7 @@ namespace v2rayN.Handler
private void InitCoreInfo()
{
coreInfos = new List<CoreInfo>();
coreInfos = new(16);
coreInfos.Add(new CoreInfo
{

View File

@@ -12,7 +12,7 @@ namespace v2rayN.Handler
{
public sealed class MainFormHandler
{
private static readonly Lazy<MainFormHandler> instance = new Lazy<MainFormHandler>(() => new MainFormHandler());
private static readonly Lazy<MainFormHandler> instance = new(() => new());
//Action<bool, string> _updateUI;
//private DownloadHandle downloadHandle2;
@@ -42,19 +42,14 @@ namespace v2rayN.Handler
{
return new Icon(fileName);
}
switch (index)
return index switch
{
case 0:
return Properties.Resources.NotifyIcon1;
case 1:
return Properties.Resources.NotifyIcon2;
case 2:
return Properties.Resources.NotifyIcon3;
case 3:
return Properties.Resources.NotifyIcon2;
}
return Properties.Resources.NotifyIcon1;
0 => Properties.Resources.NotifyIcon1,
1 => Properties.Resources.NotifyIcon2,
2 => Properties.Resources.NotifyIcon3,
3 => Properties.Resources.NotifyIcon2,
_ => Properties.Resources.NotifyIcon1, // default
};
}
catch (Exception ex)
{
@@ -82,7 +77,7 @@ namespace v2rayN.Handler
return BitmapFrame.Create(new Uri($"pack://application:,,,/Resources/NotifyIcon{index}.ico", UriKind.RelativeOrAbsolute));
}
private Icon GetNotifyIcon4Routing(Config config)
private Icon? GetNotifyIcon4Routing(Config config)
{
try
{
@@ -107,9 +102,9 @@ namespace v2rayN.Handler
int width = 128;
int height = 128;
Bitmap bitmap = new Bitmap(width, height);
Bitmap bitmap = new(width, height);
Graphics graphics = Graphics.FromImage(bitmap);
SolidBrush drawBrush = new SolidBrush(color);
SolidBrush drawBrush = new(color);
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
//graphics.FillRectangle(drawBrush, new Rectangle(0, 0, width, height));
@@ -143,7 +138,7 @@ namespace v2rayN.Handler
return;
}
SaveFileDialog fileDialog = new SaveFileDialog
SaveFileDialog fileDialog = new()
{
Filter = "Config|*.json",
FilterIndex = 2,
@@ -176,14 +171,13 @@ namespace v2rayN.Handler
{
return;
}
if (item.configType != EConfigType.VMess
&& item.configType != EConfigType.VLESS)
if (item.configType is not EConfigType.VMess and not EConfigType.VLESS)
{
UI.Show(ResUI.NonVmessService);
return;
}
SaveFileDialog fileDialog = new SaveFileDialog
SaveFileDialog fileDialog = new()
{
Filter = "Config|*.json",
FilterIndex = 2,
@@ -212,14 +206,14 @@ namespace v2rayN.Handler
public void BackupGuiNConfig(Config config, bool auto = false)
{
string fileName = $"guiNConfig_{DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss_fff")}.json";
string fileName = $"guiNConfig_{DateTime.Now:yyyy_MM_dd_HH_mm_ss_fff}.json";
if (auto)
{
fileName = Utils.GetBackupPath(fileName);
}
else
{
SaveFileDialog fileDialog = new SaveFileDialog
SaveFileDialog fileDialog = new()
{
FileName = fileName,
Filter = "guiNConfig|*.json",
@@ -254,7 +248,7 @@ namespace v2rayN.Handler
public bool RestoreGuiNConfig(ref Config config)
{
var fileContent = string.Empty;
using (OpenFileDialog fileDialog = new OpenFileDialog())
using (OpenFileDialog fileDialog = new())
{
fileDialog.InitialDirectory = Utils.GetBackupPath("");
fileDialog.Filter = "guiNConfig|*.json|All|*.*";
@@ -286,7 +280,7 @@ namespace v2rayN.Handler
BackupGuiNConfig(config, true);
config = resConfig;
LazyConfig.Instance.SetConfig(ref config);
LazyConfig.Instance.SetConfig(config);
return true;
}
@@ -381,12 +375,12 @@ namespace v2rayN.Handler
try
{
HotkeyManager.Current.AddOrReplace(((int)item.eGlobalHotkey).ToString(), gesture, handler);
var msg = string.Format(ResUI.RegisterGlobalHotkeySuccessfully, $"{item.eGlobalHotkey.ToString()}");
var msg = string.Format(ResUI.RegisterGlobalHotkeySuccessfully, $"{item.eGlobalHotkey}");
update(false, msg);
}
catch (Exception ex)
{
var msg = string.Format(ResUI.RegisterGlobalHotkeyFailed, $"{item.eGlobalHotkey.ToString()}", ex.Message);
var msg = string.Format(ResUI.RegisterGlobalHotkeyFailed, $"{item.eGlobalHotkey}", ex.Message);
update(false, msg);
Utils.SaveLog(msg);
}

View File

@@ -0,0 +1,114 @@
using v2rayN.Base;
using v2rayN.Mode;
namespace v2rayN.Handler
{
class ProfileExHandler
{
private static readonly Lazy<ProfileExHandler> _instance = new(() => new());
private List<ProfileExItem> _lstProfileEx;
public List<ProfileExItem> ProfileExs => _lstProfileEx;
public static ProfileExHandler Instance => _instance.Value;
public ProfileExHandler()
{
Init();
}
private void Init()
{
SqliteHelper.Instance.Execute($"delete from ProfileExItem where indexId not in ( select indexId from ProfileItem )");
_lstProfileEx = SqliteHelper.Instance.Table<ProfileExItem>().ToList();
}
private void AddProfileEx(string indexId, ref ProfileExItem profileEx)
{
profileEx = new()
{
indexId = indexId,
delay = 0,
speed = 0,
sort = 0
};
_lstProfileEx.Add(profileEx);
//SqliteHelper.Instance.Replace(profileEx);
}
public void ClearAll()
{
SqliteHelper.Instance.Execute($"delete from ProfileExItem ");
_lstProfileEx = new();
}
public void SaveTo()
{
try
{
foreach (var item in _lstProfileEx)
{
SqliteHelper.Instance.Replace(item);
}
//SqliteHelper.Instance.UpdateAll(_lstProfileEx);
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
}
}
public Task SetTestDelay(string indexId, string delayVal)
{
var profileEx = _lstProfileEx.FirstOrDefault(t => t.indexId == indexId);
if (profileEx == null)
{
AddProfileEx(indexId, ref profileEx);
}
int.TryParse(delayVal, out int delay);
profileEx.delay = delay;
return Task.CompletedTask;
}
public Task SetTestSpeed(string indexId, string speedVal)
{
var profileEx = _lstProfileEx.FirstOrDefault(t => t.indexId == indexId);
if (profileEx == null)
{
AddProfileEx(indexId, ref profileEx);
}
decimal.TryParse(speedVal, out decimal speed);
profileEx.speed = speed;
return Task.CompletedTask;
}
public void SetSort(string indexId, int sort)
{
var profileEx = _lstProfileEx.FirstOrDefault(t => t.indexId == indexId);
if (profileEx == null)
{
AddProfileEx(indexId, ref profileEx);
}
profileEx.sort = sort;
}
public int GetSort(string indexId)
{
var profileEx = _lstProfileEx.FirstOrDefault(t => t.indexId == indexId);
if (profileEx == null)
{
return 0;
}
return profileEx.sort;
}
public int GetMaxSort()
{
if (_lstProfileEx.Count <= 0)
{
return 0;
}
return _lstProfileEx.Max(t => t == null ? 0 : t.sort);
}
}
}

View File

@@ -10,16 +10,16 @@ namespace v2rayN.Handler
return SetProxy(null, null, 1);
}
public static bool SetProxy(string strProxy, string exceptions, int type)
public static bool SetProxy(string? strProxy, string? exceptions, int type)
{
InternetPerConnOptionList list = new InternetPerConnOptionList();
InternetPerConnOptionList list = new();
int optionCount = 1;
if (type == 1)
{
optionCount = 1;
}
else if (type == 2 || type == 4)
else if (type is 2 or 4)
{
optionCount = Utils.IsNullOrEmpty(exceptions) ? 2 : 3;
}
@@ -71,12 +71,12 @@ namespace v2rayN.Handler
{
if (Environment.Is64BitOperatingSystem)
{
IntPtr opt = new IntPtr(optionsPtr.ToInt64() + (i * optSize));
IntPtr opt = new(optionsPtr.ToInt64() + (i * optSize));
Marshal.StructureToPtr(options[i], opt, false);
}
else
{
IntPtr opt = new IntPtr(optionsPtr.ToInt32() + (i * optSize));
IntPtr opt = new(optionsPtr.ToInt32() + (i * optSize));
Marshal.StructureToPtr(options[i], opt, false);
}
}
@@ -84,7 +84,7 @@ namespace v2rayN.Handler
list.options = optionsPtr;
// and then make a pointer out of the whole list
IntPtr ipcoListPtr = Marshal.AllocCoTaskMem((int)list.dwSize);
IntPtr ipcoListPtr = Marshal.AllocCoTaskMem(list.dwSize);
Marshal.StructureToPtr(list, ipcoListPtr, false);
// and finally, call the API method!
@@ -189,24 +189,21 @@ namespace v2rayN.Handler
//判断是否使用代理
public static bool UsedProxy()
{
RegistryKey rk = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings", true);
if (rk.GetValue("ProxyEnable").ToString() == "1")
using RegistryKey? rk = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings", true);
if (rk?.GetValue("ProxyEnable")?.ToString() == "1")
{
rk.Close();
return true;
}
else
{
rk.Close();
return false;
}
}
//获得代理的IP和端口
public static string GetProxyProxyServer()
public static string? GetProxyProxyServer()
{
RegistryKey rk = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings", true);
using RegistryKey? rk = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings", true);
string ProxyServer = rk.GetValue("ProxyServer").ToString();
rk.Close();
return ProxyServer;
}

View File

@@ -9,13 +9,13 @@ namespace v2rayN.Handler
/// </summary>
public class QRCodeHelper
{
public static DrawingImage GetQRCode(string strContent)
public static DrawingImage? GetQRCode(string strContent)
{
try
{
QRCodeGenerator qrGenerator = new QRCodeGenerator();
QRCodeGenerator qrGenerator = new();
QRCodeData qrCodeData = qrGenerator.CreateQrCode(strContent, QRCodeGenerator.ECCLevel.H);
XamlQRCode qrCode = new XamlQRCode(qrCodeData);
XamlQRCode qrCode = new(qrCodeData);
DrawingImage qrCodeAsXaml = qrCode.GetGraphic(40);
return qrCodeAsXaml;
}

View File

@@ -17,32 +17,22 @@ namespace v2rayN.Handler
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public static string GetShareUrl(ProfileItem item)
public static string? GetShareUrl(ProfileItem item)
{
try
{
string url = string.Empty;
string? url = string.Empty;
switch (item.configType)
url = item.configType switch
{
case EConfigType.VMess:
url = ShareVmess(item);
break;
case EConfigType.Shadowsocks:
url = ShareShadowsocks(item);
break;
case EConfigType.Socks:
url = ShareSocks(item);
break;
case EConfigType.Trojan:
url = ShareTrojan(item);
break;
case EConfigType.VLESS:
url = ShareVLESS(item);
break;
default:
break;
}
EConfigType.VMess => ShareVmess(item),
EConfigType.Shadowsocks => ShareShadowsocks(item),
EConfigType.Socks => ShareSocks(item),
EConfigType.Trojan => ShareTrojan(item),
EConfigType.VLESS => ShareVLESS(item),
_ => null,
};
return url;
}
catch (Exception ex)
@@ -56,7 +46,7 @@ namespace v2rayN.Handler
{
string url = string.Empty;
VmessQRCode vmessQRCode = new VmessQRCode
VmessQRCode vmessQRCode = new()
{
v = item.configVersion.ToString(),
ps = item.remarks.TrimEx(), //备注也许很长 ;
@@ -177,7 +167,7 @@ namespace v2rayN.Handler
return Utils.IsIpv6(address) ? $"[{address}]" : address;
}
private static int GetStdTransport(ProfileItem item, string securityDef, ref Dictionary<string, string> dicQuery)
private static int GetStdTransport(ProfileItem item, string? securityDef, ref Dictionary<string, string> dicQuery)
{
if (!Utils.IsNullOrEmpty(item.flow))
{
@@ -260,7 +250,7 @@ namespace v2rayN.Handler
if (!Utils.IsNullOrEmpty(item.path))
{
dicQuery.Add("serviceName", Utils.UrlEncode(item.path));
if (item.headerType == Global.GrpcgunMode || item.headerType == Global.GrpcmultiMode)
if (item.headerType is Global.GrpcgunMode or Global.GrpcmultiMode)
{
dicQuery.Add("mode", Utils.UrlEncode(item.headerType));
}
@@ -278,13 +268,13 @@ namespace v2rayN.Handler
/// <summary>
/// 从剪贴板导入URL
/// </summary>
/// <param name="fileName"></param>
/// <param name="msg"></param>
/// <returns></returns>
public static ProfileItem ImportFromClipboardConfig(string clipboardData, out string msg)
public static ProfileItem? ImportFromClipboardConfig(string clipboardData, out string msg)
{
msg = string.Empty;
ProfileItem profileItem = new ProfileItem();
ProfileItem profileItem = new();
try
{
@@ -368,7 +358,7 @@ namespace v2rayN.Handler
return profileItem;
}
private static ProfileItem ResolveVmess(string result, out string msg)
private static ProfileItem? ResolveVmess(string result, out string msg)
{
msg = string.Empty;
var profileItem = new ProfileItem
@@ -376,11 +366,11 @@ namespace v2rayN.Handler
configType = EConfigType.VMess
};
result = result.Substring(Global.vmessProtocol.Length);
result = result[Global.vmessProtocol.Length..];
result = Utils.Base64Decode(result);
//转成Json
VmessQRCode vmessQRCode = Utils.FromJson<VmessQRCode>(result);
VmessQRCode? vmessQRCode = Utils.FromJson<VmessQRCode>(result);
if (vmessQRCode == null)
{
msg = ResUI.FailedConversionConfiguration;
@@ -418,17 +408,17 @@ namespace v2rayN.Handler
return profileItem;
}
private static ProfileItem ResolveVmess4Kitsunebi(string result)
private static ProfileItem? ResolveVmess4Kitsunebi(string result)
{
ProfileItem profileItem = new ProfileItem
ProfileItem profileItem = new()
{
configType = EConfigType.VMess
};
result = result.Substring(Global.vmessProtocol.Length);
result = result[Global.vmessProtocol.Length..];
int indexSplit = result.IndexOf("?");
if (indexSplit > 0)
{
result = result.Substring(0, indexSplit);
result = result[..indexSplit];
}
result = Utils.Base64Decode(result);
@@ -439,7 +429,7 @@ namespace v2rayN.Handler
}
string[] arr21 = arr1[0].Split(':');
string[] arr22 = arr1[1].Split(':');
if (arr21.Length != 2 || arr21.Length != 2)
if (arr21.Length != 2 || arr22.Length != 2)
{
return null;
}
@@ -456,15 +446,15 @@ namespace v2rayN.Handler
return profileItem;
}
private static ProfileItem ResolveStdVmess(string result)
private static ProfileItem? ResolveStdVmess(string result)
{
ProfileItem i = new ProfileItem
ProfileItem i = new()
{
configType = EConfigType.VMess,
security = "auto"
};
Uri u = new Uri(result);
Uri u = new(result);
i.address = u.IdnHost;
i.port = u.Port;
@@ -537,7 +527,7 @@ namespace v2rayN.Handler
return i;
}
private static ProfileItem ResolveSip002(string result)
private static ProfileItem? ResolveSip002(string result)
{
Uri parsedUrl;
try
@@ -548,7 +538,7 @@ namespace v2rayN.Handler
{
return null;
}
ProfileItem server = new ProfileItem
ProfileItem server = new()
{
remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped),
address = parsedUrl.IdnHost,
@@ -556,7 +546,7 @@ namespace v2rayN.Handler
};
string rawUserInfo = parsedUrl.GetComponents(UriComponents.UserInfo, UriFormat.UriEscaped);
//2022-blake3
if (rawUserInfo.Contains(":"))
if (rawUserInfo.Contains(':'))
{
string[] userInfoParts = rawUserInfo.Split(new[] { ':' }, 2);
if (userInfoParts.Length != 2)
@@ -600,16 +590,16 @@ namespace v2rayN.Handler
return server;
}
private static readonly Regex UrlFinder = new Regex(@"ss://(?<base64>[A-Za-z0-9+-/=_]+)(?:#(?<tag>\S+))?", RegexOptions.IgnoreCase);
private static readonly Regex DetailsParser = new Regex(@"^((?<method>.+?):(?<password>.*)@(?<hostname>.+?):(?<port>\d+?))$", RegexOptions.IgnoreCase);
private static readonly Regex UrlFinder = new(@"ss://(?<base64>[A-Za-z0-9+-/=_]+)(?:#(?<tag>\S+))?", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly Regex DetailsParser = new(@"^((?<method>.+?):(?<password>.*)@(?<hostname>.+?):(?<port>\d+?))$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static ProfileItem ResolveSSLegacy(string result)
private static ProfileItem? ResolveSSLegacy(string result)
{
var match = UrlFinder.Match(result);
if (!match.Success)
return null;
ProfileItem server = new ProfileItem();
ProfileItem server = new();
var base64 = match.Groups["base64"].Value.TrimEnd('/');
var tag = match.Groups["tag"].Value;
if (!Utils.IsNullOrEmpty(tag))
@@ -635,16 +625,16 @@ namespace v2rayN.Handler
}
private static readonly Regex StdVmessUserInfo = new Regex(
@"^(?<network>[a-z]+)(\+(?<streamSecurity>[a-z]+))?:(?<id>[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$");
private static readonly Regex StdVmessUserInfo = new(
@"^(?<network>[a-z]+)(\+(?<streamSecurity>[a-z]+))?:(?<id>[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$", RegexOptions.Compiled);
private static ProfileItem ResolveSocks(string result)
private static ProfileItem? ResolveSocks(string result)
{
ProfileItem profileItem = new ProfileItem
ProfileItem profileItem = new()
{
configType = EConfigType.Socks
};
result = result.Substring(Global.socksProtocol.Length);
result = result[Global.socksProtocol.Length..];
//remark
int indexRemark = result.IndexOf("#");
if (indexRemark > 0)
@@ -654,7 +644,7 @@ namespace v2rayN.Handler
profileItem.remarks = Utils.UrlDecode(result.Substring(indexRemark + 1, result.Length - indexRemark - 1));
}
catch { }
result = result.Substring(0, indexRemark);
result = result[..indexRemark];
}
//part decode
int indexS = result.IndexOf("@");
@@ -678,15 +668,15 @@ namespace v2rayN.Handler
{
return null;
}
profileItem.address = arr1[1].Substring(0, indexPort);
profileItem.port = Utils.ToInt(arr1[1].Substring(indexPort + 1, arr1[1].Length - (indexPort + 1)));
profileItem.address = arr1[1][..indexPort];
profileItem.port = Utils.ToInt(arr1[1][(indexPort + 1)..]);
profileItem.security = arr21[0];
profileItem.id = arr21[1];
return profileItem;
}
private static ProfileItem ResolveSocksNew(string result)
private static ProfileItem? ResolveSocksNew(string result)
{
Uri parsedUrl;
try
@@ -697,7 +687,7 @@ namespace v2rayN.Handler
{
return null;
}
ProfileItem server = new ProfileItem
ProfileItem server = new()
{
remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped),
address = parsedUrl.IdnHost,
@@ -719,12 +709,12 @@ namespace v2rayN.Handler
private static ProfileItem ResolveTrojan(string result)
{
ProfileItem item = new ProfileItem
ProfileItem item = new()
{
configType = EConfigType.Trojan
};
Uri url = new Uri(result);
Uri url = new(result);
item.address = url.IdnHost;
item.port = url.Port;
@@ -738,13 +728,13 @@ namespace v2rayN.Handler
}
private static ProfileItem ResolveStdVLESS(string result)
{
ProfileItem item = new ProfileItem
ProfileItem item = new()
{
configType = EConfigType.VLESS,
security = "none"
};
Uri url = new Uri(result);
Uri url = new(result);
item.address = url.IdnHost;
item.port = url.Port;

View File

@@ -112,24 +112,24 @@ namespace v2rayN.Handler
private void RunPing()
{
RunPingSub((ServerTestItem it) =>
RunPingSub(async (ServerTestItem it) =>
{
long time = Ping(it.address);
var output = FormatOut(time, Global.DelayUnit);
LazyConfig.Instance.SetTestResult(it.indexId, output, "");
await ProfileExHandler.Instance.SetTestDelay(it.indexId, output);
UpdateFunc(it.indexId, output);
});
}
private void RunTcping()
{
RunPingSub((ServerTestItem it) =>
RunPingSub(async (ServerTestItem it) =>
{
int time = GetTcpingTime(it.address, it.port);
var output = FormatOut(time, Global.DelayUnit);
LazyConfig.Instance.SetTestResult(it.indexId, output, "");
await ProfileExHandler.Instance.SetTestDelay(it.indexId, output);
UpdateFunc(it.indexId, output);
});
}
@@ -150,7 +150,7 @@ namespace v2rayN.Handler
DownloadHandle downloadHandle = new DownloadHandle();
//Thread.Sleep(5000);
List<Task> tasks = new List<Task>();
List<Task> tasks = new();
foreach (var it in _selecteds)
{
if (!it.allowTest)
@@ -161,16 +161,15 @@ namespace v2rayN.Handler
{
continue;
}
tasks.Add(Task.Run(() =>
tasks.Add(Task.Run(async () =>
{
try
{
LazyConfig.Instance.SetTestResult(it.indexId, "-1", "");
WebProxy webProxy = new WebProxy(Global.Loopback, it.port);
WebProxy webProxy = new(Global.Loopback, it.port);
string output = GetRealPingTime(downloadHandle, webProxy);
LazyConfig.Instance.SetTestResult(it.indexId, output, "");
await ProfileExHandler.Instance.SetTestDelay(it.indexId, output);
UpdateFunc(it.indexId, output);
int.TryParse(output, out int delay);
it.delay = delay;
@@ -191,6 +190,7 @@ namespace v2rayN.Handler
finally
{
if (pid > 0) _coreHandler.CoreStopPid(pid);
ProfileExHandler.Instance.SaveTo();
}
return Task.CompletedTask;
@@ -214,7 +214,7 @@ namespace v2rayN.Handler
string url = _config.speedTestItem.speedTestUrl;
var timeout = _config.speedTestItem.speedTestTimeout;
DownloadHandle downloadHandle = new DownloadHandle();
DownloadHandle downloadHandle = new();
foreach (var it in _selecteds)
{
@@ -231,19 +231,19 @@ namespace v2rayN.Handler
// UpdateFunc(it.indexId, "", ResUI.SpeedtestingSkip);
// continue;
//}
_ = LazyConfig.Instance.SetTestResult(it.indexId, "", "-1");
await ProfileExHandler.Instance.SetTestSpeed(it.indexId, "-1");
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
if (item is null) continue;
WebProxy webProxy = new WebProxy(Global.Loopback, it.port);
WebProxy webProxy = new(Global.Loopback, it.port);
await downloadHandle.DownloadDataAsync(url, webProxy, timeout, (bool success, string msg) =>
await downloadHandle.DownloadDataAsync(url, webProxy, timeout, async (bool success, string msg) =>
{
decimal.TryParse(msg, out decimal dec);
if (dec > 0)
{
_ = LazyConfig.Instance.SetTestResult(it.indexId, "", msg);
await ProfileExHandler.Instance.SetTestSpeed(it.indexId, msg);
}
UpdateFunc(it.indexId, "", msg);
});
@@ -254,6 +254,7 @@ namespace v2rayN.Handler
_coreHandler.CoreStopPid(pid);
}
UpdateFunc("", ResUI.SpeedtestingCompleted);
ProfileExHandler.Instance.SaveTo();
}
private async Task RunSpeedTestMulti()
@@ -269,7 +270,7 @@ namespace v2rayN.Handler
string url = _config.speedTestItem.speedTestUrl;
var timeout = _config.speedTestItem.speedTestTimeout;
DownloadHandle downloadHandle = new DownloadHandle();
DownloadHandle downloadHandle = new();
foreach (var it in _selecteds)
{
@@ -281,18 +282,18 @@ namespace v2rayN.Handler
{
continue;
}
_ = LazyConfig.Instance.SetTestResult(it.indexId, "", "-1");
await ProfileExHandler.Instance.SetTestSpeed(it.indexId, "-1");
var item = LazyConfig.Instance.GetProfileItem(it.indexId);
if (item is null) continue;
WebProxy webProxy = new WebProxy(Global.Loopback, it.port);
_ = downloadHandle.DownloadDataAsync(url, webProxy, timeout, (bool success, string msg) =>
WebProxy webProxy = new(Global.Loopback, it.port);
_ = downloadHandle.DownloadDataAsync(url, webProxy, timeout, async (bool success, string msg) =>
{
decimal.TryParse(msg, out decimal dec);
if (dec > 0)
{
_ = LazyConfig.Instance.SetTestResult(it.indexId, "", msg);
await ProfileExHandler.Instance.SetTestSpeed(it.indexId, msg);
}
UpdateFunc(it.indexId, "", msg);
});
@@ -306,6 +307,7 @@ namespace v2rayN.Handler
_coreHandler.CoreStopPid(pid);
}
UpdateFunc("", ResUI.SpeedtestingCompleted);
ProfileExHandler.Instance.SaveTo();
}
private async Task RunMixedtestAsync()
@@ -336,11 +338,11 @@ namespace v2rayN.Handler
ipAddress = ipHostInfo.AddressList[0];
}
Stopwatch timer = new Stopwatch();
Stopwatch timer = new();
timer.Start();
IPEndPoint endPoint = new IPEndPoint(ipAddress, port);
Socket clientSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint endPoint = new(ipAddress, port);
using Socket clientSocket = new(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
IAsyncResult result = clientSocket.BeginConnect(endPoint, null, null);
if (!result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5)))
@@ -349,7 +351,6 @@ namespace v2rayN.Handler
timer.Stop();
responseTime = timer.Elapsed.Milliseconds;
clientSocket.Close();
}
catch (Exception ex)
{
@@ -371,7 +372,7 @@ namespace v2rayN.Handler
{
int timeout = 30;
int echoNum = 2;
Ping pingSender = new Ping();
using Ping pingSender = new();
for (int i = 0; i < echoNum; i++)
{
PingReply reply = pingSender.Send(host, timeout);

View File

@@ -13,7 +13,7 @@ namespace v2rayN.Handler
private Channel channel_;
private StatsService.StatsServiceClient client_;
private bool exitFlag_;
private ServerStatItem _serverStatItem;
private ServerStatItem? _serverStatItem;
private List<ServerStatItem> _lstServerStat;
public List<ServerStatItem> ServerStat => _lstServerStat;
@@ -70,7 +70,7 @@ namespace v2rayN.Handler
{
if (Enable && channel_.State == ChannelState.Ready)
{
QueryStatsResponse res = null;
QueryStatsResponse? res = null;
try
{
res = client_.QueryStats(new QueryStatsRequest() { Pattern = "", Reset = true });
@@ -229,7 +229,7 @@ namespace v2rayN.Handler
try
{
// TCP stack please do me a favor
TcpListener l = new TcpListener(IPAddress.Loopback, 0);
TcpListener l = new(IPAddress.Loopback, 0);
l.Start();
int port = ((IPEndPoint)l.LocalEndpoint).Port;
l.Stop();

View File

@@ -20,7 +20,7 @@ namespace v2rayN.Handler
// <proxy-server><CR-LF>
// <bypass-list><CR-LF>
// <pac-url>
private static SysproxyConfig _userSettings = null;
private static SysproxyConfig? _userSettings = null;
enum RET_ERRORS : int
{
@@ -154,85 +154,82 @@ namespace v2rayN.Handler
// using event to avoid hanging when redirect standard output/error
// ref: https://stackoverflow.com/questions/139593/processstartinfo-hanging-on-waitforexit-why
// and http://blog.csdn.net/zhangweixing0/article/details/7356841
using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
using AutoResetEvent outputWaitHandle = new(false);
using AutoResetEvent errorWaitHandle = new(false);
using Process process = new();
// Configure the process using the StartInfo properties.
process.StartInfo.FileName = Utils.GetTempPath("sysproxy.exe");
process.StartInfo.Arguments = arguments;
process.StartInfo.WorkingDirectory = Utils.GetTempPath();
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardOutput = true;
// Need to provide encoding info, or output/error strings we got will be wrong.
process.StartInfo.StandardOutputEncoding = Encoding.Unicode;
process.StartInfo.StandardErrorEncoding = Encoding.Unicode;
process.StartInfo.CreateNoWindow = true;
StringBuilder output = new(1024);
StringBuilder error = new(1024);
process.OutputDataReceived += (sender, e) =>
{
using (Process process = new Process())
if (e.Data == null)
{
// Configure the process using the StartInfo properties.
process.StartInfo.FileName = Utils.GetTempPath("sysproxy.exe");
process.StartInfo.Arguments = arguments;
process.StartInfo.WorkingDirectory = Utils.GetTempPath();
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardOutput = true;
// Need to provide encoding info, or output/error strings we got will be wrong.
process.StartInfo.StandardOutputEncoding = Encoding.Unicode;
process.StartInfo.StandardErrorEncoding = Encoding.Unicode;
process.StartInfo.CreateNoWindow = true;
StringBuilder output = new StringBuilder();
StringBuilder error = new StringBuilder();
process.OutputDataReceived += (sender, e) =>
{
if (e.Data == null)
{
outputWaitHandle.Set();
}
else
{
output.AppendLine(e.Data);
}
};
process.ErrorDataReceived += (sender, e) =>
{
if (e.Data == null)
{
errorWaitHandle.Set();
}
else
{
error.AppendLine(e.Data);
}
};
try
{
process.Start();
process.BeginErrorReadLine();
process.BeginOutputReadLine();
process.WaitForExit();
}
catch (System.ComponentModel.Win32Exception e)
{
// log the arguments
throw new Exception(process.StartInfo.Arguments);
}
string stderr = error.ToString();
string stdout = output.ToString();
int exitCode = process.ExitCode;
if (exitCode != (int)RET_ERRORS.RET_NO_ERROR)
{
throw new Exception(stderr);
}
//if (arguments == "query")
//{
// if (stdout.IsNullOrWhiteSpace() || stdout.IsNullOrEmpty())
// {
// throw new Exception("failed to query wininet settings");
// }
// _queryStr = stdout;
//}
outputWaitHandle.Set();
}
else
{
output.AppendLine(e.Data);
}
};
process.ErrorDataReceived += (sender, e) =>
{
if (e.Data == null)
{
errorWaitHandle.Set();
}
else
{
error.AppendLine(e.Data);
}
};
try
{
process.Start();
process.BeginErrorReadLine();
process.BeginOutputReadLine();
process.WaitForExit();
}
catch (System.ComponentModel.Win32Exception e)
{
// log the arguments
throw new Exception(process.StartInfo.Arguments);
}
string stderr = error.ToString();
string stdout = output.ToString();
int exitCode = process.ExitCode;
if (exitCode != (int)RET_ERRORS.RET_NO_ERROR)
{
throw new Exception(stderr);
}
//if (arguments == "query")
//{
// if (stdout.IsNullOrWhiteSpace() || stdout.IsNullOrEmpty())
// {
// throw new Exception("failed to query wininet settings");
// }
// _queryStr = stdout;
//}
}

View File

@@ -3,17 +3,18 @@ using System.IO;
using System.Reactive.Linq;
using v2rayN.Handler;
using v2rayN.Mode;
using v2rayN.Resx;
namespace v2rayN.Base
{
public sealed class TunHandler
{
private static readonly Lazy<TunHandler> _instance = new Lazy<TunHandler>(() => new());
private static readonly Lazy<TunHandler> _instance = new(() => new());
public static TunHandler Instance => _instance.Value;
private string _tunConfigName = "tunConfig.json";
private static Config _config;
private CoreInfo coreInfo;
private Process _process;
private Process? _process;
private static int _socksPort;
private static bool _needRestart = true;
private static bool _isRunning = false;
@@ -60,6 +61,7 @@ namespace v2rayN.Base
{
return;
}
CoreStartTest();
CoreStart();
}
}
@@ -101,6 +103,7 @@ namespace v2rayN.Base
configStr = configStr.Replace("$stack$", $"{_config.tunModeItem.stack}");
//logs
configStr = configStr.Replace("$log_disabled$", $"aaa{(!_config.tunModeItem.enabledLog).ToString().ToLower()}");
if (_config.tunModeItem.showWindow)
{
configStr = configStr.Replace("$log_output$", $"");
@@ -108,7 +111,7 @@ namespace v2rayN.Base
else
{
var dtNow = DateTime.Now;
var log_output = $"\"output\": \"{Utils.GetLogPath($"singbox_{dtNow.ToString("yyyy-MM-dd")}.txt")}\", ";
var log_output = $"\"output\": \"{Utils.GetLogPath($"singbox_{dtNow:yyyy-MM-dd}.txt")}\", ";
configStr = configStr.Replace("$log_output$", $"{log_output.Replace(@"\", @"\\")}");
}
@@ -116,8 +119,8 @@ namespace v2rayN.Base
configStr = configStr.Replace("$socksPort$", $"{_socksPort}");
//exe
List<string> lstDnsExe = new List<string>();
List<string> lstDirectExe = new List<string>();
List<string> lstDnsExe = new();
List<string> lstDirectExe = new();
var coreInfos = LazyConfig.Instance.GetCoreInfos();
foreach (var it in coreInfos)
{
@@ -225,7 +228,8 @@ namespace v2rayN.Base
}
if (Utils.IsNullOrEmpty(fileName))
{
string msg = string.Format(ResUI.NotFoundCore, Utils.GetBinPath("", coreInfo.coreType), string.Join(", ", coreInfo.coreExes.ToArray()), coreInfo.coreUrl);
Utils.SaveLog(msg);
}
return fileName;
}
@@ -235,12 +239,12 @@ namespace v2rayN.Base
try
{
string fileName = CoreFindexe();
if (fileName == "")
if (Utils.IsNullOrEmpty(fileName))
{
return;
}
var showWindow = _config.tunModeItem.showWindow;
Process p = new Process
Process p = new()
{
StartInfo = new ProcessStartInfo
{
@@ -293,5 +297,47 @@ namespace v2rayN.Base
Utils.SaveLog(ex.Message, ex);
}
}
private int CoreStartTest()
{
Utils.SaveLog("Tun mode configuration file test start");
try
{
string fileName = CoreFindexe();
if (fileName == "")
{
return -1;
}
Process p = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = fileName,
Arguments = $"run -c \"{Utils.GetConfigPath(_tunConfigName)}\"",
WorkingDirectory = Utils.GetConfigPath(),
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardError = true,
Verb = "runas",
}
};
p.Start();
if (p.WaitForExit(2000))
{
throw new Exception(p.StandardError.ReadToEnd());
}
KillProcess(p);
return 0;
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
return -1;
}
finally
{
Utils.SaveLog("Tun mode configuration file test end");
}
}
}
}

View File

@@ -35,51 +35,46 @@ namespace v2rayN.Handler
_updateFunc = update;
var url = string.Empty;
DownloadHandle downloadHandle = null;
if (downloadHandle == null)
DownloadHandle downloadHandle = new();
downloadHandle.UpdateCompleted += (sender2, args) =>
{
downloadHandle = new DownloadHandle();
downloadHandle.UpdateCompleted += (sender2, args) =>
if (args.Success)
{
if (args.Success)
{
_updateFunc(false, ResUI.MsgDownloadV2rayCoreSuccessfully);
_updateFunc(false, ResUI.MsgDownloadV2rayCoreSuccessfully);
try
try
{
string fileName = Utils.GetTempPath(Utils.GetDownloadFileName(url));
fileName = Utils.UrlEncode(fileName);
Process process = new()
{
string fileName = Utils.GetTempPath(Utils.GetDownloadFileName(url));
fileName = Utils.UrlEncode(fileName);
Process process = new Process
StartInfo = new ProcessStartInfo
{
StartInfo = new ProcessStartInfo
{
FileName = "v2rayUpgrade.exe",
Arguments = $"\"{fileName}\"",
WorkingDirectory = Utils.StartupPath()
}
};
process.Start();
if (process.Id > 0)
{
_updateFunc(true, "");
FileName = "v2rayUpgrade.exe",
Arguments = $"\"{fileName}\"",
WorkingDirectory = Utils.StartupPath()
}
}
catch (Exception ex)
};
process.Start();
if (process.Id > 0)
{
_updateFunc(false, ex.Message);
_updateFunc(true, "");
}
}
else
catch (Exception ex)
{
_updateFunc(false, args.Msg);
_updateFunc(false, ex.Message);
}
};
downloadHandle.Error += (sender2, args) =>
}
else
{
_updateFunc(false, args.GetException().Message);
};
}
_updateFunc(false, args.Msg);
}
};
downloadHandle.Error += (sender2, args) =>
{
_updateFunc(false, args.GetException().Message);
};
AbsoluteCompleted += (sender2, args) =>
{
if (args.Success)
@@ -106,36 +101,32 @@ namespace v2rayN.Handler
_updateFunc = update;
var url = string.Empty;
DownloadHandle downloadHandle = null;
if (downloadHandle == null)
DownloadHandle downloadHandle = new();
downloadHandle.UpdateCompleted += (sender2, args) =>
{
downloadHandle = new DownloadHandle();
downloadHandle.UpdateCompleted += (sender2, args) =>
if (args.Success)
{
if (args.Success)
{
_updateFunc(false, ResUI.MsgDownloadV2rayCoreSuccessfully);
_updateFunc(false, ResUI.MsgUnpacking);
_updateFunc(false, ResUI.MsgDownloadV2rayCoreSuccessfully);
_updateFunc(false, ResUI.MsgUnpacking);
try
{
_updateFunc(true, url);
}
catch (Exception ex)
{
_updateFunc(false, ex.Message);
}
}
else
try
{
_updateFunc(false, args.Msg);
_updateFunc(true, url);
}
};
downloadHandle.Error += (sender2, args) =>
catch (Exception ex)
{
_updateFunc(false, ex.Message);
}
}
else
{
_updateFunc(true, args.GetException().Message);
};
}
_updateFunc(false, args.Msg);
}
};
downloadHandle.Error += (sender2, args) =>
{
_updateFunc(true, args.GetException().Message);
};
AbsoluteCompleted += (sender2, args) =>
{
@@ -226,7 +217,7 @@ namespace v2rayN.Handler
else
{
_updateFunc(false, $"{hashCode}{ResUI.MsgGetSubscriptionSuccessfully}");
if (result.Length < 99)
if (result!.Length < 99)
{
_updateFunc(false, $"{hashCode}{result}");
}
@@ -262,49 +253,44 @@ namespace v2rayN.Handler
_updateFunc = update;
var url = string.Format(Global.geoUrl, geoName);
DownloadHandle downloadHandle = null;
if (downloadHandle == null)
DownloadHandle downloadHandle = new();
downloadHandle.UpdateCompleted += (sender2, args) =>
{
downloadHandle = new DownloadHandle();
downloadHandle.UpdateCompleted += (sender2, args) =>
if (args.Success)
{
if (args.Success)
_updateFunc(false, string.Format(ResUI.MsgDownloadGeoFileSuccessfully, geoName));
try
{
_updateFunc(false, string.Format(ResUI.MsgDownloadGeoFileSuccessfully, geoName));
try
string fileName = Utils.GetTempPath(Utils.GetDownloadFileName(url));
if (File.Exists(fileName))
{
string fileName = Utils.GetTempPath(Utils.GetDownloadFileName(url));
if (File.Exists(fileName))
{
//Global.coreTypes.ForEach(it =>
//{
// string targetPath = Utils.GetBinPath($"{geoName}.dat", (ECoreType)Enum.Parse(typeof(ECoreType), it));
// File.Copy(fileName, targetPath, true);
//});
string targetPath = Utils.GetBinPath($"{geoName}.dat");
File.Copy(fileName, targetPath, true);
//Global.coreTypes.ForEach(it =>
//{
// string targetPath = Utils.GetBinPath($"{geoName}.dat", (ECoreType)Enum.Parse(typeof(ECoreType), it));
// File.Copy(fileName, targetPath, true);
//});
string targetPath = Utils.GetBinPath($"{geoName}.dat");
File.Copy(fileName, targetPath, true);
File.Delete(fileName);
//_updateFunc(true, "");
}
}
catch (Exception ex)
{
_updateFunc(false, ex.Message);
File.Delete(fileName);
//_updateFunc(true, "");
}
}
else
catch (Exception ex)
{
_updateFunc(false, args.Msg);
_updateFunc(false, ex.Message);
}
};
downloadHandle.Error += (sender2, args) =>
}
else
{
_updateFunc(false, args.GetException().Message);
};
}
_updateFunc(false, args.Msg);
}
};
downloadHandle.Error += (sender2, args) =>
{
_updateFunc(false, args.GetException().Message);
};
askToDownload(downloadHandle, url, false);
}
@@ -374,7 +360,7 @@ namespace v2rayN.Handler
return "";
}
Process p = new Process();
using Process p = new();
p.StartInfo.FileName = filePath;
p.StartInfo.Arguments = coreInfo.versionArg;
p.StartInfo.WorkingDirectory = Utils.StartupPath();

View File

@@ -160,6 +160,7 @@ namespace v2rayN.Mode
{
public bool enableTun { get; set; }
public bool showWindow { get; set; }
public bool enabledLog { get; set; }
public bool strictRoute { get; set; }
public string stack { get; set; }
public int mtu { get; set; }

View File

@@ -0,0 +1,14 @@
using SQLite;
namespace v2rayN.Mode
{
[Serializable]
public class ProfileExItem
{
[PrimaryKey]
public string indexId { get; set; }
public int delay { get; set; }
public decimal speed { get; set; }
public int sort { get; set; }
}
}

View File

@@ -11,7 +11,6 @@ namespace v2rayN.Mode
indexId = string.Empty;
configType = EConfigType.VMess;
configVersion = 2;
sort = 0;
address = string.Empty;
port = 0;
id = string.Empty;
@@ -107,11 +106,6 @@ namespace v2rayN.Mode
get; set;
}
public int sort
{
get; set;
}
/// <summary>
/// 远程服务器地址
/// </summary>
@@ -202,9 +196,6 @@ namespace v2rayN.Mode
get; set;
}
public int delay { get; set; }
public decimal speed { get; set; }
/// <summary>
/// SubItem id
/// </summary>

View File

@@ -5,6 +5,9 @@
{
public bool isActive { get; set; }
public string subRemarks { get; set; }
public int delay { get; set; }
public decimal speed { get; set; }
public int sort { get; set; }
public string delayVal { get; set; }
public string speedVal { get; set; }
public string todayUp { get; set; }

View File

@@ -2564,7 +2564,7 @@ namespace v2rayN.Resx {
}
/// <summary>
/// 查找类似 Record local logs 的本地化字符串。
/// 查找类似 Enable Log 的本地化字符串。
/// </summary>
public static string TbSettingsLogEnabled {
get {
@@ -3068,7 +3068,7 @@ namespace v2rayN.Resx {
}
/// <summary>
/// 查找类似 *QUIC securty 的本地化字符串。
/// 查找类似 *QUIC security 的本地化字符串。
/// </summary>
public static string TransportRequestHostTip4 {
get {

View File

@@ -419,7 +419,7 @@
<value>*h2 host Separated by commas (,)</value>
</data>
<data name="TransportRequestHostTip4" xml:space="preserve">
<value>*QUIC securty</value>
<value>*QUIC security</value>
</data>
<data name="TransportHeaderTypeTip1" xml:space="preserve">
<value>*tcp camouflage type</value>
@@ -815,7 +815,7 @@
<value>Keep older when deduplication</value>
</data>
<data name="TbSettingsLogEnabled" xml:space="preserve">
<value>Record local logs</value>
<value>Enable Log</value>
</data>
<data name="TbSettingsLogLevel" xml:space="preserve">
<value>Log Level</value>

File diff suppressed because it is too large Load Diff

View File

@@ -130,7 +130,7 @@
<value>配置格式不正确</value>
</data>
<data name="CustomServerTips" xml:space="preserve">
<value>注意,自定义配置完全依赖您自己的配置,不能使用所有设置功能。如需使用系统代理请手修改监听端口。</value>
<value>注意,自定义配置完全依赖您自己的配置,不能使用所有设置功能。如需使用系统代理请手修改监听端口。</value>
</data>
<data name="Downloading" xml:space="preserve">
<value>下载开始...</value>
@@ -148,7 +148,7 @@
<value>生成默认配置文件失败</value>
</data>
<data name="FailedGetDefaultConfiguration" xml:space="preserve">
<value>取默认配置失败</value>
<value>取默认配置失败</value>
</data>
<data name="FailedImportedCustomServer" xml:space="preserve">
<value>导入自定义配置服务器失败</value>
@@ -815,7 +815,7 @@
<value>去重时保留序号较小的项</value>
</data>
<data name="TbSettingsLogEnabled" xml:space="preserve">
<value>记录本地日志(默认关闭)</value>
<value>启用日志(默认关闭)</value>
</data>
<data name="TbSettingsLogLevel" xml:space="preserve">
<value>日志等级</value>
@@ -905,7 +905,7 @@
<value>路由</value>
</data>
<data name="NotRunAsAdmin" xml:space="preserve">
<value>以管理员身份运行</value>
<value>以管理员身份运行</value>
</data>
<data name="RunAsAdmin" xml:space="preserve">
<value>以管理员身份运行</value>
@@ -1126,4 +1126,4 @@
<data name="TbSettingsSpeedTestUrl" xml:space="preserve">
<value>测速文件地址</value>
</data>
</root>
</root>

View File

@@ -1,6 +1,6 @@
{
"log": {
"disabled": false,
"disabled": $log_disabled$,
"level": "debug",
$log_output$
"timestamp": true

View File

@@ -10,8 +10,7 @@ namespace v2rayN.Tool
{
try
{
using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write))
fs.Write(content, 0, content.Length);
File.WriteAllBytes(fileName, content);
return true;
}
catch (Exception ex)
@@ -25,20 +24,9 @@ namespace v2rayN.Tool
{
try
{
// Because the uncompressed size of the file is unknown,
// we are using an arbitrary buffer size.
byte[] buffer = new byte[4096];
int n;
using (FileStream fs = File.Create(fileName))
using (GZipStream input = new GZipStream(new MemoryStream(content),
CompressionMode.Decompress, false))
{
while ((n = input.Read(buffer, 0, buffer.Length)) > 0)
{
fs.Write(buffer, 0, n);
}
}
using FileStream fs = File.Create(fileName);
using GZipStream input = new(new MemoryStream(content), CompressionMode.Decompress, false);
input.CopyTo(fs);
}
catch (Exception ex)
{
@@ -55,42 +43,38 @@ namespace v2rayN.Tool
{
try
{
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (StreamReader sr = new StreamReader(fs, encoding))
{
return sr.ReadToEnd();
}
using FileStream fs = new(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using StreamReader sr = new(fs, encoding);
return sr.ReadToEnd();
}
catch (Exception ex)
{
Utils.SaveLog(ex.Message, ex);
throw ex;
throw;
}
}
public static bool ZipExtractToFile(string fileName, string toPath, string ignoredName)
{
try
{
using (ZipArchive archive = ZipFile.OpenRead(fileName))
using ZipArchive archive = ZipFile.OpenRead(fileName);
foreach (ZipArchiveEntry entry in archive.Entries)
{
foreach (ZipArchiveEntry entry in archive.Entries)
if (entry.Length == 0)
{
if (entry.Length == 0)
continue;
}
try
{
if (!Utils.IsNullOrEmpty(ignoredName) && entry.Name.Contains(ignoredName))
{
continue;
}
try
{
if (!Utils.IsNullOrEmpty(ignoredName) && entry.Name.Contains(ignoredName))
{
continue;
}
entry.ExtractToFile(Path.Combine(toPath, entry.Name), true);
}
catch (IOException ex)
{
Utils.SaveLog(ex.Message, ex);
}
entry.ExtractToFile(Path.Combine(toPath, entry.Name), true);
}
catch (IOException ex)
{
Utils.SaveLog(ex.Message, ex);
}
}
}

View File

@@ -16,12 +16,12 @@ namespace v2rayN
{
handle = CreateJobObject(IntPtr.Zero, null);
IntPtr extendedInfoPtr = IntPtr.Zero;
JOBOBJECT_BASIC_LIMIT_INFORMATION info = new JOBOBJECT_BASIC_LIMIT_INFORMATION
JOBOBJECT_BASIC_LIMIT_INFORMATION info = new()
{
LimitFlags = 0x2000
};
JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new()
{
BasicLimitInformation = info
};
@@ -100,7 +100,7 @@ namespace v2rayN
#region Interop
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr CreateJobObject(IntPtr a, string lpName);
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);

View File

@@ -9,8 +9,8 @@ namespace v2rayN.Tool
{
public static void Setup()
{
LoggingConfiguration config = new LoggingConfiguration();
FileTarget fileTarget = new FileTarget();
LoggingConfiguration config = new();
FileTarget fileTarget = new();
config.AddTarget("file", fileTarget);
fileTarget.Layout = "${longdate}-${level:uppercase=true} ${message}";
fileTarget.FileName = Utils.GetLogPath("${shortdate}.txt");

View File

@@ -48,11 +48,10 @@ namespace v2rayN
try
{
Assembly assembly = Assembly.GetExecutingAssembly();
using (Stream stream = assembly.GetManifestResourceStream(res))
using (StreamReader reader = new StreamReader(stream))
{
result = reader.ReadToEnd();
}
using Stream? stream = assembly.GetManifestResourceStream(res);
ArgumentNullException.ThrowIfNull(stream);
using StreamReader reader = new(stream);
result = reader.ReadToEnd();
}
catch (Exception ex)
{
@@ -72,10 +71,12 @@ namespace v2rayN
try
{
using (StreamReader reader = new StreamReader(res))
if (!File.Exists(res))
{
result = reader.ReadToEnd();
return result;
}
using StreamReader reader = new(res);
result = reader.ReadToEnd();
}
catch (Exception ex)
{
@@ -90,7 +91,7 @@ namespace v2rayN
/// <typeparam name="T"></typeparam>
/// <param name="strJson"></param>
/// <returns></returns>
public static T FromJson<T>(string strJson)
public static T? FromJson<T>(string strJson)
{
try
{
@@ -98,8 +99,7 @@ namespace v2rayN
{
return default;
}
T obj = JsonConvert.DeserializeObject<T>(strJson);
return obj;
return JsonConvert.DeserializeObject<T>(strJson);
}
catch
{
@@ -112,7 +112,7 @@ namespace v2rayN
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static string ToJson(Object obj, bool indented = true)
public static string ToJson(object? obj, bool indented = true)
{
string result = string.Empty;
try
@@ -141,25 +141,23 @@ namespace v2rayN
/// <param name="obj"></param>
/// <param name="filePath"></param>
/// <returns></returns>
public static int ToJsonFile(Object obj, string filePath, bool nullValue = true)
public static int ToJsonFile(object? obj, string filePath, bool nullValue = true)
{
int result;
try
{
using (StreamWriter file = File.CreateText(filePath))
using StreamWriter file = File.CreateText(filePath);
JsonSerializer serializer;
if (nullValue)
{
JsonSerializer serializer;
if (nullValue)
{
serializer = new JsonSerializer() { Formatting = Formatting.Indented };
}
else
{
serializer = new JsonSerializer() { Formatting = Formatting.Indented, NullValueHandling = NullValueHandling.Ignore };
}
serializer.Serialize(file, obj);
serializer = new JsonSerializer() { Formatting = Formatting.Indented };
}
else
{
serializer = new JsonSerializer() { Formatting = Formatting.Indented, NullValueHandling = NullValueHandling.Ignore };
}
serializer.Serialize(file, obj);
result = 0;
}
catch (Exception ex)
@@ -170,7 +168,7 @@ namespace v2rayN
return result;
}
public static JObject ParseJson(string strJson)
public static JObject? ParseJson(string strJson)
{
try
{
@@ -202,7 +200,7 @@ namespace v2rayN
}
if (wrap)
{
return string.Join("," + Environment.NewLine, lst.ToArray());
return string.Join("," + Environment.NewLine, lst);
}
else
{
@@ -225,7 +223,7 @@ namespace v2rayN
try
{
str = str.Replace(Environment.NewLine, "");
return new List<string>(str.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries));
return new List<string>(str.Split(',', StringSplitOptions.RemoveEmptyEntries));
}
catch (Exception ex)
{
@@ -244,8 +242,9 @@ namespace v2rayN
try
{
str = str.Replace(Environment.NewLine, "");
List<string> list = new List<string>(str.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries));
return list.OrderBy(x => x).ToList();
List<string> list = new(str.Split(',', StringSplitOptions.RemoveEmptyEntries));
list.Sort();
return list;
}
catch (Exception ex)
{
@@ -337,7 +336,7 @@ namespace v2rayN
{
try
{
return (obj == null ? string.Empty : obj.ToString());
return obj?.ToString() ?? string.Empty;
}
catch (Exception ex)
{
@@ -414,10 +413,9 @@ namespace v2rayN
public static string GetMD5(string str)
{
var md5 = MD5.Create();
byte[] byteOld = Encoding.UTF8.GetBytes(str);
byte[] byteNew = md5.ComputeHash(byteOld);
StringBuilder sb = new StringBuilder();
byte[] byteNew = MD5.HashData(byteOld);
StringBuilder sb = new(32);
foreach (byte b in byteNew)
{
sb.Append(b.ToString("x2"));
@@ -440,7 +438,7 @@ namespace v2rayN
}
try
{
Uri uri = new Uri(url);
Uri uri = new(url);
if (uri.Host == uri.IdnHost)
{
return url;
@@ -568,18 +566,14 @@ namespace v2rayN
public static bool IsIpv6(string ip)
{
IPAddress address;
if (IPAddress.TryParse(ip, out address))
if (IPAddress.TryParse(ip, out IPAddress? address))
{
switch (address.AddressFamily)
return address.AddressFamily switch
{
case AddressFamily.InterNetwork:
return false;
case AddressFamily.InterNetworkV6:
return true;
default:
return false;
}
AddressFamily.InterNetwork => false,
AddressFamily.InterNetworkV6 => true,
_ => false,
};
}
return false;
}
@@ -682,13 +676,13 @@ namespace v2rayN
return Application.StartupPath;
}
public static string RegReadValue(string path, string name, string def)
public static string? RegReadValue(string path, string name, string def)
{
RegistryKey regKey = null;
RegistryKey? regKey = null;
try
{
regKey = Registry.CurrentUser.OpenSubKey(path, false);
string value = regKey?.GetValue(name) as string;
string? value = regKey?.GetValue(name) as string;
if (IsNullOrEmpty(value))
{
return def;
@@ -711,7 +705,7 @@ namespace v2rayN
public static void RegWriteValue(string path, string name, object value)
{
RegistryKey regKey = null;
RegistryKey? regKey = null;
try
{
regKey = Registry.CurrentUser.CreateSubKey(path);
@@ -743,14 +737,12 @@ namespace v2rayN
public static bool CheckForDotNetVersion(int release = 528040)
{
const string subkey = @"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\";
using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey(subkey))
using RegistryKey? ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey(subkey);
if (ndpKey != null && ndpKey.GetValue("Release") != null)
{
if (ndpKey != null && ndpKey.GetValue("Release") != null)
{
return (int)ndpKey.GetValue("Release") >= release ? true : false;
}
return false;
return (int)ndpKey.GetValue("Release") >= release ? true : false;
}
return false;
}
/// <summary>
@@ -771,31 +763,29 @@ namespace v2rayN
string taskDescription = description;
string deamonFileName = fileName;
using (var taskService = new TaskService())
using var taskService = new TaskService();
var tasks = taskService.RootFolder.GetTasks(new Regex(TaskName));
foreach (var t in tasks)
{
var tasks = taskService.RootFolder.GetTasks(new Regex(TaskName));
foreach (var t in tasks)
{
taskService.RootFolder.DeleteTask(t.Name);
}
if (string.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.FromMinutes(1) });
task.Principal.RunLevel = TaskRunLevel.Highest;
task.Actions.Add(new ExecAction(deamonFileName));
taskService.RootFolder.RegisterTaskDefinition(TaskName, task);
taskService.RootFolder.DeleteTask(t.Name);
}
if (string.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.FromMinutes(1) });
task.Principal.RunLevel = TaskRunLevel.Highest;
task.Actions.Add(new ExecAction(deamonFileName));
taskService.RootFolder.RegisterTaskDefinition(TaskName, task);
}
#endregion
@@ -904,16 +894,13 @@ namespace v2rayN
public static T DeepCopy<T>(T obj)
{
object retval;
using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter bf = new BinaryFormatter();
//序列化成流
bf.Serialize(ms, obj);
ms.Seek(0, SeekOrigin.Begin);
//反序列化成对象
retval = bf.Deserialize(ms);
ms.Close();
}
MemoryStream ms = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
//序列化成流
bf.Serialize(ms, obj);
ms.Seek(0, SeekOrigin.Begin);
//反序列化成对象
retval = bf.Deserialize(ms);
return (T)retval;
}
@@ -921,7 +908,7 @@ namespace v2rayN
/// 获取剪贴板数
/// </summary>
/// <returns></returns>
public static string GetClipboardData()
public static string? GetClipboardData()
{
string strData = string.Empty;
try
@@ -1008,7 +995,7 @@ namespace v2rayN
return fileName;
}
public static IPAddress GetDefaultGateway()
public static IPAddress? GetDefaultGateway()
{
return NetworkInterface
.GetAllNetworkInterfaces()
@@ -1071,14 +1058,11 @@ namespace v2rayN
public static string UnGzip(byte[] buf)
{
MemoryStream sb = new MemoryStream();
using (GZipStream input = new GZipStream(new MemoryStream(buf),
CompressionMode.Decompress,
false))
{
input.CopyTo(sb);
}
return Encoding.UTF8.GetString(sb.ToArray());
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)
@@ -1194,42 +1178,40 @@ namespace v2rayN
{
foreach (Screen screen in Screen.AllScreens)
{
using (Bitmap fullImage = new Bitmap(screen.Bounds.Width,
screen.Bounds.Height))
using Bitmap fullImage = new Bitmap(screen.Bounds.Width,
screen.Bounds.Height);
using (Graphics g = Graphics.FromImage(fullImage))
{
using (Graphics g = Graphics.FromImage(fullImage))
g.CopyFromScreen(screen.Bounds.X,
screen.Bounds.Y,
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 Rectangle(marginLeft, marginTop, fullImage.Width - marginLeft * 2, fullImage.Height - marginTop * 2);
Bitmap target = new Bitmap(screen.Bounds.Width, screen.Bounds.Height);
double imageScale = (double)screen.Bounds.Width / (double)cropRect.Width;
using (Graphics g = Graphics.FromImage(target))
{
g.CopyFromScreen(screen.Bounds.X,
screen.Bounds.Y,
0, 0,
fullImage.Size,
CopyPixelOperation.SourceCopy);
g.DrawImage(fullImage, new Rectangle(0, 0, target.Width, target.Height),
cropRect,
GraphicsUnit.Pixel);
}
int maxTry = 10;
for (int i = 0; i < maxTry; i++)
BitmapLuminanceSource source = new BitmapLuminanceSource(target);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader = new QRCodeReader();
Result result = reader.decode(bitmap);
if (result != null)
{
int marginLeft = (int)((double)fullImage.Width * i / 2.5 / maxTry);
int marginTop = (int)((double)fullImage.Height * i / 2.5 / maxTry);
Rectangle cropRect = new Rectangle(marginLeft, marginTop, fullImage.Width - marginLeft * 2, fullImage.Height - marginTop * 2);
Bitmap target = new Bitmap(screen.Bounds.Width, screen.Bounds.Height);
double imageScale = (double)screen.Bounds.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 BitmapLuminanceSource(target);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
QRCodeReader reader = new QRCodeReader();
Result result = reader.decode(bitmap);
if (result != null)
{
string ret = result.Text;
return ret;
}
string ret = result.Text;
return ret;
}
}
}

View File

@@ -106,7 +106,7 @@ namespace v2rayN.ViewModels
{
UI.Show(ResUI.CustomServerTips);
OpenFileDialog fileDialog = new OpenFileDialog
OpenFileDialog fileDialog = new()
{
Multiselect = false,
Filter = "Config|*.json|YAML|*.yaml;*.yml|All|*.*"
@@ -121,10 +121,7 @@ namespace v2rayN.ViewModels
return;
}
var item = LazyConfig.Instance.GetProfileItem(SelectedSource.indexId);
if (item is null)
{
item = SelectedSource;
}
item ??= SelectedSource;
item.address = fileName;
if (ConfigHandler.AddCustomServer(ref _config, item, false) == 0)
{

View File

@@ -37,7 +37,7 @@ namespace v2rayN.ViewModels
private string _serverFilter = string.Empty;
private static Config _config;
private NoticeHandler? _noticeHandler;
private readonly PaletteHelper _paletteHelper = new PaletteHelper();
private readonly PaletteHelper _paletteHelper = new();
private Dictionary<int, bool> _dicHeaderSort = new();
private Action<string> _updateView;
@@ -254,7 +254,7 @@ namespace v2rayN.ViewModels
SystemProxySelected = (int)_config.sysProxyType;
this.WhenAnyValue(
x => x.SystemProxySelected,
y => y != null && y >= 0)
y => y >= 0)
.Subscribe(c => DoSystemProxySelected(c));
this.WhenAnyValue(
@@ -532,7 +532,7 @@ namespace v2rayN.ViewModels
{
_noticeHandler?.SendMessage(msg);
}
private async void UpdateTaskHandler(bool success, string msg)
private void UpdateTaskHandler(bool success, string msg)
{
_noticeHandler?.SendMessage(msg);
if (success)
@@ -664,6 +664,8 @@ namespace v2rayN.ViewModels
SysProxyHandle.UpdateSysProxy(_config, true);
}
ProfileExHandler.Instance.SaveTo();
_statistics?.SaveTo();
_statistics?.Close();
@@ -708,19 +710,19 @@ namespace v2rayN.ViewModels
private void RefreshServers()
{
List<ProfileItemModel> lstModel = LazyConfig.Instance.ProfileItems(_subId, _serverFilter);
_lstProfile = Utils.FromJson<List<ProfileItem>>(Utils.ToJson(lstModel));
ConfigHandler.SetDefaultServer(_config, _lstProfile);
ConfigHandler.SetDefaultServer(_config, lstModel);
List<ServerStatItem> lstServerStat = new();
if (_statistics != null && _statistics.Enable)
{
lstServerStat = _statistics.ServerStat;
}
var lstProfileExs = ProfileExHandler.Instance.ProfileExs;
lstModel = (from t in lstModel
join t2 in lstServerStat
on t.indexId equals t2.indexId into t2b
join t2 in lstServerStat on t.indexId equals t2.indexId into t2b
from t22 in t2b.DefaultIfEmpty()
join t3 in lstProfileExs on t.indexId equals t3.indexId into t3b
from t33 in t3b.DefaultIfEmpty()
select new ProfileItemModel
{
indexId = t.indexId,
@@ -733,14 +735,15 @@ namespace v2rayN.ViewModels
streamSecurity = t.streamSecurity,
subRemarks = t.subRemarks,
isActive = t.indexId == _config.indexId,
delay = t.delay,
delayVal = t.delay != 0 ? $"{t.delay} {Global.DelayUnit}" : string.Empty,
speedVal = t.speed != 0 ? $"{t.speed} {Global.SpeedUnit}" : string.Empty,
sort = t33 == null ? 0 : t33.sort,
delayVal = t33?.delay != 0 ? $"{t33?.delay} {Global.DelayUnit}" : string.Empty,
speedVal = t33?.speed != 0 ? $"{t33?.speed} {Global.SpeedUnit}" : string.Empty,
todayDown = t22 == null ? "" : Utils.HumanFy(t22.todayDown),
todayUp = t22 == null ? "" : Utils.HumanFy(t22.todayUp),
totalDown = t22 == null ? "" : Utils.HumanFy(t22.totalDown),
totalUp = t22 == null ? "" : Utils.HumanFy(t22.totalUp)
}).ToList();
}).OrderBy(t => t.sort).ToList();
_lstProfile = Utils.FromJson<List<ProfileItem>>(Utils.ToJson(lstModel));
Application.Current.Dispatcher.Invoke((Action)(() =>
{
@@ -801,7 +804,14 @@ namespace v2rayN.ViewModels
{
_subItems.Add(item);
}
SelectedSub = _subItems[0];
if (_subId != null && _subItems.FirstOrDefault(t => t.id == _subId) != null)
{
SelectedSub = _subItems.FirstOrDefault(t => t.id == _subId);
}
else
{
SelectedSub = _subItems[0];
}
}
#endregion
@@ -810,7 +820,7 @@ namespace v2rayN.ViewModels
private int GetProfileItems(out List<ProfileItem> lstSelecteds)
{
lstSelecteds = new List<ProfileItem>();
if (SelectedProfiles == null || SelectedProfiles.Count() <= 0)
if (SelectedProfiles == null || SelectedProfiles.Count <= 0)
{
return -1;
}
@@ -834,7 +844,6 @@ namespace v2rayN.ViewModels
{
subid = _subId,
configType = eConfigType,
displayLog = false
};
}
else
@@ -876,6 +885,7 @@ namespace v2rayN.ViewModels
int ret = ConfigHandler.AddBatchServers(ref _config, clipboardData, _subId, false);
if (ret > 0)
{
InitSubscriptionView();
RefreshServers();
_noticeHandler?.Enqueue(string.Format(ResUI.SuccessfullyImportedServerViaClipboard, ret));
}
@@ -900,6 +910,7 @@ namespace v2rayN.ViewModels
int ret = ConfigHandler.AddBatchServers(ref _config, result, _subId, false);
if (ret > 0)
{
InitSubscriptionView();
RefreshServers();
_noticeHandler?.Enqueue(ResUI.SuccessfullyImportedServerViaScan);
}
@@ -974,7 +985,7 @@ namespace v2rayN.ViewModels
return;
}
if (ConfigHandler.SetDefaultServer(ref _config, item) == 0)
if (ConfigHandler.SetDefaultServerIndex(ref _config, indexId) == 0)
{
RefreshServers();
Reload();
@@ -1158,7 +1169,7 @@ namespace v2rayN.ViewModels
return;
}
StringBuilder sb = new StringBuilder();
StringBuilder sb = new();
foreach (var it in lstSelecteds)
{
string url = ShareHandler.GetShareUrl(it);
@@ -1183,10 +1194,10 @@ namespace v2rayN.ViewModels
return;
}
StringBuilder sb = new StringBuilder();
StringBuilder sb = new();
foreach (var it in lstSelecteds)
{
string url = ShareHandler.GetShareUrl(it);
string? url = ShareHandler.GetShareUrl(it);
if (Utils.IsNullOrEmpty(url))
{
continue;
@@ -1257,7 +1268,7 @@ namespace v2rayN.ViewModels
private void ImportOldGuiConfig()
{
OpenFileDialog fileDialog = new OpenFileDialog
OpenFileDialog fileDialog = new()
{
Multiselect = false,
Filter = "guiNConfig|*.json|All|*.*"
@@ -1521,7 +1532,7 @@ namespace v2rayN.ViewModels
public void ShowHideWindow(bool? blShow)
{
var bl = blShow.HasValue ? blShow.Value : !Global.ShowInTaskbar;
var bl = blShow ?? !Global.ShowInTaskbar;
if (bl)
{
//Application.Current.MainWindow.ShowInTaskbar = true;
@@ -1640,7 +1651,7 @@ namespace v2rayN.ViewModels
public void InboundDisplayStaus()
{
StringBuilder sb = new StringBuilder();
StringBuilder sb = new();
sb.Append($"[{Global.InboundSocks}:{LazyConfig.Instance.GetLocalPort(Global.InboundSocks)}]");
sb.Append(" | ");
//if (_config.sysProxyType == ESysProxyType.ForcedChange)
@@ -1651,21 +1662,21 @@ namespace v2rayN.ViewModels
//{
sb.Append($"[{Global.InboundHttp}:{LazyConfig.Instance.GetLocalPort(Global.InboundHttp)}]");
//}
InboundDisplay = $"{ResUI.LabLocal}:{sb.ToString()}";
InboundDisplay = $"{ResUI.LabLocal}:{sb}";
if (_config.inbound[0].allowLANConn)
{
if (_config.inbound[0].newPort4LAN)
{
StringBuilder sb2 = new StringBuilder();
StringBuilder sb2 = new();
sb2.Append($"[{Global.InboundSocks}:{LazyConfig.Instance.GetLocalPort(Global.InboundSocks2)}]");
sb2.Append(" | ");
sb2.Append($"[{Global.InboundHttp}:{LazyConfig.Instance.GetLocalPort(Global.InboundHttp2)}]");
InboundLanDisplay = $"{ResUI.LabLAN}:{sb2.ToString()}";
InboundLanDisplay = $"{ResUI.LabLAN}:{sb2}";
}
else
{
InboundLanDisplay = $"{ResUI.LabLAN}:{sb.ToString()}";
InboundLanDisplay = $"{ResUI.LabLAN}:{sb}";
}
}
else
@@ -1702,10 +1713,10 @@ namespace v2rayN.ViewModels
.Delay(TimeSpan.FromSeconds(1))
.Subscribe(x =>
{
Application.Current.Dispatcher.Invoke((Action)(() =>
Application.Current.Dispatcher.Invoke(() =>
{
ShowHideWindow(false);
}));
});
});
}
}

View File

@@ -75,6 +75,7 @@ namespace v2rayN.ViewModels
#region Tun mode
[Reactive] public bool TunShowWindow { get; set; }
[Reactive] public bool TunEnabledLog { get; set; }
[Reactive] public bool TunStrictRoute { get; set; }
[Reactive] public string TunStack { get; set; }
[Reactive] public int TunMtu { get; set; }
@@ -168,6 +169,7 @@ namespace v2rayN.ViewModels
#region Tun mode
TunShowWindow = _config.tunModeItem.showWindow;
TunEnabledLog = _config.tunModeItem.enabledLog;
TunStrictRoute = _config.tunModeItem.strictRoute;
TunStack = _config.tunModeItem.stack;
TunMtu = _config.tunModeItem.mtu;
@@ -340,6 +342,7 @@ namespace v2rayN.ViewModels
//tun mode
_config.tunModeItem.showWindow = TunShowWindow;
_config.tunModeItem.enabledLog = TunEnabledLog;
_config.tunModeItem.strictRoute = TunStrictRoute;
_config.tunModeItem.stack = TunStack;
_config.tunModeItem.mtu = TunMtu;

View File

@@ -18,6 +18,7 @@
Background="{DynamicResource MaterialDesignPaper}"
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="NoResize"
ShowInTaskbar="False"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"

View File

@@ -11,6 +11,7 @@ namespace v2rayN.Views
public AddServer2Window(ProfileItem profileItem)
{
InitializeComponent();
this.Owner = Application.Current.MainWindow;
this.Loaded += Window_Loaded;
ViewModel = new AddServer2ViewModel(profileItem, this);

View File

@@ -16,6 +16,7 @@
Background="{DynamicResource MaterialDesignPaper}"
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="NoResize"
ShowInTaskbar="False"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"

View File

@@ -16,6 +16,7 @@ namespace v2rayN.Views
public AddServerWindow(ProfileItem profileItem)
{
InitializeComponent();
this.Owner = Application.Current.MainWindow;
this.Loaded += Window_Loaded;
cmbNetwork.SelectionChanged += CmbNetwork_SelectionChanged;
cmbStreamSecurity.SelectionChanged += CmbStreamSecurity_SelectionChanged;

View File

@@ -18,6 +18,7 @@
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
KeyDown="GlobalHotkeySettingWindow_KeyDown"
ResizeMode="NoResize"
ShowInTaskbar="False"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"

View File

@@ -16,6 +16,7 @@ namespace v2rayN.Views
public GlobalHotkeySettingWindow()
{
InitializeComponent();
this.Owner = Application.Current.MainWindow;
_config = LazyConfig.Instance.GetConfig();
if (_config.globalHotkeys == null)

View File

@@ -333,41 +333,34 @@
</materialDesign:PopupBox>
</ToolBar>
</ToolBarTray>
<ToolBarTray DockPanel.Dock="Top">
<ToolBar
HorizontalAlignment="Center"
VerticalAlignment="Center"
ClipToBounds="True"
Style="{StaticResource MaterialDesignToolBar}">
<ListBox
x:Name="lstGroup"
FontSize="{DynamicResource StdFontSize}"
ItemContainerStyle="{StaticResource MyChipListBoxItem}"
Style="{StaticResource MaterialDesignChoiceChipPrimaryOutlineListBox}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding remarks}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button
x:Name="btnAddSub"
Width="30"
Height="30"
Margin="4,0"
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}">
<materialDesign:PackIcon Kind="Plus" />
</Button>
<Separator />
<TextBox
x:Name="txtServerFilter"
Width="100"
Margin="4,0"
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.MsgServerTitle}"
materialDesign:TextFieldAssist.HasClearButton="True"
Style="{StaticResource DefTextBox}" />
</ToolBar>
</ToolBarTray>
<WrapPanel Margin="2" DockPanel.Dock="Top">
<ListBox
x:Name="lstGroup"
FontSize="{DynamicResource StdFontSize}"
ItemContainerStyle="{StaticResource MyChipListBoxItem}"
Style="{StaticResource MaterialDesignChoiceChipPrimaryOutlineListBox}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding remarks}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button
x:Name="btnAddSub"
Width="30"
Height="30"
Margin="4,0"
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}">
<materialDesign:PackIcon Kind="Plus" />
</Button>
<TextBox
x:Name="txtServerFilter"
Width="200"
Margin="4,0"
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.MsgServerTitle}"
materialDesign:TextFieldAssist.HasClearButton="True"
Style="{StaticResource DefTextBox}" />
</WrapPanel>
<materialDesign:ColorZone
Height="50"

View File

@@ -16,6 +16,7 @@
Background="{DynamicResource MaterialDesignPaper}"
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="NoResize"
ShowInTaskbar="False"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"
@@ -815,7 +816,7 @@
</Grid.ColumnDefinitions>
<TextBlock
Grid.Row="1"
Grid.Row="0"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
@@ -823,6 +824,20 @@
Text="{x:Static resx:ResUI.TbSettingsTunModeShowWindow}" />
<ToggleButton
x:Name="togShowWindow"
Grid.Row="0"
Grid.Column="1"
Margin="{StaticResource SettingItemMargin}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource SettingItemMargin}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsLogEnabled}" />
<ToggleButton
x:Name="togEnabledLog"
Grid.Row="1"
Grid.Column="1"
Margin="{StaticResource SettingItemMargin}"

View File

@@ -17,6 +17,7 @@ namespace v2rayN.Views
public OptionSettingWindow()
{
InitializeComponent();
this.Owner = Application.Current.MainWindow;
_config = LazyConfig.Instance.GetConfig();
ViewModel = new OptionSettingViewModel(this);
@@ -171,6 +172,7 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.TunShowWindow, v => v.togShowWindow.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TunEnabledLog, v => v.togEnabledLog.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TunStrictRoute, v => v.togStrictRoute.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TunStack, v => v.cmbStack.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TunMtu, v => v.cmbMtu.Text).DisposeWith(disposables);

View File

@@ -16,6 +16,7 @@
Background="{DynamicResource MaterialDesignPaper}"
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="NoResize"
ShowInTaskbar="False"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"

View File

@@ -12,6 +12,7 @@ namespace v2rayN.Views
public RoutingRuleDetailsWindow(RulesItem rulesItem)
{
InitializeComponent();
this.Owner = Application.Current.MainWindow;
this.Loaded += Window_Loaded;
clbProtocol.SelectionChanged += ClbProtocol_SelectionChanged;
clbInboundTag.SelectionChanged += ClbInboundTag_SelectionChanged;

View File

@@ -16,6 +16,7 @@
Background="{DynamicResource MaterialDesignPaper}"
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="NoResize"
ShowInTaskbar="False"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"

View File

@@ -12,6 +12,7 @@ namespace v2rayN.Views
public RoutingRuleSettingWindow(RoutingItem routingItem)
{
InitializeComponent();
this.Owner = Application.Current.MainWindow;
this.Loaded += Window_Loaded;
this.PreviewKeyDown += RoutingRuleSettingWindow_PreviewKeyDown;
lstRules.SelectionChanged += lstRules_SelectionChanged;

View File

@@ -16,6 +16,7 @@
Background="{DynamicResource MaterialDesignPaper}"
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="NoResize"
ShowInTaskbar="False"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"

View File

@@ -1,5 +1,6 @@
using ReactiveUI;
using System.Reactive.Disposables;
using System.Windows;
using System.Windows.Input;
using v2rayN.Mode;
using v2rayN.ViewModels;
@@ -11,6 +12,7 @@ namespace v2rayN.Views
public RoutingSettingWindow()
{
InitializeComponent();
this.Owner = Application.Current.MainWindow;
this.Closing += RoutingSettingWindow_Closing;
this.PreviewKeyDown += RoutingSettingWindow_PreviewKeyDown;
lstRoutings.SelectionChanged += lstRoutings_SelectionChanged;

View File

@@ -16,6 +16,7 @@
Background="{DynamicResource MaterialDesignPaper}"
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="NoResize"
ShowInTaskbar="False"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"

View File

@@ -11,6 +11,7 @@ namespace v2rayN.Views
public SubEditWindow(SubItem subItem)
{
InitializeComponent();
this.Owner = Application.Current.MainWindow;
this.Loaded += Window_Loaded;
ViewModel = new SubEditViewModel(subItem, this);

View File

@@ -16,6 +16,7 @@
Background="{DynamicResource MaterialDesignPaper}"
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
ResizeMode="NoResize"
ShowInTaskbar="False"
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextOptions.TextFormattingMode="Display"

View File

@@ -1,6 +1,7 @@
using ReactiveUI;
using System.ComponentModel;
using System.Reactive.Disposables;
using System.Windows;
using System.Windows.Input;
using v2rayN.ViewModels;
@@ -11,6 +12,7 @@ namespace v2rayN.Views
public SubSettingWindow()
{
InitializeComponent();
this.Owner = Application.Current.MainWindow;
ViewModel = new SubSettingViewModel(this);
this.Closing += SubSettingWindow_Closing;

View File

@@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
@@ -9,7 +10,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<ApplicationIcon>v2rayN.ico</ApplicationIcon>
<Copyright>Copyright © 2017-2023 (GPLv3)</Copyright>
<FileVersion>6.12</FileVersion>
<FileVersion>6.13</FileVersion>
</PropertyGroup>
<ItemGroup>