Compare commits

..

18 Commits
7.0.3 ... 7.0.6

Author SHA1 Message Date
2dust
0accf262dc up 7.0.6 2024-11-03 16:49:06 +08:00
2dust
e0eb73bb0a Code clean 2024-11-03 16:45:48 +08:00
2dust
258e822c13 Add exit function to the main interface for Desktop 2024-11-03 14:48:13 +08:00
2dust
4f05b93d63 Bug fix
MainModule FileName only exists in Win32.
2024-11-03 13:44:12 +08:00
2dust
bb661d4f50 Only one instance is allowed to run 2024-11-03 13:30:32 +08:00
2dust
201cfaa922 Fix
https://github.com/2dust/v2rayN/issues/5966
2024-11-02 15:02:30 +08:00
2dust
c339aa349c up PackageReference 2024-11-02 14:42:26 +08:00
2dust
046421f345 Code clean 2024-11-02 14:42:01 +08:00
fonaix
3a2c9e7aaa 修复:日志文本框垂直显示上下空白问题 (#5967) 2024-11-02 10:28:18 +08:00
2dust
0bb6e6bd86 up 7.0.5 2024-11-01 16:54:16 +08:00
2dust
693e8ab157 Add startup auto-start for desktop 2024-11-01 14:54:23 +08:00
2dust
033c16c992 Refactor to select active nodes when updating subscriptions 2024-11-01 10:19:31 +08:00
2dust
6ec61433fb Only update the stable version of the core
https://github.com/2dust/v2rayN/issues/5950
2024-11-01 09:26:15 +08:00
2dust
072f773245 up 7.0.4 2024-10-31 09:59:59 +08:00
2dust
0086f65a96 Bug fix
b7f4fd7469
2024-10-30 08:57:10 +08:00
2dust
281f14f47e Adjustment of preset rule sets 2024-10-28 13:45:39 +08:00
2dust
9fd20ff001 De-duplication after subscription update 2024-10-28 09:38:20 +08:00
2dust
7df90a6034 Bug fix
https://github.com/2dust/v2rayN/issues/5928
2024-10-28 09:16:24 +08:00
39 changed files with 527 additions and 401 deletions

View File

@@ -22,13 +22,13 @@ namespace AmazTool
Console.WriteLine("Try to end the process(尝试结束进程)."); Console.WriteLine("Try to end the process(尝试结束进程).");
try try
{ {
var path = GetPath(V2rayN);
Console.WriteLine(path);
var existing = Process.GetProcessesByName(V2rayN); var existing = Process.GetProcessesByName(V2rayN);
var pp = existing.FirstOrDefault(p => p.MainModule?.FileName != null && p.MainModule?.FileName.Contains(path) == true); foreach (var pp in existing)
{
pp?.Kill(); pp?.Kill();
pp?.WaitForExit(1000); pp?.WaitForExit(1000);
} }
}
catch (Exception ex) catch (Exception ex)
{ {
// Access may be denied without admin right. The user may not be an administrator. // Access may be denied without admin right. The user may not be an administrator.

View File

@@ -37,33 +37,35 @@ namespace ServiceLib.Common
foreach (var filePath in files) foreach (var filePath in files)
{ {
var file = new FileInfo(filePath); var file = new FileInfo(filePath);
if (file.CreationTime < now) if (file.CreationTime >= now) continue;
{
try try
{ {
file.Delete(); file.Delete();
} }
catch { } catch
{
// ignored
} }
} }
} }
catch { } catch
{
// ignored
}
}); });
} }
public static void SaveLog(string strContent) public static void SaveLog(string strContent)
{ {
if (LogManager.IsLoggingEnabled()) if (!LogManager.IsLoggingEnabled()) return;
{
var logger = LogManager.GetLogger("Log1"); LogManager.GetLogger("Log1").Info(strContent);
logger.Info(strContent);
}
} }
public static void SaveLog(string strTitle, Exception ex) public static void SaveLog(string strTitle, Exception ex)
{ {
if (LogManager.IsLoggingEnabled()) if (!LogManager.IsLoggingEnabled()) return;
{
var logger = LogManager.GetLogger("Log2"); var logger = LogManager.GetLogger("Log2");
logger.Debug($"{strTitle},{ex.Message}"); logger.Debug($"{strTitle},{ex.Message}");
logger.Debug(ex.StackTrace); logger.Debug(ex.StackTrace);
@@ -73,5 +75,4 @@ namespace ServiceLib.Common
} }
} }
} }
}
} }

View File

