mirror of
https://github.com/netchx/netch.git
synced 2026-03-20 18:19:44 +08:00
Update Updater, Configuration
Update MainForm Binding Servers,Modes
This commit is contained in:
@@ -50,13 +50,13 @@ namespace Netch.Forms
|
||||
MessageBoxX.Show(i18N.Translate("Please select an IP"));
|
||||
}
|
||||
|
||||
private void ControlButton_Click(object sender, EventArgs e)
|
||||
private async void ControlButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
Global.Settings.TUNTAP.BypassIPs.Clear();
|
||||
foreach (var ip in IPListBox.Items)
|
||||
Global.Settings.TUNTAP.BypassIPs.Add((string)ip);
|
||||
|
||||
Configuration.Save();
|
||||
await Configuration.SaveAsync();
|
||||
MessageBoxX.Show(i18N.Translate("Saved"));
|
||||
Close();
|
||||
}
|
||||
|
||||
@@ -71,11 +71,15 @@ namespace Netch.Forms
|
||||
// 计算 ComboBox绘制 目标宽度
|
||||
RecordSize();
|
||||
|
||||
LoadServers();
|
||||
// Bind Server
|
||||
ServerComboBox.DataSource = Global.Settings.Server;
|
||||
SelectLastServer();
|
||||
ServerHelper.DelayTestHelper.UpdateInterval();
|
||||
|
||||
// Load and Bind Mode
|
||||
ModeHelper.Load();
|
||||
LoadModes();
|
||||
ModeComboBox.DataSource = Global.Modes;
|
||||
SelectLastMode();
|
||||
|
||||
// 加载翻译
|
||||
TranslateControls();
|
||||
@@ -207,7 +211,7 @@ namespace Netch.Forms
|
||||
|
||||
#region Server
|
||||
|
||||
private void ImportServersFromClipboardToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
private async void ImportServersFromClipboardToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var texts = Clipboard.GetText();
|
||||
if (!string.IsNullOrWhiteSpace(texts))
|
||||
@@ -216,12 +220,11 @@ namespace Netch.Forms
|
||||
Global.Settings.Server.AddRange(servers);
|
||||
NotifyTip(i18N.TranslateFormat("Import {0} server(s) form Clipboard", servers.Count));
|
||||
|
||||
LoadServers();
|
||||
Configuration.Save();
|
||||
await Configuration.SaveAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private void AddServerToolStripMenuItem_Click([NotNull] object? sender, EventArgs? e)
|
||||
private async void AddServerToolStripMenuItem_Click([NotNull] object? sender, EventArgs? e)
|
||||
{
|
||||
if (sender == null)
|
||||
throw new ArgumentNullException(nameof(sender));
|
||||
@@ -231,8 +234,7 @@ namespace Netch.Forms
|
||||
Hide();
|
||||
util.Create();
|
||||
|
||||
LoadServers();
|
||||
Configuration.Save();
|
||||
await Configuration.SaveAsync();
|
||||
Show();
|
||||
}
|
||||
|
||||
@@ -262,7 +264,6 @@ namespace Netch.Forms
|
||||
{
|
||||
Hide();
|
||||
new SubscribeForm().ShowDialog();
|
||||
LoadServers();
|
||||
Show();
|
||||
}
|
||||
|
||||
@@ -291,8 +292,7 @@ namespace Netch.Forms
|
||||
{
|
||||
await Subscription.UpdateServersAsync();
|
||||
|
||||
LoadServers();
|
||||
Configuration.Save();
|
||||
await Configuration.SaveAsync();
|
||||
StatusText(i18N.Translate("Subscription updated"));
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -433,7 +433,7 @@ namespace Netch.Forms
|
||||
{
|
||||
if (exception is not MessageException)
|
||||
{
|
||||
Log.Error(exception, "更新失败");
|
||||
Log.Error(exception, "更新未处理异常");
|
||||
}
|
||||
|
||||
NotifyTip(exception.Message, info: false);
|
||||
@@ -469,7 +469,7 @@ namespace Netch.Forms
|
||||
return;
|
||||
}
|
||||
|
||||
Configuration.Save();
|
||||
await Configuration.SaveAsync();
|
||||
|
||||
// 服务器、模式 需选择
|
||||
if (ServerComboBox.SelectedItem is not Server server)
|
||||
@@ -541,7 +541,6 @@ namespace Netch.Forms
|
||||
{
|
||||
i18N.Load(Global.Settings.Language);
|
||||
TranslateControls();
|
||||
LoadModes();
|
||||
LoadProfiles();
|
||||
}
|
||||
|
||||
@@ -558,13 +557,6 @@ namespace Netch.Forms
|
||||
|
||||
#region Server
|
||||
|
||||
private void LoadServers()
|
||||
{
|
||||
ServerComboBox.Items.Clear();
|
||||
ServerComboBox.Items.AddRange(Global.Settings.Server.Cast<object>().ToArray());
|
||||
SelectLastServer();
|
||||
}
|
||||
|
||||
private void SelectLastServer()
|
||||
{
|
||||
// 如果值合法,选中该位置
|
||||
@@ -582,7 +574,7 @@ namespace Netch.Forms
|
||||
Global.Settings.ServerComboBoxSelectedIndex = ServerComboBox.SelectedIndex;
|
||||
}
|
||||
|
||||
private void EditServerPictureBox_Click(object sender, EventArgs e)
|
||||
private async void EditServerPictureBox_Click(object sender, EventArgs e)
|
||||
{
|
||||
// 当前ServerComboBox中至少有一项
|
||||
if (!(ServerComboBox.SelectedItem is Server server))
|
||||
@@ -596,8 +588,7 @@ namespace Netch.Forms
|
||||
|
||||
Hide();
|
||||
ServerHelper.GetUtilByTypeName(server.Type).Edit(server);
|
||||
LoadServers();
|
||||
Configuration.Save();
|
||||
await Configuration.SaveAsync();
|
||||
Show();
|
||||
}
|
||||
|
||||
@@ -670,21 +661,12 @@ namespace Netch.Forms
|
||||
}
|
||||
|
||||
Global.Settings.Server.Remove(server);
|
||||
LoadServers();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mode
|
||||
|
||||
public void LoadModes()
|
||||
{
|
||||
ModeComboBox.Items.Clear();
|
||||
ModeComboBox.Items.AddRange(Global.Modes.Cast<object>().ToArray());
|
||||
ModeComboBox.Tag = null;
|
||||
SelectLastMode();
|
||||
}
|
||||
|
||||
private void SelectLastMode()
|
||||
{
|
||||
// 如果值合法,选中该位置
|
||||
@@ -1225,7 +1207,7 @@ namespace Netch.Forms
|
||||
Hide();
|
||||
|
||||
if (saveConfiguration)
|
||||
Configuration.Save();
|
||||
await Configuration.SaveAsync();
|
||||
|
||||
foreach (var file in new[] { Constants.TempConfig, Constants.TempRouteFile })
|
||||
if (File.Exists(file))
|
||||
|
||||
@@ -244,7 +244,7 @@ namespace Netch.Forms
|
||||
Show();
|
||||
}
|
||||
|
||||
private void ControlButton_Click(object sender, EventArgs e)
|
||||
private async void ControlButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
Utils.Utils.ComponentIterator(this, component => Utils.Utils.ChangeControlForeColor(component, Color.Black));
|
||||
|
||||
@@ -268,7 +268,7 @@ namespace Netch.Forms
|
||||
|
||||
Utils.Utils.RegisterNetchStartupItem();
|
||||
|
||||
Configuration.Save();
|
||||
await Configuration.SaveAsync();
|
||||
MessageBoxX.Show(i18N.Translate("Saved"));
|
||||
Close();
|
||||
}
|
||||
|
||||
@@ -57,9 +57,9 @@ namespace Netch.Forms
|
||||
Global.Settings.SubscribeLink[index].Enable = SubscribeLinkListView.Items[index].Checked;
|
||||
}
|
||||
|
||||
private void SubscribeForm_FormClosing(object sender, FormClosingEventArgs e)
|
||||
private async void SubscribeForm_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
Configuration.Save();
|
||||
await Configuration.SaveAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace Netch
|
||||
Directory.CreateDirectory(item);
|
||||
|
||||
// 加载配置
|
||||
Configuration.Load();
|
||||
Configuration.LoadAsync().Wait();
|
||||
|
||||
if (!SingleInstance.IsFirstInstance)
|
||||
{
|
||||
|
||||
@@ -94,8 +94,6 @@ namespace Netch.Services
|
||||
|
||||
#region Apply Update
|
||||
|
||||
private static readonly ImmutableArray<string> KeepDirectories = new List<string> { "data", "mode\\Custom", "logging" }.ToImmutableArray();
|
||||
|
||||
private async Task ApplyUpdate()
|
||||
{
|
||||
var mainForm = Global.MainForm;
|
||||
@@ -105,17 +103,7 @@ namespace Netch.Services
|
||||
ModeHelper.SuspendWatcher = true;
|
||||
// Stop and Save
|
||||
await mainForm.Stop();
|
||||
Configuration.Save();
|
||||
|
||||
// Backup Configuration file
|
||||
try
|
||||
{
|
||||
File.Copy(Configuration.SettingFileFullName, Configuration.SettingFileFullName + ".bak", true);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
await Configuration.SaveAsync();
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -123,13 +111,22 @@ namespace Netch.Services
|
||||
var extractPath = Path.Combine(_tempDirectory, "extract");
|
||||
int exitCode;
|
||||
if ((exitCode = Extract(extractPath, true)) != 0)
|
||||
throw new Exception(i18N.Translate($"7za exit with code {exitCode}"));
|
||||
throw new MessageException(i18N.Translate($"7za unexpectedly exited. ({exitCode})"));
|
||||
|
||||
var updateDirectory = Path.Combine(extractPath, "Netch");
|
||||
if (!Directory.Exists(updateDirectory))
|
||||
throw new MessageException(i18N.Translate("Update file top-level directory not exist"));
|
||||
|
||||
var updateMainProgramFilePath = Path.Combine(updateDirectory, "Netch.exe");
|
||||
if (!File.Exists(updateMainProgramFilePath))
|
||||
throw new MessageException(i18N.Translate($"Update file main program not exist"));
|
||||
|
||||
|
||||
// rename install directory files with .old suffix unless in keep folders
|
||||
MarkFilesOld();
|
||||
|
||||
// move {tempDirectory}\extract\Netch to install folder
|
||||
MoveAllFilesOver(Path.Combine(extractPath, "Netch"), _installDirectory);
|
||||
MoveAllFilesOver(updateDirectory, _installDirectory);
|
||||
|
||||
// release mutex, exit
|
||||
mainForm.Invoke(new Action(Netch.SingleInstance.Dispose));
|
||||
@@ -139,33 +136,30 @@ namespace Netch.Services
|
||||
|
||||
private void MarkFilesOld()
|
||||
{
|
||||
// extend keepDirectories relative path to absolute path
|
||||
var extendedKeepDirectories = KeepDirectories.Select(d => Path.Combine(_installDirectory, d)).ToImmutableArray();
|
||||
var keepDirs = new[] { "data", "mode\\Custom", "logging" };
|
||||
|
||||
var keepDirFullPath = keepDirs.Select(d => Path.Combine(_installDirectory, d)).ToImmutableList();
|
||||
|
||||
// weed out keep files
|
||||
List<string> filesToDelete = new();
|
||||
foreach (var file in Directory.GetFiles(_installDirectory, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
if (extendedKeepDirectories.Any(p => file.StartsWith(p)))
|
||||
// skip keep files
|
||||
if (keepDirFullPath.Any(p => file.StartsWith(p)))
|
||||
continue;
|
||||
|
||||
// skip disable state files
|
||||
if (Path.GetFileName(file) is ModeHelper.DisableModeDirectoryFileName)
|
||||
continue;
|
||||
|
||||
filesToDelete.Add(file);
|
||||
}
|
||||
|
||||
// rename files
|
||||
foreach (var file in filesToDelete)
|
||||
try
|
||||
{
|
||||
File.Move(file, file + ".old");
|
||||
}
|
||||
catch(Exception e)
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e,"failed to rename file \"{File}\"",file);
|
||||
Log.Error(e, "failed to rename file \"{File}\"", file);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int Extract(string destDirName, bool overwrite)
|
||||
@@ -182,12 +176,9 @@ namespace Netch.Services
|
||||
if (overwrite)
|
||||
argument.Append(" -y");
|
||||
|
||||
var process = Process.Start(new ProcessStartInfo
|
||||
var process = Process.Start(new ProcessStartInfo(temp7za, argument.ToString())
|
||||
{
|
||||
UseShellExecute = false,
|
||||
WindowStyle = ProcessWindowStyle.Hidden,
|
||||
FileName = temp7za,
|
||||
Arguments = argument.ToString()
|
||||
UseShellExecute = false
|
||||
})!;
|
||||
|
||||
process.WaitForExit();
|
||||
|
||||
@@ -5,6 +5,7 @@ using Netch.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Serilog;
|
||||
|
||||
@@ -79,7 +80,8 @@ namespace Netch.Utils
|
||||
|
||||
var processList = instances.Select(instance => instance.Id).ToList();
|
||||
|
||||
Log.Information("流量统计进程: {Processes}", $"{string.Join(",", instances.Select(instance => $"({instance.Id})" + instance.ProcessName).ToArray())}");
|
||||
Log.Information("流量统计进程: {Processes}",
|
||||
$"{string.Join(",", instances.Select(instance => $"({instance.Id})" + instance.ProcessName).ToArray())}");
|
||||
|
||||
received = 0;
|
||||
|
||||
@@ -118,7 +120,7 @@ namespace Netch.Utils
|
||||
|
||||
while (Global.MainForm.State != State.Stopped)
|
||||
{
|
||||
Task.Delay(1000).Wait();
|
||||
Thread.Sleep(1000);
|
||||
lock (counterLock)
|
||||
Global.MainForm.OnBandwidthUpdated(received);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
using Serilog;
|
||||
|
||||
namespace Netch.Utils
|
||||
@@ -15,7 +16,13 @@ namespace Netch.Utils
|
||||
/// </summary>
|
||||
public static string DataDirectoryFullName => Path.Combine(Global.NetchDir, "data");
|
||||
|
||||
public static string SettingFileFullName => $"{DataDirectoryFullName}\\settings.json";
|
||||
public static string FileFullName => Path.Combine(DataDirectoryFullName, FileName);
|
||||
|
||||
private static string BackupFileFullName => Path.Combine(DataDirectoryFullName, BackupFileName);
|
||||
|
||||
private const string FileName = "settings.json";
|
||||
|
||||
private const string BackupFileName = "settings.json.bak";
|
||||
|
||||
private static readonly JsonSerializerOptions JsonSerializerOptions = Global.NewDefaultJsonSerializerOptions;
|
||||
|
||||
@@ -25,33 +32,44 @@ namespace Netch.Utils
|
||||
JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载配置
|
||||
/// </summary>
|
||||
public static void Load()
|
||||
public static async Task LoadAsync()
|
||||
{
|
||||
if (File.Exists(SettingFileFullName))
|
||||
try
|
||||
{
|
||||
try
|
||||
if (!File.Exists(FileFullName))
|
||||
{
|
||||
using var fileStream = File.OpenRead(SettingFileFullName);
|
||||
var settings = JsonSerializer.DeserializeAsync<Setting>(fileStream, JsonSerializerOptions).Result!;
|
||||
|
||||
CheckSetting(settings);
|
||||
|
||||
Global.Settings = settings;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e,"加载配置异常");
|
||||
Environment.Exit(-1);
|
||||
Global.Settings = null!;
|
||||
await SaveAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
if (await LoadAsyncCore(FileFullName))
|
||||
return;
|
||||
|
||||
Log.Information("尝试加载备份配置文件 {FileName}", BackupFileFullName);
|
||||
await LoadAsyncCore(BackupFileFullName);
|
||||
}
|
||||
else
|
||||
catch (Exception e)
|
||||
{
|
||||
// 保存默认设置
|
||||
Save();
|
||||
Log.Error(e, "加载配置异常");
|
||||
Environment.Exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
private static async ValueTask<bool> LoadAsyncCore(string filename)
|
||||
{
|
||||
try
|
||||
{
|
||||
await using var fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true);
|
||||
var settings = (await JsonSerializer.DeserializeAsync<Setting>(fs, JsonSerializerOptions))!;
|
||||
|
||||
CheckSetting(settings);
|
||||
Global.Settings = settings;
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e, @"从 {FileName} 加载配置异常", filename);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,13 +88,26 @@ namespace Netch.Utils
|
||||
/// <summary>
|
||||
/// 保存配置
|
||||
/// </summary>
|
||||
public static void Save()
|
||||
public static async Task SaveAsync()
|
||||
{
|
||||
if (!Directory.Exists(DataDirectoryFullName))
|
||||
Directory.CreateDirectory(DataDirectoryFullName);
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(DataDirectoryFullName))
|
||||
Directory.CreateDirectory(DataDirectoryFullName);
|
||||
|
||||
using var fileStream = File.Create(SettingFileFullName);
|
||||
JsonSerializer.SerializeAsync(fileStream, Global.Settings, JsonSerializerOptions).Wait();
|
||||
var tempFile = Path.Combine(DataDirectoryFullName, FileFullName + ".tmp");
|
||||
|
||||
await using (var fileStream = new FileStream(tempFile, FileMode.Create, FileAccess.Write, FileShare.None, 4096, true))
|
||||
{
|
||||
await JsonSerializer.SerializeAsync(fileStream, Global.Settings, JsonSerializerOptions);
|
||||
}
|
||||
|
||||
File.Replace(tempFile, FileFullName, BackupFileFullName);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e, "保存配置异常");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,6 @@ namespace Netch.Utils
|
||||
return;
|
||||
|
||||
Load();
|
||||
Global.MainForm.LoadModes();
|
||||
}
|
||||
|
||||
public static string GetRelativePath(string fullName)
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Management;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
using Netch.Models;
|
||||
using Vanara.PInvoke;
|
||||
|
||||
@@ -47,7 +49,11 @@ namespace Netch.Utils
|
||||
if (metric != null)
|
||||
arguments += $"metric={metric} ";
|
||||
|
||||
Utils.ProcessRunHiddenAsync("netsh", arguments).Wait();
|
||||
Process.Start(new ProcessStartInfo("netsh.exe", arguments)
|
||||
{
|
||||
UseShellExecute = false,
|
||||
Verb = "runas"
|
||||
})!.WaitForExit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -228,37 +228,6 @@ namespace Netch.Utils
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task ProcessRunHiddenAsync(string fileName, string arguments = "", bool print = true)
|
||||
{
|
||||
var p = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = fileName,
|
||||
Arguments = arguments,
|
||||
WindowStyle = ProcessWindowStyle.Hidden,
|
||||
Verb = "runas",
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
CreateNoWindow = true
|
||||
}
|
||||
};
|
||||
|
||||
Log.Debug($"{fileName} {arguments}");
|
||||
|
||||
p.Start();
|
||||
var output = await p.StandardOutput.ReadToEndAsync();
|
||||
var error = await p.StandardError.ReadToEndAsync();
|
||||
if (print)
|
||||
{
|
||||
Console.Write(output);
|
||||
Console.Write(error);
|
||||
}
|
||||
|
||||
await p.WaitForExitAsync();
|
||||
}
|
||||
|
||||
public static int SubnetToCidr(string value)
|
||||
{
|
||||
var subnet = IPAddress.Parse(value);
|
||||
|
||||
Reference in New Issue
Block a user