@@ -38,6 +38,7 @@ namespace ServiceLib.Common
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(ex.Message, ex);
} }
return result; return result;
} }
@@ -58,6 +59,7 @@ namespace ServiceLib.Common
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(ex.Message, ex);
} }
return null; return null;
} }
@@ -92,6 +94,7 @@ namespace ServiceLib.Common
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(ex.Message, ex);
} }
return string.Empty; return string.Empty;
} }
@@ -116,6 +119,7 @@ namespace ServiceLib.Common
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(ex.Message, ex);
} }
return null; return null;
} }
@@ -137,6 +141,7 @@ namespace ServiceLib.Common
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(ex.Message, ex);
} }
return null; return null;
} }
@@ -156,6 +161,7 @@ namespace ServiceLib.Common
{ {
Logging.SaveLog("Base64Encode", ex); Logging.SaveLog("Base64Encode", ex);
} }
return string.Empty; return string.Empty;
} }
@@ -189,6 +195,7 @@ namespace ServiceLib.Common
{ {
Logging.SaveLog("Base64Decode", ex); Logging.SaveLog("Base64Decode", ex);
} }
return string.Empty; return string.Empty;
} }
@@ -251,14 +258,17 @@ namespace ServiceLib.Common
unit = "TB"; unit = "TB";
return; return;
} }
result = GBs + ((MBs % factor) / (factor + 0.0)); result = GBs + ((MBs % factor) / (factor + 0.0));
unit = "GB"; unit = "GB";
return; return;
} }
result = MBs + ((KBs % factor) / (factor + 0.0)); result = MBs + ((KBs % factor) / (factor + 0.0));
unit = "MB"; unit = "MB";
return; return;
} }
result = KBs + ((amount % factor) / (factor + 0.0)); result = KBs + ((amount % factor) / (factor + 0.0));
unit = "KB"; unit = "KB";
return; return;
@@ -302,6 +312,7 @@ namespace ServiceLib.Common
{ {
continue; continue;
} }
var key = Uri.UnescapeDataString(keyValue[0]); var key = Uri.UnescapeDataString(keyValue[0]);
var val = Uri.UnescapeDataString(keyValue[1]); var val = Uri.UnescapeDataString(keyValue[1]);
@@ -323,6 +334,7 @@ namespace ServiceLib.Common
{ {
sb.Append(b.ToString("x2")); sb.Append(b.ToString("x2"));
} }
return sb.ToString(); return sb.ToString();
} }
@@ -337,6 +349,7 @@ namespace ServiceLib.Common
{ {
return url; return url;
} }
try try
{ {
Uri uri = new(url); Uri uri = new(url);
@@ -368,6 +381,7 @@ namespace ServiceLib.Common
{ {
return text; return text;
} }
return text.Replace("", ",").Replace(Environment.NewLine, ","); return text.Replace("", ",").Replace(Environment.NewLine, ",");
} }
@@ -391,6 +405,7 @@ namespace ServiceLib.Common
{ {
return true; return true;
} }
return text == "null"; return text == "null";
} }
@@ -424,6 +439,7 @@ namespace ServiceLib.Common
_ => false, _ => false,
}; };
} }
return false; return false;
} }
@@ -448,6 +464,7 @@ namespace ServiceLib.Common
if (ipBytes[0] == 172 && ipBytes[1] >= 16 && ipBytes[1] <= 31) return true; if (ipBytes[0] == 172 && ipBytes[1] >= 16 && ipBytes[1] <= 31) return true;
if (ipBytes[0] == 192 && ipBytes[1] == 168) return true; if (ipBytes[0] == 192 && ipBytes[1] == 168) return true;
} }
return false; return false;
} }
@@ -468,6 +485,7 @@ namespace ServiceLib.Common
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(ex.Message, ex);
} }
return false; return false;
} }
@@ -489,6 +507,7 @@ namespace ServiceLib.Common
catch catch
{ {
} }
return 59090; return 59090;
} }
@@ -512,7 +531,8 @@ namespace ServiceLib.Common
{ {
if (blFull) if (blFull)
{ {
return $"{Global.AppName} - V{GetVersionInfo()} - {RuntimeInformation.ProcessArchitecture} - {File.GetLastWriteTime(GetExePath()):yyyy/MM/dd}"; return
$"{Global.AppName} - V{GetVersionInfo()} - {RuntimeInformation.ProcessArchitecture} - {File.GetLastWriteTime(GetExePath()):yyyy/MM/dd}";
} }
else else
{ {
@@ -523,6 +543,7 @@ namespace ServiceLib.Common
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(ex.Message, ex);
} }
return Global.AppName; return Global.AppName;
} }
@@ -560,6 +581,7 @@ namespace ServiceLib.Common
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(ex.Message, ex);
} }
return string.Empty; return string.Empty;
} }
@@ -572,7 +594,11 @@ namespace ServiceLib.Common
{ {
try try
{ {
if (fileName.IsNullOrEmpty()) { return; } if (fileName.IsNullOrEmpty())
{
return;
}
Process.Start(new ProcessStartInfo(fileName, arguments) { UseShellExecute = true }); Process.Start(new ProcessStartInfo(fileName, arguments) { UseShellExecute = true });
} }
catch (Exception ex) catch (Exception ex)
@@ -605,6 +631,7 @@ namespace ServiceLib.Common
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(ex.Message, ex);
} }
return systemHosts; return systemHosts;
} }
@@ -629,17 +656,20 @@ namespace ServiceLib.Common
cmd = cmd.WithArguments(args); cmd = cmd.WithArguments(args);
} }
} }
var result = await cmd.ExecuteBufferedAsync(); var result = await cmd.ExecuteBufferedAsync();
if (result.IsSuccess) if (result.IsSuccess)
{ {
return result.StandardOutput.ToString(); return result.StandardOutput.ToString();
} }
Logging.SaveLog(result.ToString() ?? ""); Logging.SaveLog(result.ToString() ?? "");
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog("GetCliWrapOutput", ex); Logging.SaveLog("GetCliWrapOutput", ex);
} }
return null; return null;
} }
@@ -654,6 +684,7 @@ namespace ServiceLib.Common
{ {
return startupPath; return startupPath;
} }
return Path.Combine(startupPath, fileName); return Path.Combine(startupPath, fileName);
} }
@@ -674,6 +705,7 @@ namespace ServiceLib.Common
{ {
Directory.CreateDirectory(tempPath); Directory.CreateDirectory(tempPath);
} }
if (IsNullOrEmpty(filename)) if (IsNullOrEmpty(filename))
{ {
return tempPath; return tempPath;
@@ -691,6 +723,7 @@ namespace ServiceLib.Common
{ {
Directory.CreateDirectory(tempPath); Directory.CreateDirectory(tempPath);
} }
return Path.Combine(tempPath, filename); return Path.Combine(tempPath, filename);
} }
@@ -701,6 +734,7 @@ namespace ServiceLib.Common
{ {
Directory.CreateDirectory(tempPath); Directory.CreateDirectory(tempPath);
} }
if (Utils.IsNullOrEmpty(filename)) if (Utils.IsNullOrEmpty(filename))
{ {
return tempPath; return tempPath;
@@ -718,6 +752,7 @@ namespace ServiceLib.Common
{ {
Directory.CreateDirectory(tempPath); Directory.CreateDirectory(tempPath);
} }
if (coreType != null) if (coreType != null)
{ {
tempPath = Path.Combine(tempPath, coreType.ToLower().ToString()); tempPath = Path.Combine(tempPath, coreType.ToLower().ToString());
@@ -726,6 +761,7 @@ namespace ServiceLib.Common
Directory.CreateDirectory(tempPath); Directory.CreateDirectory(tempPath);
} }
} }
if (IsNullOrEmpty(filename)) if (IsNullOrEmpty(filename))
{ {
return tempPath; return tempPath;
@@ -743,6 +779,7 @@ namespace ServiceLib.Common
{ {
Directory.CreateDirectory(tempPath); Directory.CreateDirectory(tempPath);
} }
if (Utils.IsNullOrEmpty(filename)) if (Utils.IsNullOrEmpty(filename))
{ {
return tempPath; return tempPath;
@@ -760,6 +797,7 @@ namespace ServiceLib.Common
{ {
Directory.CreateDirectory(tempPath); Directory.CreateDirectory(tempPath);
} }
if (Utils.IsNullOrEmpty(filename)) if (Utils.IsNullOrEmpty(filename))
{ {
return tempPath; return tempPath;
@@ -825,6 +863,13 @@ namespace ServiceLib.Common
return await GetCliWrapOutput("/bin/bash", arg); return await GetCliWrapOutput("/bin/bash", arg);
} }
public static string? GetHomePath()
{
return IsWindows()
? Environment.ExpandEnvironmentVariables("%HOMEDRIVE%%HOMEPATH%")
: Environment.GetEnvironmentVariable("HOME");
}
#endregion Platform #endregion Platform
} }
} }

View File

@@ -0,0 +1,52 @@
using Microsoft.Win32;
namespace ServiceLib.Common
{
internal static class WindowsUtils
{
public static string? RegReadValue(string path, string name, string def)
{
RegistryKey? regKey = null;
try
{
regKey = Registry.CurrentUser.OpenSubKey(path, false);
var value = regKey?.GetValue(name) as string;
return Utils.IsNullOrEmpty(value) ? def : value;
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
}
finally
{
regKey?.Close();
}
return def;
}
public static void RegWriteValue(string path, string name, object value)
{
RegistryKey? regKey = null;
try
{
regKey = Registry.CurrentUser.CreateSubKey(path);
if (Utils.IsNullOrEmpty(value.ToString()))
{
regKey?.DeleteValue(name, false);
}
else
{
regKey?.SetValue(name, value);
}
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
}
finally
{
regKey?.Close();
}
}
}
}

View File

@@ -5,6 +5,7 @@
ClearMsg, ClearMsg,
SendMsgView, SendMsgView,
SendSnackMsg, SendSnackMsg,
RefreshProfiles RefreshProfiles,
StopSpeedtest
} }
} }

View File

@@ -28,21 +28,24 @@
public const string CoreSpeedtestConfigFileName = "configSpeedtest.json"; public const string CoreSpeedtestConfigFileName = "configSpeedtest.json";
public const string CoreMultipleLoadConfigFileName = "configMultipleLoad.json"; public const string CoreMultipleLoadConfigFileName = "configMultipleLoad.json";
public const string ClashMixinConfigFileName = "Mixin.yaml"; public const string ClashMixinConfigFileName = "Mixin.yaml";
public const string V2raySampleClient = "ServiceLib.Sample.SampleClientConfig";
public const string SingboxSampleClient = "ServiceLib.Sample.SingboxSampleClientConfig"; public const string NamespaceSample = "ServiceLib.Sample.";
public const string V2raySampleHttpRequestFileName = "ServiceLib.Sample.SampleHttpRequest"; public const string V2raySampleClient = NamespaceSample + "SampleClientConfig";
public const string V2raySampleHttpResponseFileName = "ServiceLib.Sample.SampleHttpResponse"; public const string SingboxSampleClient = NamespaceSample + "SingboxSampleClientConfig";
public const string V2raySampleInbound = "ServiceLib.Sample.SampleInbound"; public const string V2raySampleHttpRequestFileName = NamespaceSample + "SampleHttpRequest";
public const string V2raySampleOutbound = "ServiceLib.Sample.SampleOutbound"; public const string V2raySampleHttpResponseFileName = NamespaceSample + "SampleHttpResponse";
public const string SingboxSampleOutbound = "ServiceLib.Sample.SingboxSampleOutbound"; public const string V2raySampleInbound = NamespaceSample + "SampleInbound";
public const string CustomRoutingFileName = "ServiceLib.Sample.custom_routing_"; public const string V2raySampleOutbound = NamespaceSample + "SampleOutbound";
public const string TunSingboxDNSFileName = "ServiceLib.Sample.tun_singbox_dns"; public const string SingboxSampleOutbound = NamespaceSample + "SingboxSampleOutbound";
public const string TunSingboxInboundFileName = "ServiceLib.Sample.tun_singbox_inbound"; public const string CustomRoutingFileName = NamespaceSample + "custom_routing_";
public const string TunSingboxRulesFileName = "ServiceLib.Sample.tun_singbox_rules"; public const string TunSingboxDNSFileName = NamespaceSample + "tun_singbox_dns";
public const string DNSV2rayNormalFileName = "ServiceLib.Sample.dns_v2ray_normal"; public const string TunSingboxInboundFileName = NamespaceSample + "tun_singbox_inbound";
public const string DNSSingboxNormalFileName = "ServiceLib.Sample.dns_singbox_normal"; public const string TunSingboxRulesFileName = NamespaceSample + "tun_singbox_rules";
public const string ClashMixinYaml = "ServiceLib.Sample.clash_mixin_yaml"; public const string DNSV2rayNormalFileName = NamespaceSample + "dns_v2ray_normal";
public const string ClashTunYaml = "ServiceLib.Sample.clash_tun_yaml"; public const string DNSSingboxNormalFileName = NamespaceSample + "dns_singbox_normal";
public const string ClashMixinYaml = NamespaceSample + "clash_mixin_yaml";
public const string ClashTunYaml = NamespaceSample + "clash_tun_yaml";
public const string LinuxAutostartConfig = NamespaceSample + "linux_autostart_config";
public const string DefaultSecurity = "auto"; public const string DefaultSecurity = "auto";
public const string DefaultNetwork = "tcp"; public const string DefaultNetwork = "tcp";

View File

@@ -71,7 +71,7 @@
public bool InitComponents() public bool InitComponents()
{ {
Logging.Setup(); Logging.Setup();
Logging.LoggingEnabled(true); Logging.LoggingEnabled(_config.GuiItem.EnableLog);
Logging.SaveLog($"v2rayN start up | {Utils.GetVersion()} | {Utils.GetExePath()}"); Logging.SaveLog($"v2rayN start up | {Utils.GetVersion()} | {Utils.GetExePath()}");
Logging.SaveLog($"{Environment.OSVersion} - {(Environment.Is64BitOperatingSystem ? 64 : 32)}"); Logging.SaveLog($"{Environment.OSVersion} - {(Environment.Is64BitOperatingSystem ? 64 : 32)}");
Logging.ClearLogs(); Logging.ClearLogs();

View File

@@ -0,0 +1,148 @@
using System.Security.Principal;
using System.Text.RegularExpressions;
namespace ServiceLib.Handler
{
public static class AutoStartupHandler
{
public static async Task<bool> UpdateTask(Config config)
{
if (Utils.IsWindows())
{
await ClearTaskWindows();
if (config.GuiItem.AutoRun)
{
await SetTaskWindows();
}
}
else if (Utils.IsLinux())
{
await ClearTaskLinux();
if (config.GuiItem.AutoRun)
{
await SetTaskLinux();
}
}
return true;
}
#region Windows
private static async Task ClearTaskWindows()
{
var autoRunName = GetAutoRunNameWindows();
WindowsUtils.RegWriteValue(Global.AutoRunRegPath, autoRunName, "");
if (Utils.IsAdministrator())
{
AutoStartTaskService(autoRunName, "", "");
}
}
private static async Task SetTaskWindows()
{
try
{
var autoRunName = GetAutoRunNameWindows();
var exePath = Utils.GetExePath();
if (Utils.IsAdministrator())
{
AutoStartTaskService(autoRunName, exePath, "");
}
else
{
WindowsUtils.RegWriteValue(Global.AutoRunRegPath, autoRunName, exePath.AppendQuotes());
}
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
}
}
/// <summary>
/// Auto Start via TaskService
/// </summary>
/// <param name="taskName"></param>
/// <param name="fileName"></param>
/// <param name="description"></param>
/// <exception cref="ArgumentNullException"></exception>
public static void AutoStartTaskService(string taskName, string fileName, string description)
{
if (Utils.IsNullOrEmpty(taskName))
{
return;
}
var logonUser = WindowsIdentity.GetCurrent().Name;
using var taskService = new Microsoft.Win32.TaskScheduler.TaskService();
var tasks = taskService.RootFolder.GetTasks(new Regex(taskName));
if (Utils.IsNullOrEmpty(fileName))
{
foreach (var t in tasks)
{
taskService.RootFolder.DeleteTask(t.Name);
}
return;
}
var task = taskService.NewTask();
task.RegistrationInfo.Description = description;
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 Microsoft.Win32.TaskScheduler.LogonTrigger { UserId = logonUser, Delay = TimeSpan.FromSeconds(10) });
task.Principal.RunLevel = Microsoft.Win32.TaskScheduler.TaskRunLevel.Highest;
task.Actions.Add(new Microsoft.Win32.TaskScheduler.ExecAction(fileName.AppendQuotes(), null, Path.GetDirectoryName(fileName)));
taskService.RootFolder.RegisterTaskDefinition(taskName, task);
}
private static string GetAutoRunNameWindows()
{
return $"{Global.AutoRunName}_{Utils.GetMd5(Utils.StartupPath())}";
}
#endregion Windows
#region Linux
private static async Task ClearTaskLinux()
{
File.Delete(GetHomePathLinux());
}
private static async Task SetTaskLinux()
{
try
{
var linuxConfig = Utils.GetEmbedText(Global.LinuxAutostartConfig);
if (linuxConfig.IsNotEmpty())
{
linuxConfig = linuxConfig.Replace("$ExecPath$", Utils.GetExePath());
Logging.SaveLog(linuxConfig);
var homePath = GetHomePathLinux();
Directory.CreateDirectory(Path.GetDirectoryName(homePath));
await File.WriteAllTextAsync(homePath, linuxConfig);
}
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
}
}
private static string GetHomePathLinux()
{
return Path.Combine(Utils.GetHomePath(), ".config", "autostart", $"{Global.AppName}.desktop");
}
#endregion Linux
}
}

View File

@@ -1034,14 +1034,14 @@ namespace ServiceLib.Handler
/// <param name="strData"></param> /// <param name="strData"></param>
/// <param name="subid"></param> /// <param name="subid"></param>
/// <returns>成功导入的数量</returns> /// <returns>成功导入的数量</returns>
private static async Task<int> AddBatchServers(Config config, string strData, string subid, bool isSub, List<ProfileItem> lstOriSub) private static async Task<int> AddBatchServersCommon(Config config, string strData, string subid, bool isSub)
{ {
if (Utils.IsNullOrEmpty(strData)) if (Utils.IsNullOrEmpty(strData))
{ {
return -1; return -1;
} }
string subFilter = string.Empty; var subFilter = string.Empty;
//remove sub items //remove sub items
if (isSub && Utils.IsNotEmpty(subid)) if (isSub && Utils.IsNotEmpty(subid))
{ {
@@ -1049,16 +1049,14 @@ namespace ServiceLib.Handler
subFilter = (await AppHandler.Instance.GetSubItem(subid))?.Filter ?? ""; subFilter = (await AppHandler.Instance.GetSubItem(subid))?.Filter ?? "";
} }
int countServers = 0; var countServers = 0;
//Check for duplicate indexId
List<string>? lstDbIndexId = null;
List<ProfileItem> lstAdd = new(); List<ProfileItem> lstAdd = new();
var arrData = strData.Split(Environment.NewLine.ToCharArray()).Where(t => !t.IsNullOrEmpty()); var arrData = strData.Split(Environment.NewLine.ToCharArray()).Where(t => !t.IsNullOrEmpty());
if (isSub) if (isSub)
{ {
arrData = arrData.Distinct(); arrData = arrData.Distinct();
} }
foreach (string str in arrData) foreach (var str in arrData)
{ {
//maybe sub //maybe sub
if (!isSub && (str.StartsWith(Global.HttpsProtocol) || str.StartsWith(Global.HttpProtocol))) if (!isSub && (str.StartsWith(Global.HttpsProtocol) || str.StartsWith(Global.HttpProtocol)))
@@ -1075,37 +1073,14 @@ namespace ServiceLib.Handler
continue; continue;
} }
//exist sub items //exist sub items //filter
if (isSub && Utils.IsNotEmpty(subid)) if (isSub && Utils.IsNotEmpty(subid) && Utils.IsNotEmpty(subFilter))
{
var existItem = lstOriSub?.FirstOrDefault(t => t.IsSub == isSub
&& config.UiItem.EnableUpdateSubOnlyRemarksExist ? t.Remarks == profileItem.Remarks : CompareProfileItem(t, profileItem, true));
if (existItem != null)
{
//Check for duplicate indexId
if (lstDbIndexId is null)
{
lstDbIndexId = await AppHandler.Instance.ProfileItemIndexes("");
}
if (lstAdd.Any(t => t.IndexId == existItem.IndexId)
|| lstDbIndexId.Any(t => t == existItem.IndexId))
{
profileItem.IndexId = string.Empty;
}
else
{
profileItem.IndexId = existItem.IndexId;
}
}
//filter
if (Utils.IsNotEmpty(subFilter))
{ {
if (!Regex.IsMatch(profileItem.Remarks, subFilter)) if (!Regex.IsMatch(profileItem.Remarks, subFilter))
{ {
continue; continue;
} }
} }
}
profileItem.Subid = subid; profileItem.Subid = subid;
profileItem.IsSub = isSub; profileItem.IsSub = isSub;
@@ -1138,7 +1113,7 @@ namespace ServiceLib.Handler
return countServers; return countServers;
} }
private static async Task<int> AddBatchServers4Custom(Config config, string strData, string subid, bool isSub, List<ProfileItem> lstOriSub) private static async Task<int> AddBatchServers4Custom(Config config, string strData, string subid, bool isSub)
{ {
if (Utils.IsNullOrEmpty(strData)) if (Utils.IsNullOrEmpty(strData))
{ {
@@ -1222,10 +1197,7 @@ namespace ServiceLib.Handler
{ {
await RemoveServerViaSubid(config, subid, isSub); await RemoveServerViaSubid(config, subid, isSub);
} }
if (isSub && lstOriSub?.Count == 1)
{
profileItem.IndexId = lstOriSub[0].IndexId;
}
profileItem.Subid = subid; profileItem.Subid = subid;
profileItem.IsSub = isSub; profileItem.IsSub = isSub;
profileItem.PreSocksPort = preSocksPort; profileItem.PreSocksPort = preSocksPort;
@@ -1239,7 +1211,7 @@ namespace ServiceLib.Handler
} }
} }
private static async Task<int> AddBatchServers4SsSIP008(Config config, string strData, string subid, bool isSub, List<ProfileItem> lstOriSub) private static async Task<int> AddBatchServers4SsSIP008(Config config, string strData, string subid, bool isSub)
{ {
if (Utils.IsNullOrEmpty(strData)) if (Utils.IsNullOrEmpty(strData))
{ {
@@ -1278,34 +1250,47 @@ namespace ServiceLib.Handler
return -1; return -1;
} }
List<ProfileItem>? lstOriSub = null; List<ProfileItem>? lstOriSub = null;
ProfileItem? activeProfile = null;
if (isSub && Utils.IsNotEmpty(subid)) if (isSub && Utils.IsNotEmpty(subid))
{ {
lstOriSub = await AppHandler.Instance.ProfileItems(subid); lstOriSub = await AppHandler.Instance.ProfileItems(subid);
activeProfile = lstOriSub?.FirstOrDefault(t => t.IndexId == config.IndexId);
} }
var counter = 0; var counter = 0;
if (Utils.IsBase64String(strData)) if (Utils.IsBase64String(strData))
{ {
counter = await AddBatchServers(config, Utils.Base64Decode(strData), subid, isSub, lstOriSub); counter = await AddBatchServersCommon(config, Utils.Base64Decode(strData), subid, isSub);
} }
if (counter < 1) if (counter < 1)
{ {
counter = await AddBatchServers(config, strData, subid, isSub, lstOriSub); counter = await AddBatchServersCommon(config, strData, subid, isSub);
} }
if (counter < 1) if (counter < 1)
{ {
counter = await AddBatchServers(config, Utils.Base64Decode(strData), subid, isSub, lstOriSub); counter = await AddBatchServersCommon(config, Utils.Base64Decode(strData), subid, isSub);
} }
if (counter < 1) if (counter < 1)
{ {
counter = await AddBatchServers4SsSIP008(config, strData, subid, isSub, lstOriSub); counter = await AddBatchServers4SsSIP008(config, strData, subid, isSub);
} }
//maybe other sub //maybe other sub
if (counter < 1) if (counter < 1)
{ {
counter = await AddBatchServers4Custom(config, strData, subid, isSub, lstOriSub); counter = await AddBatchServers4Custom(config, strData, subid, isSub);
}
//Select active node
if (activeProfile != null)
{
var lstSub = await AppHandler.Instance.ProfileItems(subid);
var existItem = lstSub?.FirstOrDefault(t => config.UiItem.EnableUpdateSubOnlyRemarksExist ? t.Remarks == activeProfile.Remarks : CompareProfileItem(t, activeProfile, true));
if (existItem != null)
{
await ConfigHandler.SetDefaultServerIndex(config, existItem.IndexId);
}
} }
return counter; return counter;

View File

@@ -108,13 +108,11 @@ namespace ServiceLib.Handler
{ {
try try
{ {
bool hasProc = false;
if (_process != null) if (_process != null)
{ {
await KillProcess(_process); await KillProcess(_process);
_process.Dispose(); _process.Dispose();
_process = null; _process = null;
hasProc = true;
} }
if (_processPre != null) if (_processPre != null)
@@ -122,26 +120,6 @@ namespace ServiceLib.Handler
await KillProcess(_processPre); await KillProcess(_processPre);
_processPre.Dispose(); _processPre.Dispose();
_processPre = null; _processPre = null;
hasProc = true;
}
if (!hasProc)
{
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo();
foreach (var it in coreInfo)
{
if (it.CoreType == ECoreType.v2rayN)
{
continue;
}
foreach (var name in it.CoreExes)
{
var path = Utils.GetBinPath(Utils.GetExeName(name), it.CoreType.ToString());
var existing = Process.GetProcessesByName(name);
var pp = existing.FirstOrDefault(p => p.MainModule?.FileName != null && p.MainModule?.FileName.Contains(path) == true);
await KillProcess(pp);
}
}
} }
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -11,24 +11,24 @@ namespace ServiceLib.Handler.SysProxy
{ {
if (type == 1) if (type == 1)
{ {
RegWriteValue(_regPath, "ProxyEnable", 0); WindowsUtils.RegWriteValue(_regPath, "ProxyEnable", 0);
RegWriteValue(_regPath, "ProxyServer", string.Empty); WindowsUtils.RegWriteValue(_regPath, "ProxyServer", string.Empty);
RegWriteValue(_regPath, "ProxyOverride", string.Empty); WindowsUtils.RegWriteValue(_regPath, "ProxyOverride", string.Empty);
RegWriteValue(_regPath, "AutoConfigURL", string.Empty); WindowsUtils.RegWriteValue(_regPath, "AutoConfigURL", string.Empty);
} }
if (type == 2) if (type == 2)
{ {
RegWriteValue(_regPath, "ProxyEnable", 1); WindowsUtils.RegWriteValue(_regPath, "ProxyEnable", 1);
RegWriteValue(_regPath, "ProxyServer", strProxy ?? string.Empty); WindowsUtils.RegWriteValue(_regPath, "ProxyServer", strProxy ?? string.Empty);
RegWriteValue(_regPath, "ProxyOverride", exceptions ?? string.Empty); WindowsUtils.RegWriteValue(_regPath, "ProxyOverride", exceptions ?? string.Empty);
RegWriteValue(_regPath, "AutoConfigURL", string.Empty); WindowsUtils.RegWriteValue(_regPath, "AutoConfigURL", string.Empty);
} }
else if (type == 4) else if (type == 4)
{ {
RegWriteValue(_regPath, "ProxyEnable", 0); WindowsUtils.RegWriteValue(_regPath, "ProxyEnable", 0);
RegWriteValue(_regPath, "ProxyServer", string.Empty); WindowsUtils.RegWriteValue(_regPath, "ProxyServer", string.Empty);
RegWriteValue(_regPath, "ProxyOverride", string.Empty); WindowsUtils.RegWriteValue(_regPath, "ProxyOverride", string.Empty);
RegWriteValue(_regPath, "AutoConfigURL", strProxy ?? string.Empty); WindowsUtils.RegWriteValue(_regPath, "AutoConfigURL", strProxy ?? string.Empty);
} }
return true; return true;
} }
@@ -356,30 +356,5 @@ namespace ServiceLib.Handler.SysProxy
ref int lpcEntries // Number of entries written to the buffer ref int lpcEntries // Number of entries written to the buffer
); );
} }
private static void RegWriteValue(string path, string name, object value)
{
Microsoft.Win32.RegistryKey? regKey = null;
try
{
regKey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(path);
if (string.IsNullOrEmpty(value.ToString()))
{
regKey?.DeleteValue(name, false);
}
else
{
regKey?.SetValue(name, value);
}
}
catch (Exception ex)
{
//Logging.SaveLog(ex.Message, ex);
}
finally
{
regKey?.Close();
}
}
} }
} }

View File

@@ -88,6 +88,8 @@
public int TrayMenuServersLimit { get; set; } = 20; public int TrayMenuServersLimit { get; set; } = 20;
public bool EnableHWA { get; set; } = false; public bool EnableHWA { get; set; } = false;
public bool EnableLog { get; set; } = true;
} }
[Serializable] [Serializable]

View File

@@ -870,6 +870,15 @@ namespace ServiceLib.Resx {
} }
} }
/// <summary>
/// 查找类似 Are you sure to exit? 的本地化字符串。
/// </summary>
public static string menuExitTips {
get {
return ResourceManager.GetString("menuExitTips", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 Export selected server for complete configuration 的本地化字符串。 /// 查找类似 Export selected server for complete configuration 的本地化字符串。
/// </summary> /// </summary>

View File

@@ -1363,4 +1363,7 @@
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve"> <data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
<value>Install the font to the system and restart the settings</value> <value>Install the font to the system and restart the settings</value>
</data> </data>
<data name="menuExitTips" xml:space="preserve">
<value>Are you sure to exit?</value>
</data>
</root> </root>

View File

@@ -1360,4 +1360,7 @@
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve"> <data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
<value>安装字体到系统中,重启设置</value> <value>安装字体到系统中,重启设置</value>
</data> </data>
<data name="menuExitTips" xml:space="preserve">
<value>是否确定退出?</value>
</data>
</root> </root>

View File

@@ -1240,4 +1240,7 @@
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve"> <data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
<value>安裝字體到系統中,重新啟動設定</value> <value>安裝字體到系統中,重新啟動設定</value>
</data> </data>
<data name="menuExitTips" xml:space="preserve">
<value>是否確定退出?</value>
</data>
</root> </root>

View File

@@ -42,15 +42,7 @@
] ]
}, },
{ {
"remarks": "代理GFW", "remarks": "代理IP",
"outboundTag": "proxy",
"domain": [
"geosite:gfw",
"geosite:greatfire"
]
},
{
"remarks": "代理Google等",
"outboundTag": "proxy", "outboundTag": "proxy",
"ip": [ "ip": [
"1.0.0.1", "1.0.0.1",
@@ -65,6 +57,14 @@
"geoip:twitter" "geoip:twitter"
] ]
}, },
{
"remarks": "代理GFW",
"outboundTag": "proxy",
"domain": [
"geosite:gfw",
"geosite:greatfire"
]
},
{ {
"remarks": "最终直连", "remarks": "最终直连",
"port": "0-65535", "port": "0-65535",

View File

@@ -34,19 +34,6 @@
"geosite:private" "geosite:private"
] ]
}, },
{
"remarks": "绕过中国域名",
"outboundTag": "direct",
"domain": [
"domain:dns.alidns.com",
"domain:doh.pub",
"domain:dot.pub",
"domain:doh.360.cn",
"domain:dot.360.cn",
"geosite:cn",
"geosite:geolocation-cn"
]
},
{ {
"remarks": "绕过中国IP", "remarks": "绕过中国IP",
"outboundTag": "direct", "outboundTag": "direct",
@@ -73,6 +60,19 @@
"geoip:cn" "geoip:cn"
] ]
}, },
{
"remarks": "绕过中国域名",
"outboundTag": "direct",
"domain": [
"domain:dns.alidns.com",
"domain:doh.pub",
"domain:dot.pub",
"domain:doh.360.cn",
"domain:dot.360.cn",
"geosite:cn",
"geosite:geolocation-cn"
]
},
{ {
"remarks": "最终代理", "remarks": "最终代理",
"port": "0-65535", "port": "0-65535",

View File

@@ -0,0 +1,10 @@
[Desktop Entry]
Type=Application
Exec=$ExecPath$
Hidden=false
NoDisplay=false
X-GNOME-Autostart-enabled=true
Name[en_US]=v2rayN
Name=v2rayN
Comment[en_US]=v2rayN
Comment=v2rayN

View File

@@ -4,7 +4,7 @@
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<Version>7.0.3</Version> <Version>7.0.6</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -16,9 +16,11 @@
<PackageReference Include="WebDav.Client" Version="2.8.0" /> <PackageReference Include="WebDav.Client" Version="2.8.0" />
<PackageReference Include="YamlDotNet" Version="16.1.3" /> <PackageReference Include="YamlDotNet" Version="16.1.3" />
<PackageReference Include="QRCoder" Version="1.6.0" /> <PackageReference Include="QRCoder" Version="1.6.0" />
<PackageReference Include="CliWrap" Version="3.6.6" /> <PackageReference Include="CliWrap" Version="3.6.7" />
<PackageReference Include="SkiaSharp.QrCode" Version="0.7.0" /> <PackageReference Include="SkiaSharp.QrCode" Version="0.7.0" />
<PackageReference Include="ZXing.Net.Bindings.SkiaSharp" Version="0.16.14" /> <PackageReference Include="ZXing.Net.Bindings.SkiaSharp" Version="0.16.14" />
<PackageReference Include="TaskScheduler" Version="2.11.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -41,6 +43,7 @@
<EmbeddedResource Include="Sample\tun_singbox_dns" /> <EmbeddedResource Include="Sample\tun_singbox_dns" />
<EmbeddedResource Include="Sample\tun_singbox_inbound" /> <EmbeddedResource Include="Sample\tun_singbox_inbound" />
<EmbeddedResource Include="Sample\tun_singbox_rules" /> <EmbeddedResource Include="Sample\tun_singbox_rules" />
<EmbeddedResource Include="Sample\linux_autostart_config" />
</ItemGroup> </ItemGroup>

View File

@@ -1,4 +1,5 @@
using System.Diagnostics; using ReactiveUI;
using System.Diagnostics;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
@@ -80,10 +81,12 @@ namespace ServiceLib.Services
Task.Run(RunMixedtestAsync); Task.Run(RunMixedtestAsync);
break; break;
} }
MessageBus.Current.Listen<string>(EMsgCommand.StopSpeedtest.ToString()).Subscribe(ExitLoop);
} }
public void ExitLoop() private void ExitLoop(string x)
{ {
if (_exitLoop) return;
_exitLoop = true; _exitLoop = true;
UpdateFunc("", ResUI.SpeedtestingStop); UpdateFunc("", ResUI.SpeedtestingStop);
} }

View File

@@ -6,12 +6,10 @@ namespace ServiceLib.Services
public class UpdateService public class UpdateService
{ {
private Action<bool, string>? _updateFunc; private Action<bool, string>? _updateFunc;
private Config _config;
private int _timeout = 30; private int _timeout = 30;
public async Task CheckUpdateGuiN(Config config, Action<bool, string> updateFunc, bool preRelease) public async Task CheckUpdateGuiN(Config config, Action<bool, string> updateFunc, bool preRelease)
{ {
_config = config;
_updateFunc = updateFunc; _updateFunc = updateFunc;
var url = string.Empty; var url = string.Empty;
var fileName = string.Empty; var fileName = string.Empty;
@@ -53,7 +51,6 @@ namespace ServiceLib.Services
public async Task CheckUpdateCore(ECoreType type, Config config, Action<bool, string> updateFunc, bool preRelease) public async Task CheckUpdateCore(ECoreType type, Config config, Action<bool, string> updateFunc, bool preRelease)
{ {
_config = config;
_updateFunc = updateFunc; _updateFunc = updateFunc;
var url = string.Empty; var url = string.Empty;
var fileName = string.Empty; var fileName = string.Empty;
@@ -108,13 +105,12 @@ namespace ServiceLib.Services
public async Task UpdateSubscriptionProcess(Config config, string subId, bool blProxy, Action<bool, string> updateFunc) public async Task UpdateSubscriptionProcess(Config config, string subId, bool blProxy, Action<bool, string> updateFunc)
{ {
_config = config;
_updateFunc = updateFunc; _updateFunc = updateFunc;
_updateFunc?.Invoke(false, ResUI.MsgUpdateSubscriptionStart); _updateFunc?.Invoke(false, ResUI.MsgUpdateSubscriptionStart);
var subItem = await AppHandler.Instance.SubItems(); var subItem = await AppHandler.Instance.SubItems();
if (subItem == null || subItem.Count <= 0) if (subItem is not { Count: > 0 })
{ {
_updateFunc?.Invoke(false, ResUI.MsgNoValidSubscription); _updateFunc?.Invoke(false, ResUI.MsgNoValidSubscription);
return; return;
@@ -122,10 +118,10 @@ namespace ServiceLib.Services
foreach (var item in subItem) foreach (var item in subItem)
{ {
string id = item.Id.TrimEx(); var id = item.Id.TrimEx();
string url = item.Url.TrimEx(); var url = item.Url.TrimEx();
string userAgent = item.UserAgent.TrimEx(); var userAgent = item.UserAgent.TrimEx();
string hashCode = $"{item.Remarks}->"; var hashCode = $"{item.Remarks}->";
if (Utils.IsNullOrEmpty(id) || Utils.IsNullOrEmpty(url) || Utils.IsNotEmpty(subId) && item.Id != subId) if (Utils.IsNullOrEmpty(id) || Utils.IsNullOrEmpty(url) || Utils.IsNotEmpty(subId) && item.Id != subId)
{ {
//_updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgNoValidSubscription}"); //_updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgNoValidSubscription}");
@@ -219,7 +215,7 @@ namespace ServiceLib.Services
_updateFunc?.Invoke(false, $"{hashCode}{result}"); _updateFunc?.Invoke(false, $"{hashCode}{result}");
} }
int ret = await ConfigHandler.AddBatchServers(config, result, id, true); var ret = await ConfigHandler.AddBatchServers(config, result, id, true);
if (ret <= 0) if (ret <= 0)
{ {
Logging.SaveLog("FailedImportSubscription"); Logging.SaveLog("FailedImportSubscription");
@@ -231,6 +227,8 @@ namespace ServiceLib.Services
: $"{hashCode}{ResUI.MsgFailedImportSubscription}"); : $"{hashCode}{ResUI.MsgFailedImportSubscription}");
} }
_updateFunc?.Invoke(false, "-------------------------------------------------------"); _updateFunc?.Invoke(false, "-------------------------------------------------------");
await ConfigHandler.DedupServerList(config, id);
} }
_updateFunc?.Invoke(true, $"{ResUI.MsgUpdateSubscriptionEnd}"); _updateFunc?.Invoke(true, $"{ResUI.MsgUpdateSubscriptionEnd}");
@@ -452,7 +450,6 @@ namespace ServiceLib.Services
private async Task UpdateGeoFile(string geoName, Config config, Action<bool, string> updateFunc) private async Task UpdateGeoFile(string geoName, Config config, Action<bool, string> updateFunc)
{ {
_config = config;
_updateFunc = updateFunc; _updateFunc = updateFunc;
var geoUrl = string.IsNullOrEmpty(config?.ConstItem.GeoSourceUrl) var geoUrl = string.IsNullOrEmpty(config?.ConstItem.GeoSourceUrl)
@@ -468,7 +465,6 @@ namespace ServiceLib.Services
private async Task UpdateSrsFileAll(Config config, Action<bool, string> updateFunc) private async Task UpdateSrsFileAll(Config config, Action<bool, string> updateFunc)
{ {
_config = config;
_updateFunc = updateFunc; _updateFunc = updateFunc;
var geoipFiles = new List<string>(); var geoipFiles = new List<string>();
@@ -519,9 +515,9 @@ namespace ServiceLib.Services
private async Task UpdateSrsFile(string type, string srsName, Config config, Action<bool, string> updateFunc) private async Task UpdateSrsFile(string type, string srsName, Config config, Action<bool, string> updateFunc)
{ {
var srsUrl = string.IsNullOrEmpty(_config.ConstItem.SrsSourceUrl) var srsUrl = string.IsNullOrEmpty(config.ConstItem.SrsSourceUrl)
? Global.SingboxRulesetUrl ? Global.SingboxRulesetUrl
: _config.ConstItem.SrsSourceUrl; : config.ConstItem.SrsSourceUrl;
var fileName = $"{type}-{srsName}.srs"; var fileName = $"{type}-{srsName}.srs";
var targetPath = Path.Combine(Utils.GetBinPath("srss"), fileName); var targetPath = Path.Combine(Utils.GetBinPath("srss"), fileName);

View File

@@ -99,13 +99,13 @@ namespace ServiceLib.ViewModels
{ {
await CheckUpdateN(EnableCheckPreReleaseUpdate); await CheckUpdateN(EnableCheckPreReleaseUpdate);
} }
else if (item.CoreType == ECoreType.mihomo.ToString()) else if (item.CoreType == ECoreType.Xray.ToString())
{ {
await CheckUpdateCore(item, false); await CheckUpdateCore(item, EnableCheckPreReleaseUpdate);
} }
else else
{ {
await CheckUpdateCore(item, EnableCheckPreReleaseUpdate); await CheckUpdateCore(item, false);
} }
} }

View File

@@ -52,6 +52,8 @@ namespace ServiceLib.ViewModels
public ReactiveCommand<Unit, Unit> ReloadCmd { get; } public ReactiveCommand<Unit, Unit> ReloadCmd { get; }
public ReactiveCommand<Unit, Unit> ExitCmd { get; }
[Reactive] [Reactive]
public bool BlReloadEnabled { get; set; } public bool BlReloadEnabled { get; set; }
@@ -187,6 +189,11 @@ namespace ServiceLib.ViewModels
await Reload(); await Reload();
}); });
ExitCmd = ReactiveCommand.CreateFromTask(async () =>
{
await Exit();
});
RegionalPresetDefaultCmd = ReactiveCommand.CreateFromTask(async () => RegionalPresetDefaultCmd = ReactiveCommand.CreateFromTask(async () =>
{ {
await ApplyRegionalPreset(EPresetType.Default); await ApplyRegionalPreset(EPresetType.Default);
@@ -266,7 +273,7 @@ namespace ServiceLib.ViewModels
try try
{ {
Locator.Current.GetService<StatusBarViewModel>()?.UpdateStatistics(update); Locator.Current.GetService<StatusBarViewModel>()?.UpdateStatistics(update);
if ((update.ProxyUp + update.ProxyDown) > 0 && DateTime.Now.Second % 3 == 0) if ((update.ProxyUp + update.ProxyDown) > 0 && DateTime.Now.Second % 9 == 0)
{ {
Locator.Current.GetService<ProfilesViewModel>()?.UpdateStatistics(update); Locator.Current.GetService<ProfilesViewModel>()?.UpdateStatistics(update);
} }
@@ -289,7 +296,7 @@ namespace ServiceLib.ViewModels
await ProfileExHandler.Instance.SaveTo(); await ProfileExHandler.Instance.SaveTo();
await StatisticsHandler.Instance.SaveTo(); await StatisticsHandler.Instance.SaveTo();
StatisticsHandler.Instance.Close(); StatisticsHandler.Instance.Close();
CoreHandler.Instance.CoreStop(); await CoreHandler.Instance.CoreStop();
Logging.SaveLog("MyAppExit End"); Logging.SaveLog("MyAppExit End");
} }
@@ -588,6 +595,16 @@ namespace ServiceLib.ViewModels
} }
} }
private async Task Exit()
{
if (await _updateView?.Invoke(EViewAction.ShowYesNo, null) == false)
{
return;
}
await MyAppExitAsync(false);
}
#endregion core job #endregion core job
#region Presets #region Presets

View File

@@ -349,14 +349,9 @@ namespace ServiceLib.ViewModels
if (await ConfigHandler.SaveConfig(_config) == 0) if (await ConfigHandler.SaveConfig(_config) == 0)
{ {
if (needReboot) await AutoStartupHandler.UpdateTask(_config);
{
NoticeHandler.Instance.Enqueue(ResUI.NeedRebootTips); NoticeHandler.Instance.Enqueue(needReboot ? ResUI.NeedRebootTips : ResUI.OperationSuccess);
}
else
{
NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess);
}
_updateView?.Invoke(EViewAction.CloseWindow, null); _updateView?.Invoke(EViewAction.CloseWindow, null);
} }
else else

View File

@@ -16,7 +16,6 @@ namespace ServiceLib.ViewModels
private List<ProfileItem> _lstProfile; private List<ProfileItem> _lstProfile;
private string _serverFilter = string.Empty; private string _serverFilter = string.Empty;
private Dictionary<string, bool> _dicHeaderSort = new(); private Dictionary<string, bool> _dicHeaderSort = new();
private SpeedtestService? _speedtestHandler;
#endregion private prop #endregion private prop
@@ -686,12 +685,12 @@ namespace ServiceLib.ViewModels
} }
//ClearTestResult(); //ClearTestResult();
_speedtestHandler = new SpeedtestService(_config, lstSelecteds, actionType, UpdateSpeedtestHandler); _ = new SpeedtestService(_config, lstSelecteds, actionType, UpdateSpeedtestHandler);
} }
public void ServerSpeedtestStop() public void ServerSpeedtestStop()
{ {
_speedtestHandler?.ExitLoop(); MessageBus.Current.SendMessage("", EMsgCommand.StopSpeedtest.ToString());
} }
private async Task Export2ClientConfigAsync(bool blClipboard) private async Task Export2ClientConfigAsync(bool blClipboard)

View File

@@ -9,8 +9,6 @@ namespace v2rayN.Desktop;
public partial class App : Application public partial class App : Application
{ {
//public static EventWaitHandle ProgramStarted;
public override void Initialize() public override void Initialize()
{ {
if (!AppHandler.Instance.InitApp()) if (!AppHandler.Instance.InitApp())
@@ -32,7 +30,7 @@ public partial class App : Application
{ {
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{ {
OnStartup(desktop.Args); AppHandler.Instance.InitComponents();
desktop.Exit += OnExit; desktop.Exit += OnExit;
desktop.MainWindow = new MainWindow(); desktop.MainWindow = new MainWindow();
@@ -41,22 +39,6 @@ public partial class App : Application
base.OnFrameworkInitializationCompleted(); base.OnFrameworkInitializationCompleted();
} }
private void OnStartup(string[]? Args)
{
var exePathKey = Utils.GetMd5(Utils.GetExePath());
var rebootas = (Args ?? new string[] { }).Any(t => t == Global.RebootAs);
//ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, exePathKey, out bool bCreatedNew);
//if (!rebootas && !bCreatedNew)
//{
// ProgramStarted.Set();
// Environment.Exit(0);
// return;
//}
AppHandler.Instance.InitComponents();
}
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{ {
if (e.ExceptionObject != null) if (e.ExceptionObject != null)

View File

@@ -5,12 +5,44 @@ namespace v2rayN.Desktop;
internal class Program internal class Program
{ {
public static EventWaitHandle ProgramStarted;
// Initialization code. Don't use any Avalonia, third-party APIs or any // Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break. // yet and stuff might break.
[STAThread] [STAThread]
public static void Main(string[] args) => BuildAvaloniaApp() public static void Main(string[] args)
{
OnStartup(args);
BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args); .StartWithClassicDesktopLifetime(args);
}
private static void OnStartup(string[]? Args)
{
if (Utils.IsWindows())
{
var exePathKey = Utils.GetMd5(Utils.GetExePath());
var rebootas = (Args ?? new string[] { }).Any(t => t == Global.RebootAs);
ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, exePathKey, out bool bCreatedNew);
if (!rebootas && !bCreatedNew)
{
ProgramStarted.Set();
Environment.Exit(0);
return;
}
}
else
{
_ = new Mutex(true, "v2rayN", out var bOnlyOneInstance);
if (!bOnlyOneInstance)
{
Environment.Exit(0);
return;
}
}
}
// Avalonia configuration, don't remove; also used by visual designer. // Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp() public static AppBuilder BuildAvaloniaApp()

View File

@@ -1,5 +1,6 @@
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Notifications;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Styling; using Avalonia.Styling;
@@ -94,6 +95,7 @@ namespace v2rayN.Desktop.ViewModels
x.OfType<TextBox>(), x.OfType<TextBox>(),
x.OfType<TextBlock>(), x.OfType<TextBlock>(),
x.OfType<Menu>(), x.OfType<Menu>(),
x.OfType<ContextMenu>(),
x.OfType<DataGridRow>(), x.OfType<DataGridRow>(),
x.OfType<ListBoxItem>() x.OfType<ListBoxItem>()
)); ));
@@ -120,8 +122,10 @@ namespace v2rayN.Desktop.ViewModels
x.OfType<TextBox>(), x.OfType<TextBox>(),
x.OfType<TextBlock>(), x.OfType<TextBlock>(),
x.OfType<Menu>(), x.OfType<Menu>(),
x.OfType<ContextMenu>(),
x.OfType<DataGridRow>(), x.OfType<DataGridRow>(),
x.OfType<ListBoxItem>() x.OfType<ListBoxItem>(),
x.OfType<WindowNotificationManager>()
)); ));
style.Add(new Setter() style.Add(new Setter()
{ {

View File

@@ -114,7 +114,7 @@
<MenuItem x:Name="menuClose" Padding="8,0"> <MenuItem x:Name="menuClose" Padding="8,0">
<MenuItem.Header> <MenuItem.Header>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<TextBlock Text="{x:Static resx:ResUI.menuClose}" /> <TextBlock Text="{x:Static resx:ResUI.menuExit}" />
</StackPanel> </StackPanel>
</MenuItem.Header> </MenuItem.Header>
</MenuItem> </MenuItem>

View File

@@ -7,6 +7,7 @@ using Avalonia.Interactivity;
using Avalonia.ReactiveUI; using Avalonia.ReactiveUI;
using Avalonia.Threading; using Avalonia.Threading;
using DialogHostAvalonia; using DialogHostAvalonia;
using MsBox.Avalonia.Enums;
using ReactiveUI; using ReactiveUI;
using Splat; using Splat;
using System.ComponentModel; using System.ComponentModel;
@@ -29,13 +30,10 @@ namespace v2rayN.Desktop.Views
_config = AppHandler.Instance.Config; _config = AppHandler.Instance.Config;
_manager = new WindowNotificationManager(TopLevel.GetTopLevel(this)) { MaxItems = 3, Position = NotificationPosition.BottomRight }; _manager = new WindowNotificationManager(TopLevel.GetTopLevel(this)) { MaxItems = 3, Position = NotificationPosition.BottomRight };
//ThreadPool.RegisterWaitForSingleObject(App.ProgramStarted, OnProgramStarted, null, -1, false);
this.Closing += MainWindow_Closing; this.Closing += MainWindow_Closing;
this.KeyDown += MainWindow_KeyDown; this.KeyDown += MainWindow_KeyDown;
menuSettingsSetUWP.Click += menuSettingsSetUWP_Click; menuSettingsSetUWP.Click += menuSettingsSetUWP_Click;
menuPromotion.Click += menuPromotion_Click; menuPromotion.Click += menuPromotion_Click;
menuClose.Click += menuClose_Click;
menuCheckUpdate.Click += MenuCheckUpdate_Click; menuCheckUpdate.Click += MenuCheckUpdate_Click;
menuBackupAndRestore.Click += MenuBackupAndRestore_Click; menuBackupAndRestore.Click += MenuBackupAndRestore_Click;
@@ -82,6 +80,7 @@ namespace v2rayN.Desktop.Views
this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables); this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.ExitCmd, v => v.menuClose).DisposeWith(disposables);
switch (_config.UiItem.MainGirdOrientation) switch (_config.UiItem.MainGirdOrientation)
{ {
@@ -114,6 +113,8 @@ namespace v2rayN.Desktop.Views
this.Title = $"{Utils.GetVersion()} - {(AppHandler.Instance.IsAdministrator ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}"; this.Title = $"{Utils.GetVersion()} - {(AppHandler.Instance.IsAdministrator ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}";
if (Utils.IsWindows()) if (Utils.IsWindows())
{ {
ThreadPool.RegisterWaitForSingleObject(Program.ProgramStarted, OnProgramStarted, null, -1, false);
menuGlobalHotkeySetting.IsVisible = false; menuGlobalHotkeySetting.IsVisible = false;
} }
else else
@@ -158,7 +159,9 @@ namespace v2rayN.Desktop.Views
private void OnProgramStarted(object state, bool timeout) private void OnProgramStarted(object state, bool timeout)
{ {
ShowHideWindow(true); Dispatcher.UIThread.Post(() =>
ShowHideWindow(true),
DispatcherPriority.Default);
} }
private void DelegateSnackMsg(string content) private void DelegateSnackMsg(string content)
@@ -240,6 +243,14 @@ namespace v2rayN.Desktop.Views
Locator.Current.GetService<ProfilesViewModel>()?.AutofitColumnWidthAsync(), Locator.Current.GetService<ProfilesViewModel>()?.AutofitColumnWidthAsync(),
DispatcherPriority.Default); DispatcherPriority.Default);
break; break;
case EViewAction.ShowYesNo:
if (await UI.ShowYesNo(this, ResUI.menuExitTips) == ButtonResult.No)
{
return false;
}
StorageUI();
break;
} }
return await Task.FromResult(true); return await Task.FromResult(true);
@@ -302,12 +313,6 @@ namespace v2rayN.Desktop.Views
} }
} }
private void menuClose_Click(object? sender, RoutedEventArgs e)
{
StorageUI();
ShowHideWindow(false);
}
private void menuPromotion_Click(object? sender, RoutedEventArgs e) private void menuPromotion_Click(object? sender, RoutedEventArgs e)
{ {
Utils.ProcessStart($"{Utils.Base64Decode(Global.PromotionUrl)}?t={DateTime.Now.Ticks}"); Utils.ProcessStart($"{Utils.Base64Decode(Global.PromotionUrl)}?t={DateTime.Now.Ticks}");
@@ -373,9 +378,17 @@ namespace v2rayN.Desktop.Views
this.Focus(); this.Focus();
} }
else else
{
if (Utils.IsWindows())
{ {
this.Hide(); this.Hide();
} }
else
{
this.WindowState = WindowState.Minimized;
}
}
_config.UiItem.ShowInTaskbar = bl; _config.UiItem.ShowInTaskbar = bl;
} }

View File

@@ -83,6 +83,7 @@
Classes="TextArea" Classes="TextArea"
IsReadOnly="True" IsReadOnly="True"
TextAlignment="Left" TextAlignment="Left"
VerticalAlignment="Stretch"
TextWrapping="Wrap"> TextWrapping="Wrap">
<TextBox.ContextMenu> <TextBox.ContextMenu>
<ContextMenu> <ContextMenu>

View File

@@ -377,7 +377,7 @@
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<!--
<TextBlock <TextBlock
Grid.Row="1" Grid.Row="1"
Grid.Column="0" Grid.Column="0"
@@ -390,6 +390,7 @@
Grid.Column="1" Grid.Column="1"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Classes="Margin8" /> Classes="Margin8" />
<!--
<TextBlock <TextBlock
Grid.Row="1" Grid.Row="1"
Grid.Column="2" Grid.Column="2"

View File

@@ -123,7 +123,7 @@ namespace v2rayN.Desktop.Views
this.Bind(ViewModel, vm => vm.hyDownMbps, v => v.txtDownMbps.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.hyDownMbps, v => v.txtDownMbps.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.enableFragment, v => v.togenableFragment.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.enableFragment, v => v.togenableFragment.IsChecked).DisposeWith(disposables);
//this.Bind(ViewModel, vm => vm.AutoRun, v => v.togAutoRun.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.AutoRun, v => v.togAutoRun.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.EnableStatistics, v => v.togEnableStatistics.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.EnableStatistics, v => v.togEnableStatistics.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.KeepOlderDedupl, v => v.togKeepOlderDedupl.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.KeepOlderDedupl, v => v.togKeepOlderDedupl.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.IgnoreGeoUpdateCore, v => v.togIgnoreGeoUpdateCore.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.IgnoreGeoUpdateCore, v => v.togIgnoreGeoUpdateCore.IsChecked).DisposeWith(disposables);
@@ -175,7 +175,6 @@ namespace v2rayN.Desktop.Views
switch (action) switch (action)
{ {
case EViewAction.CloseWindow: case EViewAction.CloseWindow:
// WindowsUtils.SetAutoRun(Global.AutoRunRegPath, Global.AutoRunName, togAutoRun.IsChecked ?? false);
this.Close(true); this.Close(true);
break; break;

View File

@@ -20,16 +20,16 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Avalonia" Version="11.1.4" /> <PackageReference Include="Avalonia" Version="11.2.0" />
<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.1.4" /> <PackageReference Include="Avalonia.Controls.DataGrid" Version="11.2.0" />
<PackageReference Include="Avalonia.Desktop" Version="11.1.4" /> <PackageReference Include="Avalonia.Desktop" Version="11.2.0" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.1.4" /> <PackageReference Include="Avalonia.Fonts.Inter" Version="11.2.0" />
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.1.4" /> <PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.2.0" />
<PackageReference Include="Avalonia.ReactiveUI" Version="11.1.4" /> <PackageReference Include="Avalonia.ReactiveUI" Version="11.2.0" />
<PackageReference Include="DialogHost.Avalonia" Version="0.8.1" /> <PackageReference Include="DialogHost.Avalonia" Version="0.8.1" />
<PackageReference Include="MessageBox.Avalonia" Version="3.1.6.13" /> <PackageReference Include="MessageBox.Avalonia" Version="3.2.0" />
<PackageReference Include="Semi.Avalonia" Version="11.1.0.4" /> <PackageReference Include="Semi.Avalonia" Version="11.2.0" />
<PackageReference Include="Semi.Avalonia.DataGrid" Version="11.1.0.4" /> <PackageReference Include="Semi.Avalonia.DataGrid" Version="11.2.0" />
<PackageReference Include="ReactiveUI" Version="20.1.63" /> <PackageReference Include="ReactiveUI" Version="20.1.63" />
<PackageReference Include="ReactiveUI.Fody" Version="19.5.41" /> <PackageReference Include="ReactiveUI.Fody" Version="19.5.41" />
</ItemGroup> </ItemGroup>

View File

@@ -1,13 +1,9 @@
using Microsoft.Win32; using Microsoft.Win32;
using Microsoft.Win32.TaskScheduler;
using System.Diagnostics; using System.Diagnostics;
using System.Drawing; using System.Drawing;
using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Security.Principal;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
using System.Windows; using System.Windows;
using System.Windows.Interop; using System.Windows.Interop;
using System.Windows.Media; using System.Windows.Media;
@@ -55,49 +51,6 @@ namespace v2rayN
} }
} }
/// <summary>
/// Auto Start via TaskService
/// </summary>
/// <param name="taskName"></param>
/// <param name="fileName"></param>
/// <param name="description"></param>
/// <exception cref="ArgumentNullException"></exception>
public static void AutoStart(string taskName, string fileName, string description)
{
if (Utils.IsNullOrEmpty(taskName))
{
return;
}
string TaskName = taskName;
var logonUser = WindowsIdentity.GetCurrent().Name;
string taskDescription = description;
string deamonFileName = fileName;
using var taskService = new TaskService();
var tasks = taskService.RootFolder.GetTasks(new Regex(TaskName));
foreach (var t in tasks)
{
taskService.RootFolder.DeleteTask(t.Name);
}
if (Utils.IsNullOrEmpty(fileName))
{
return;
}
var task = taskService.NewTask();
task.RegistrationInfo.Description = taskDescription;
task.Settings.DisallowStartIfOnBatteries = false;
task.Settings.StopIfGoingOnBatteries = false;
task.Settings.RunOnlyIfIdle = false;
task.Settings.IdleSettings.StopOnIdleEnd = false;
task.Settings.ExecutionTimeLimit = TimeSpan.Zero;
task.Triggers.Add(new LogonTrigger { UserId = logonUser, Delay = TimeSpan.FromSeconds(10) });
task.Principal.RunLevel = TaskRunLevel.Highest;
task.Actions.Add(new ExecAction(deamonFileName.AppendQuotes(), null, Path.GetDirectoryName(deamonFileName)));
taskService.RootFolder.RegisterTaskDefinition(TaskName, task);
}
[DllImport("dwmapi.dll")] [DllImport("dwmapi.dll")]
public static extern int DwmSetWindowAttribute(IntPtr hwnd, DWMWINDOWATTRIBUTE attribute, ref int attributeValue, uint attributeSize); public static extern int DwmSetWindowAttribute(IntPtr hwnd, DWMWINDOWATTRIBUTE attribute, ref int attributeValue, uint attributeSize);
@@ -116,58 +69,6 @@ namespace v2rayN
return value is int i && i > 0; return value is int i && i > 0;
} }
public static string? RegReadValue(string path, string name, string def)
{
RegistryKey? regKey = null;
try
{
regKey = Registry.CurrentUser.OpenSubKey(path, false);
string? value = regKey?.GetValue(name) as string;
if (Utils.IsNullOrEmpty(value))
{
return def;
}
else
{
return value;
}
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
}
finally
{
regKey?.Close();
}
return def;
}
public static void RegWriteValue(string path, string name, object value)
{
RegistryKey? regKey = null;
try
{
regKey = Registry.CurrentUser.CreateSubKey(path);
if (Utils.IsNullOrEmpty(value.ToString()))
{
regKey?.DeleteValue(name, false);
}
else
{
regKey?.SetValue(name, value);
}
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
}
finally
{
regKey?.Close();
}
}
public static void RemoveTunDevice() public static void RemoveTunDevice()
{ {
try try
@@ -209,42 +110,6 @@ namespace v2rayN
DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, ref attribute, attributeSize); DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, ref attribute, attributeSize);
} }
/// <summary>
/// 开机自动启动
/// </summary>
/// <param name="run"></param>
/// <returns></returns>
public static void SetAutoRun(string AutoRunRegPath, string AutoRunName, bool run)
{
try
{
var autoRunName = $"{AutoRunName}_{Utils.GetMd5(Utils.StartupPath())}";
//delete first
RegWriteValue(AutoRunRegPath, autoRunName, "");
if (Utils.IsAdministrator())
{
AutoStart(autoRunName, "", "");
}
if (run)
{
string exePath = Utils.GetExePath();
if (Utils.IsAdministrator())
{
AutoStart(autoRunName, exePath, "");
}
else
{
RegWriteValue(AutoRunRegPath, autoRunName, exePath.AppendQuotes());
}
}
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
}
}
#region Windows API #region Windows API
[Flags] [Flags]

View File

@@ -367,17 +367,17 @@ namespace v2rayN.Views
var bl = blShow ?? !_config.UiItem.ShowInTaskbar; var bl = blShow ?? !_config.UiItem.ShowInTaskbar;
if (bl) if (bl)
{ {
Application.Current.MainWindow.Show(); this?.Show();
if (Application.Current.MainWindow.WindowState == WindowState.Minimized) if (this?.WindowState == WindowState.Minimized)
{ {
Application.Current.MainWindow.WindowState = WindowState.Normal; this.WindowState = WindowState.Normal;
} }
Application.Current.MainWindow.Activate(); this?.Activate();
Application.Current.MainWindow.Focus(); this?.Focus();
} }
else else
{ {
Application.Current.MainWindow.Hide(); this?.Hide();
} }
_config.UiItem.ShowInTaskbar = bl; _config.UiItem.ShowInTaskbar = bl;
} }

View File

@@ -184,7 +184,6 @@ namespace v2rayN.Views
switch (action) switch (action)
{ {
case EViewAction.CloseWindow: case EViewAction.CloseWindow:
WindowsUtils.SetAutoRun(Global.AutoRunRegPath, Global.AutoRunName, togAutoRun.IsChecked ?? false);
this.DialogResult = true; this.DialogResult = true;
break; break;

View File

@@ -16,7 +16,6 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="MaterialDesignThemes" Version="5.1.0" /> <PackageReference Include="MaterialDesignThemes" Version="5.1.0" />
<PackageReference Include="H.NotifyIcon.Wpf" Version="2.1.4" /> <PackageReference Include="H.NotifyIcon.Wpf" Version="2.1.4" />
<PackageReference Include="TaskScheduler" Version="2.11.0" />
<PackageReference Include="ReactiveUI.Fody" Version="19.5.41" /> <PackageReference Include="ReactiveUI.Fody" Version="19.5.41" />
<PackageReference Include="ReactiveUI.WPF" Version="20.1.63" /> <PackageReference Include="ReactiveUI.WPF" Version="20.1.63" />
</ItemGroup> </ItemGroup>