From 5f671db4f399a57691eaac8e7528e7f431ff158b Mon Sep 17 00:00:00 2001 From: zkhssb Date: Fri, 26 Jan 2024 00:10:04 +0800 Subject: [PATCH 1/9] =?UTF-8?q?ADD:=20=E5=A2=9E=E5=8A=A0=E6=9C=AC=E5=9C=B0?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E6=97=A5=E5=BF=97=20=E4=BE=9D=E8=B5=96Serilo?= =?UTF-8?q?g?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NectarRCON/App.xaml.cs | 26 +++++++--- NectarRCON/NectarRCON.csproj | 3 ++ NectarRCON/Services/ApplicationHostService.cs | 47 +++++++++---------- 3 files changed, 46 insertions(+), 30 deletions(-) diff --git a/NectarRCON/App.xaml.cs b/NectarRCON/App.xaml.cs index 314c866..e6d0317 100644 --- a/NectarRCON/App.xaml.cs +++ b/NectarRCON/App.xaml.cs @@ -9,7 +9,9 @@ using System.Linq; using System.Text; using System.Windows; +using Microsoft.Extensions.Logging; using NectarRCON.Dp; +using Serilog; using Wpf.Ui.Mvvm.Contracts; using Wpf.Ui.Mvvm.Services; @@ -19,10 +21,22 @@ namespace NectarRCON; /// public partial class App { - private static readonly IHost _host = Host + private static readonly ILoggerFactory LoggerFactory = new LoggerFactory(); + private static readonly IHost Host = Microsoft.Extensions.Hosting.Host .CreateDefaultBuilder() + .ConfigureLogging(builder => + { + Log.Logger = new LoggerConfiguration() + .WriteTo.File($"logs/program/log.log", rollingInterval: RollingInterval.Minute, flushToDiskInterval: TimeSpan.FromSeconds(1)) + .CreateLogger(); + + builder.AddSerilog(); + }) .ConfigureServices((context, services) => { + services.AddSingleton(LoggerFactory); + services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); + services.AddHostedService(); services.AddSingleton(); @@ -57,13 +71,13 @@ public partial class App public static T GetService() where T : class { - return (_host.Services.GetService(typeof(T)) as T)!; + return (Host.Services.GetService(typeof(T)) as T)!; } public static T GetService(Type type) where T : class { - return (_host.Services.GetServices().Where(t => t.GetType() == type).FirstOrDefault())!; + return Host.Services.GetServices().FirstOrDefault(t => t.GetType() == type)!; } private async void OnStartup(object sender, StartupEventArgs e) @@ -75,12 +89,12 @@ private async void OnStartup(object sender, StartupEventArgs e) rconEncoding.GetEncoding(); } - await _host.StartAsync(); + await Host.StartAsync(); } private async void OnExit(object sender, ExitEventArgs e) { - await _host.StopAsync(); - _host.Dispose(); + await Host.StopAsync(); + Host.Dispose(); } } diff --git a/NectarRCON/NectarRCON.csproj b/NectarRCON/NectarRCON.csproj index c205304..8460697 100644 --- a/NectarRCON/NectarRCON.csproj +++ b/NectarRCON/NectarRCON.csproj @@ -24,6 +24,9 @@ + + + diff --git a/NectarRCON/Services/ApplicationHostService.cs b/NectarRCON/Services/ApplicationHostService.cs index ceaaf37..ec9a6bb 100644 --- a/NectarRCON/Services/ApplicationHostService.cs +++ b/NectarRCON/Services/ApplicationHostService.cs @@ -8,27 +8,25 @@ using System.Threading; using System.Threading.Tasks; using System.Windows; +using Microsoft.Extensions.Logging; +using Serilog; using Wpf.Ui.Mvvm.Contracts; namespace NectarRCON.Services; -public class ApplicationHostService : IHostedService +public class ApplicationHostService( + IServiceProvider serviceProvider, + INavigationService navigationService, + IThemeService themeService, + ILanguageService languageService, + IConfigService configService) + : IHostedService { - private readonly IServiceProvider _serviceProvider; - private readonly INavigationService _navigationService; - private readonly IThemeService _themeService; - private readonly IConfigService _configService; - private readonly ILanguageService _languageService; + private readonly INavigationService _navigationService = navigationService; private INavigationWindow? _navigationWindow; - public ApplicationHostService(IServiceProvider serviceProvider, INavigationService navigationService, IThemeService themeService, ILanguageService languageService, IConfigService configService) - { - _serviceProvider = serviceProvider; - _navigationService = navigationService; - _themeService = themeService; - _languageService = languageService; - _configService = configService; - } + public async Task StartAsync(CancellationToken cancellationToken) { + Log.Information("Starting NectarRCON..."); await HandleActivationAsync(); } public async Task StopAsync(CancellationToken cancellationToken) @@ -37,29 +35,29 @@ public async Task StopAsync(CancellationToken cancellationToken) } private void LoadConfig() { - switch (_configService.GetConfig().Theme) + switch (configService.GetConfig().Theme) { case ETheme.System: - _themeService.SetTheme(Win32Helper.GetWindowsTheme() ? Wpf.Ui.Appearance.ThemeType.Dark : Wpf.Ui.Appearance.ThemeType.Light); + themeService.SetTheme(Win32Helper.GetWindowsTheme() ? Wpf.Ui.Appearance.ThemeType.Dark : Wpf.Ui.Appearance.ThemeType.Light); break; case ETheme.Dark: - _themeService.SetTheme(Wpf.Ui.Appearance.ThemeType.Dark); + themeService.SetTheme(Wpf.Ui.Appearance.ThemeType.Dark); break; case ETheme.Light: - _themeService.SetTheme(Wpf.Ui.Appearance.ThemeType.Light); + themeService.SetTheme(Wpf.Ui.Appearance.ThemeType.Light); break; default: break; } - if (_configService.GetConfig().LanguageName == string.Empty) + if (configService.GetConfig().LanguageName == string.Empty) { - _languageService.SelectLanguage(); - _configService.GetConfig().LanguageName = _languageService.GetKey("file.language"); - _configService.Save(); + languageService.SelectLanguage(); + configService.GetConfig().LanguageName = languageService.GetKey("file.language"); + configService.Save(); } else { - _languageService.SelectLanguage(_configService.GetConfig().LanguageName, false); + languageService.SelectLanguage(configService.GetConfig().LanguageName, false); } } private async Task HandleActivationAsync() @@ -68,7 +66,8 @@ private async Task HandleActivationAsync() if (!Application.Current.Windows.OfType().Any()) { - _navigationWindow = (_serviceProvider.GetService(typeof(INavigationWindow)) as INavigationWindow)!; + _navigationWindow = (serviceProvider.GetService(typeof(INavigationWindow)) as INavigationWindow)!; + Log.Information("Show MainWindow..."); _navigationWindow!.ShowWindow(); } From 1df52647e11271e98158543ddc529d7aaec7ae0b Mon Sep 17 00:00:00 2001 From: zkhssb Date: Fri, 26 Jan 2024 00:23:31 +0800 Subject: [PATCH 2/9] =?UTF-8?q?upd:=20=E4=BF=AE=E6=94=B9=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E7=9A=84rollingInterval?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NectarRCON/App.xaml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NectarRCON/App.xaml.cs b/NectarRCON/App.xaml.cs index e6d0317..fec374f 100644 --- a/NectarRCON/App.xaml.cs +++ b/NectarRCON/App.xaml.cs @@ -27,7 +27,7 @@ public partial class App .ConfigureLogging(builder => { Log.Logger = new LoggerConfiguration() - .WriteTo.File($"logs/program/log.log", rollingInterval: RollingInterval.Minute, flushToDiskInterval: TimeSpan.FromSeconds(1)) + .WriteTo.File($"logs/program/log{DateTime.Now:yyyyMMddhhmm}.log", rollingInterval: RollingInterval.Infinite, flushToDiskInterval: TimeSpan.FromSeconds(1)) .CreateLogger(); builder.AddSerilog(); From a3a89caf7fa02f6ae6bdc251d48d7d1061919833 Mon Sep 17 00:00:00 2001 From: zkhssb Date: Fri, 26 Jan 2024 00:43:09 +0800 Subject: [PATCH 3/9] =?UTF-8?q?add:=20Rcon=E7=9B=B8=E5=85=B3=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E4=B8=8E=E6=9C=8D=E5=8A=A1=E5=A2=9E=E5=8A=A0=E6=97=A5?= =?UTF-8?q?=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NectarRCON/Rcon/RconMultiConnection.cs | 41 ++++++++---------- NectarRCON/Rcon/RconSingleConnection.cs | 48 +++++++++++----------- NectarRCON/ViewModels/MainPageViewModel.cs | 40 +++++++++++++----- 3 files changed, 71 insertions(+), 58 deletions(-) diff --git a/NectarRCON/Rcon/RconMultiConnection.cs b/NectarRCON/Rcon/RconMultiConnection.cs index 18dc859..0a8f368 100644 --- a/NectarRCON/Rcon/RconMultiConnection.cs +++ b/NectarRCON/Rcon/RconMultiConnection.cs @@ -11,13 +11,19 @@ using System.Security.Authentication; using System.Windows.Controls; using NectarRCON.Dp; +using Serilog; namespace NectarRCON.Services { /// /// Rcon多客户端连接服务 /// - internal class RconMultiConnection : IRconConnection, IDisposable + internal class RconMultiConnection( + IServerPasswordService serverPasswordService, + ILanguageService languageService, + IRconConnectionInfoService rconConnectionInfoService, + IMessageBoxService messageBoxService) + : IRconConnection, IDisposable { private readonly RconSettingsDp _settingsDp = DpFile.LoadSingleton(); public event MessageEvent? OnMessage; @@ -25,21 +31,8 @@ internal class RconMultiConnection : IRconConnection, IDisposable public event RconEvent? OnConnected; public event RconEvent? OnConnecting; - private readonly IServerPasswordService _serverPasswordService; - private readonly ILanguageService _languageService; - private readonly IRconConnectionInfoService _rconConnectionInfoService; - private readonly IMessageBoxService _messageBoxService; - private readonly Dictionary _connections = new(); - private bool _isConnecting = false; - - public RconMultiConnection(IServerPasswordService serverPasswordService, ILanguageService languageService, IRconConnectionInfoService rconConnectionInfoService, IMessageBoxService messageBoxService) - { - _serverPasswordService = serverPasswordService; - _languageService = languageService; - _rconConnectionInfoService = rconConnectionInfoService; - _messageBoxService = messageBoxService; - } + private bool _isConnecting; public void Close() { @@ -54,7 +47,7 @@ public void Connect() { Close(); _isConnecting = true; - var servers = _rconConnectionInfoService.GetInformation(); + var servers = rconConnectionInfoService.GetInformation(); try { foreach (ServerInformation info in servers) @@ -64,7 +57,7 @@ public void Connect() string address = DNSHelpers.SRVQuery(info.Address); if (string.IsNullOrEmpty(address)) // 如果没有SRV记录,就按照原来的样子设置服务器 address = $"{info.Address.Replace("localhost", "127.0.0.1")}:{info.Port}"; - ServerPassword? serverPassword = _serverPasswordService.Get(info); // 从设置中读取Rcon密码 + ServerPassword? serverPassword = serverPasswordService.Get(info); // 从设置中读取Rcon密码 string password = serverPassword?.Password ?? string.Empty; // 创建对应的Rcon客户端实例 @@ -72,9 +65,11 @@ public void Connect() IRconAdapter adapter = AdapterHelpers.CreateAdapterInstance(info.Adapter) ?? throw new InvalidOperationException($"adapter not found: {info.Adapter}"); - string host = address.Split(":")[0]; - int port = int.Parse(address.Split(":")[1]); + var host = address.Split(":")[0]; + var port = int.Parse(address.Split(":")[1]); + Log.Information("[RconMultiConnection] Connecting to {host}:{port}", host, port); + try { adapter.Connect(host, port); @@ -89,7 +84,7 @@ public void Connect() catch (Exception ex) { OnClosed?.Invoke(info); - _messageBoxService.Show(ex, $"Server: \"{info.Name}\""); + messageBoxService.Show(ex, $"Server: \"{info.Name}\""); } //设置编码 @@ -105,7 +100,7 @@ public void Connect() } public bool IsConnected() - => _connections.Where(e => e.Value.IsConnected).Any(); + => _connections.Any(e => e.Value.IsConnected); public bool IsConnecting() => _isConnecting; @@ -126,12 +121,12 @@ public void Send(string command) { connection.Dispose(); // 内部会调用Close OnClosed?.Invoke(info); - OnMessage?.Invoke(info, _languageService.GetKey("service.rcon.offline")); + OnMessage?.Invoke(info, languageService.GetKey("service.rcon.offline")); } } else { - OnMessage?.Invoke(info, _languageService.GetKey("service.rcon.offline")); + OnMessage?.Invoke(info, languageService.GetKey("service.rcon.offline")); } } } diff --git a/NectarRCON/Rcon/RconSingleConnection.cs b/NectarRCON/Rcon/RconSingleConnection.cs index 95ab132..2b4207c 100644 --- a/NectarRCON/Rcon/RconSingleConnection.cs +++ b/NectarRCON/Rcon/RconSingleConnection.cs @@ -9,26 +9,21 @@ using System.Security.Authentication; using System.Windows; using NectarRCON.Dp; +using Serilog; namespace NectarRCON.Services; -public class RconSingleConnection : IRconConnection +public class RconSingleConnection( + IServerPasswordService serverPasswordService, + ILanguageService languageService, + IRconConnectionInfoService rconConnectionInfoService) + : IRconConnection { private readonly RconSettingsDp _settingsDp = DpFile.LoadSingleton(); - private readonly IServerPasswordService _serverPasswordService; - private readonly ILanguageService _languageService; - private readonly IRconConnectionInfoService _rconConnectionInfoService; - - public RconSingleConnection(IServerPasswordService serverPasswordService, ILanguageService languageService, IRconConnectionInfoService rconConnectionInfoService) - { - _serverPasswordService = serverPasswordService; - _languageService = languageService; - _rconConnectionInfoService = rconConnectionInfoService; - } private IRconAdapter? _rconClient = null; - private bool _connecting = false; + private bool _connecting; public event MessageEvent? OnMessage; public event RconEvent? OnClosed; @@ -51,7 +46,7 @@ public void Close() } public void Connect() { - ServerInformation info = _rconConnectionInfoService.GetLastInformation() ?? throw new ArgumentNullException("Internal error, please try again"); + ServerInformation info = rconConnectionInfoService.GetLastInformation() ?? throw new ArgumentNullException("Internal error, please try again"); _connecting = true; OnConnecting?.Invoke(info); try @@ -64,7 +59,7 @@ public void Connect() address = $"{info.Address.Replace("localhost", "127.0.0.1")}:{info.Port}"; - ServerPassword? serverPassword = _serverPasswordService.Get(info); + ServerPassword? serverPassword = serverPasswordService.Get(info); string password = serverPassword?.Password ?? string.Empty; // 创建对应的Rcon客户端实例 @@ -72,9 +67,11 @@ public void Connect() _rconClient = AdapterHelpers.CreateAdapterInstance(info.Adapter) ?? throw new InvalidOperationException($"adapter not found: {info.Adapter}"); _rconClient.SetEncoding(_settingsDp.Encoding.GetEncoding()); - string host = address.Split(":")[0]; - int port = int.Parse(address.Split(":")[1]); + var host = address.Split(":")[0]; + var port = int.Parse(address.Split(":")[1]); + Log.Information("[RconSingleConnection] Connecting to {host}:{port}", host, port); + _rconClient.Connect(host, port); // 连接 if (!_rconClient.Authenticate(password)) @@ -86,8 +83,8 @@ public void Connect() } catch (FormatException ex) { - MessageBox.Show(_languageService.GetKey("ui.text.format_exception") - .Replace("%s", ex.Message), _languageService.GetKey("text.error"), MessageBoxButton.OK, MessageBoxImage.Error); + MessageBox.Show(languageService.GetKey("ui.text.format_exception") + .Replace("%s", ex.Message), languageService.GetKey("text.error"), MessageBoxButton.OK, MessageBoxImage.Error); } finally { @@ -113,36 +110,39 @@ public void Send(string command) Close(); if (ex is SocketException or IOException && _settingsDp.AutoReconnect) { + Log.Information("Rcon连接已经断开,开始自动重连..."); try { Connect(); } - catch + catch (Exception e) { - // ignored + Log.Error("自动重连失败 {err}", e); } if (IsConnected()) { try { + Log.Information("尝试重发命令..."); string result = _rconClient.Run(command); OnMessage?.Invoke(_serverInformation, result); + Log.Information("重发命令成功 -> {command}", command); return; } - catch + catch(Exception e) { - // ignored + Log.Error("尝试重发命令失败 {err}", e); } } } - MessageBox.Show($"{_languageService.GetKey("text.error")}\n{ex.Message}", ex.GetType().FullName, MessageBoxButton.OK, MessageBoxImage.Error); + MessageBox.Show($"{languageService.GetKey("text.error")}\n{ex.Message}", ex.GetType().FullName, MessageBoxButton.OK, MessageBoxImage.Error); } } else { Close(); - MessageBox.Show($"{_languageService.GetKey("text.server.not_connect.text")}", _languageService.GetKey("text.error"), MessageBoxButton.OK, MessageBoxImage.Error); + MessageBox.Show($"{languageService.GetKey("text.server.not_connect.text")}", languageService.GetKey("text.error"), MessageBoxButton.OK, MessageBoxImage.Error); } } } diff --git a/NectarRCON/ViewModels/MainPageViewModel.cs b/NectarRCON/ViewModels/MainPageViewModel.cs index 9b0888d..713d098 100644 --- a/NectarRCON/ViewModels/MainPageViewModel.cs +++ b/NectarRCON/ViewModels/MainPageViewModel.cs @@ -1,4 +1,5 @@ -using CommunityToolkit.Mvvm.ComponentModel; +using System; +using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Messaging; using NectarRCON.Interfaces; @@ -12,6 +13,7 @@ using System.Windows; using System.Windows.Input; using NectarRCON.Dp; +using Serilog; using Wpf.Ui.Mvvm.Contracts; using MessageBox = System.Windows.MessageBox; using TextBox = Wpf.Ui.Controls.TextBox; @@ -65,6 +67,7 @@ private void OnClear(object sender, ClearLogValueMessage msg) private void OnMessage(ServerInformation info, string msg) { + Log.Information("[OnMessage] {name}({adapter}) -> {msg}", info.Name, string.IsNullOrEmpty(info.Adapter) ? "TCPRcon" : info.Adapter, string.IsNullOrEmpty(msg) ? "$empty$" : msg); string logMsg = string.IsNullOrEmpty(msg) ? _languageService.GetKey("ui.main_page.successful") : msg; @@ -92,6 +95,7 @@ private async void Load(RoutedEventArgs e) [RelayCommand] private async void ReConnect() { + Log.Information($"[ReConnectCommand] 正在准备重连"); if (_rconConnectService.IsConnected()) _rconConnectService.Close(); IsDisconnection = false; @@ -100,6 +104,8 @@ private async void ReConnect() private async Task ConnectAsync() { + Log.Information($"[ConnectAsync] 准备连接到服务器"); + IsMultipleConnection = _rconConnectionInfoService.HasMultipleInformation; _rconConnectService.OnConnected -= OnConnected; _rconConnectService.OnMessage -= OnMessage; @@ -117,6 +123,8 @@ private async Task ConnectAsync() { IsLoaded = true, }); + + Log.Information($"[ConnectAsync] 连接服务: {_rconConnectService.GetType().FullName}, 是否为多连接: {IsMultipleConnection}"); _logTextBox = (TextBox)LogicalTreeHelper.FindLogicalNode(_page, "LogText"); LogText += _logService.Log(_languageService.GetKey("text.server.start")); @@ -126,18 +134,9 @@ private async Task ConnectAsync() _rconConnectService.OnClosed += OnClosed; await Task.Run(_rconConnectService.Connect); } - catch (SocketException ex) - { - var msg = _languageService.GetKey("text.server.connect.fail.text") - .Replace("\\n", "\n") - .Replace("%s", ex.Message); - _messageBoxService.Show(msg, _languageService.GetKey("text.error"), MessageBoxButton.OK, - MessageBoxImage.Error); - LogText += _logService.Log(msg); - _logTextBox?.ScrollToEnd(); - } catch (AuthenticationException ex) { + Log.Error($"[ConnectAsync] 认证失败: {ex.Message}"); var msg = ex.Message + _languageService.GetKey("text.server.connect.auth_fail") .Replace("\\n", "\n"); _messageBoxService.Show(msg, _languageService.GetKey("text.error"), MessageBoxButton.OK, @@ -149,6 +148,18 @@ private async Task ConnectAsync() ? typeof(GroupPage) : typeof(ServersPage)); } + catch (Exception ex) + { + Log.Error($"[ConnectAsync] 连接遇到错误: {ex}"); + + var msg = _languageService.GetKey("text.server.connect.fail.text") + .Replace("\\n", "\n") + .Replace("%s", ex.Message); + _messageBoxService.Show(msg, _languageService.GetKey("text.error"), MessageBoxButton.OK, + MessageBoxImage.Error); + LogText += _logService.Log(msg); + _logTextBox?.ScrollToEnd(); + } finally { _connectingDialogService.Close(); @@ -164,8 +175,14 @@ private async Task ConnectAsync() IsDisconnection = !_rconConnectService.IsConnected(); } + partial void OnIsDisconnectionChanged(bool value) + { + Log.Information("当前客户端状态: {0}", _rconConnectService.IsConnected() ? "在线" : "离线"); + } + private void OnConnected(ServerInformation info) { + Log.Information("[OnConnected] {name}({adapter})", info.Name, string.IsNullOrEmpty(info.Adapter) ? "TCPRcon" : info.Adapter); LogText += _logService.Log($"$ {info.Name}\t{_languageService.GetKey("text.server.connected")}"); IsDisconnection = false; } @@ -196,6 +213,7 @@ private void Exit() [RelayCommand] private void Run() { + Log.Information("[Run] {0}", CommandText); if (_rconConnectService.IsConnected()) { LogText += _logService.Log($"> {CommandText}"); From 6b45f9a3f15485a65177067b6bc910b3da327050 Mon Sep 17 00:00:00 2001 From: zkhssb Date: Fri, 26 Jan 2024 00:48:00 +0800 Subject: [PATCH 4/9] =?UTF-8?q?upd:=20=E6=B7=BB=E5=8A=A0=E6=88=96=E7=BC=96?= =?UTF-8?q?=E8=BE=91=E6=9C=8D=E5=8A=A1=E5=99=A8=E6=97=B6=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=9C=B0=E5=9D=80=E4=B8=AD=E7=9A=84=E7=A9=BA?= =?UTF-8?q?=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NectarRCON/ViewModels/AddServerWindowViewModel.cs | 15 ++++++++------- .../ViewModels/EditServerWindowViewModel.cs | 9 +++++---- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/NectarRCON/ViewModels/AddServerWindowViewModel.cs b/NectarRCON/ViewModels/AddServerWindowViewModel.cs index 9b15eda..858a3dc 100644 --- a/NectarRCON/ViewModels/AddServerWindowViewModel.cs +++ b/NectarRCON/ViewModels/AddServerWindowViewModel.cs @@ -10,7 +10,7 @@ public partial class AddServerWindowViewModel : ObservableObject { private readonly IServerInformationService _serverInformationService; private readonly ILanguageService _languageService; - private AddServerWindow? _serverWindow = null; + private AddServerWindow? _serverWindow; [ObservableProperty] private string _serverName = "Rcon"; [ObservableProperty] @@ -27,18 +27,19 @@ public void SetWindow(AddServerWindow window) _serverWindow = window; } [RelayCommand] - public void Ok() + private void Ok() { - if (string.IsNullOrWhiteSpace(_serverName) || string.IsNullOrWhiteSpace(_serverAddress)) + ServerAddress = ServerAddress.Trim(); + if (string.IsNullOrWhiteSpace(ServerName) || string.IsNullOrWhiteSpace(ServerAddress)) { MessageBox.Show(_languageService.GetKey("ui.add_server_window.null_text"), _languageService.GetKey("text.error"), MessageBoxButton.OK, MessageBoxImage.Error); return; } - ServerInformation information = new ServerInformation() + var information = new ServerInformation() { - Name = _serverName, - Address = _serverAddress, - Port = ushort.Parse(_serverPort) + Name = ServerName, + Address = ServerAddress, + Port = ushort.Parse(ServerPort) }; if (_serverInformationService.ServerIsExist(information.Name)) { diff --git a/NectarRCON/ViewModels/EditServerWindowViewModel.cs b/NectarRCON/ViewModels/EditServerWindowViewModel.cs index 3405de2..b8ab0c9 100644 --- a/NectarRCON/ViewModels/EditServerWindowViewModel.cs +++ b/NectarRCON/ViewModels/EditServerWindowViewModel.cs @@ -27,12 +27,12 @@ public EditServerWindowViewModel() } [RelayCommand] - public void Load(RoutedEventArgs e) + private void Load(RoutedEventArgs e) { _window = e.Source as UiWindow; SelectServer = _serverPasswordService.GetSelect(); Port = _selectServer?.Port.ToString() ?? "0"; - Address = _selectServer?.Address.ToString() ?? "localhost"; + Address = _selectServer?.Address ?? "localhost"; } [RelayCommand] public void Exit() @@ -40,9 +40,10 @@ public void Exit() _window?.Close(); } [RelayCommand] - public void Ok() + private void Ok() { - if (string.IsNullOrWhiteSpace(_selectServer?.Address)) + Address = Address.Trim(); + if (string.IsNullOrWhiteSpace(_selectServer?.Address) || string.IsNullOrEmpty(Address)) MessageBox.Show(_languageService.GetKey("ui.add_server_window.null_text"), _languageService.GetKey("text.error"), MessageBoxButton.OK, MessageBoxImage.Error); else { From 2e1557c62e6c6e5669a57210c37689888d359dd6 Mon Sep 17 00:00:00 2001 From: zkhssb Date: Fri, 26 Jan 2024 01:40:32 +0800 Subject: [PATCH 5/9] =?UTF-8?q?upd:=20=E6=97=A5=E5=BF=97TextBox=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E7=AD=89=E5=AE=BD=E5=AD=97=E4=BD=93=20#9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NectarRCON/ViewModels/MainPageViewModel.cs | 4 ++-- NectarRCON/Views/Pages/MainPage.xaml | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/NectarRCON/ViewModels/MainPageViewModel.cs b/NectarRCON/ViewModels/MainPageViewModel.cs index 713d098..8344764 100644 --- a/NectarRCON/ViewModels/MainPageViewModel.cs +++ b/NectarRCON/ViewModels/MainPageViewModel.cs @@ -77,7 +77,7 @@ private void OnMessage(ServerInformation info, string msg) private void OnClosed(ServerInformation info) { - LogText += _logService.Log($"{info.Name}\t{_languageService.GetKey("text.server.closed")}"); + LogText += _logService.Log($"{info.Name} {_languageService.GetKey("text.server.closed")}"); IsDisconnection = !_rconConnectService.IsConnected(); } @@ -183,7 +183,7 @@ partial void OnIsDisconnectionChanged(bool value) private void OnConnected(ServerInformation info) { Log.Information("[OnConnected] {name}({adapter})", info.Name, string.IsNullOrEmpty(info.Adapter) ? "TCPRcon" : info.Adapter); - LogText += _logService.Log($"$ {info.Name}\t{_languageService.GetKey("text.server.connected")}"); + LogText += _logService.Log($"$ {info.Name} {_languageService.GetKey("text.server.connected")}"); IsDisconnection = false; } diff --git a/NectarRCON/Views/Pages/MainPage.xaml b/NectarRCON/Views/Pages/MainPage.xaml index 9d4dcb2..5d16158 100644 --- a/NectarRCON/Views/Pages/MainPage.xaml +++ b/NectarRCON/Views/Pages/MainPage.xaml @@ -15,6 +15,25 @@ + + + + + + + + + Date: Fri, 26 Jan 2024 02:01:17 +0800 Subject: [PATCH 6/9] =?UTF-8?q?=E6=97=A5=E5=BF=97=E6=B8=85=E7=A9=BA?= =?UTF-8?q?=E4=B8=8E=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81=20upd:=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=B8=BB=E7=AA=97=E5=8F=A3MenuItem=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=E8=A7=A6=E5=8F=91=E4=BB=A3=E7=A0=81=20add:=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=A8=8B=E5=BA=8F=E6=97=A5=E5=BF=97=E6=B8=85?= =?UTF-8?q?=E7=A9=BA=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NectarRCON/Resources/Languages/en_us.xaml | 2 + NectarRCON/Resources/Languages/zh_cn.xaml | 2 + NectarRCON/Resources/Languages/zh_tw.xaml | 2 + NectarRCON/ViewModels/MainWindowViewModel.cs | 35 ++++- NectarRCON/Windows/MainWindow.xaml | 148 ++++++++----------- 5 files changed, 96 insertions(+), 93 deletions(-) diff --git a/NectarRCON/Resources/Languages/en_us.xaml b/NectarRCON/Resources/Languages/en_us.xaml index 42c8c56..796d8b6 100644 --- a/NectarRCON/Resources/Languages/en_us.xaml +++ b/NectarRCON/Resources/Languages/en_us.xaml @@ -26,6 +26,8 @@ Auto Reconnect KeepConnectionWindowOpen Encoding + Clear Program Logs + Do you want to clear program logs? Connect Edit diff --git a/NectarRCON/Resources/Languages/zh_cn.xaml b/NectarRCON/Resources/Languages/zh_cn.xaml index b56a714..a547371 100644 --- a/NectarRCON/Resources/Languages/zh_cn.xaml +++ b/NectarRCON/Resources/Languages/zh_cn.xaml @@ -26,6 +26,8 @@ 掉线自动重连 掉线不回到主页 文本编码 + 清理程序日志 + 是否清理程序日志? 连接 编辑 diff --git a/NectarRCON/Resources/Languages/zh_tw.xaml b/NectarRCON/Resources/Languages/zh_tw.xaml index 5f0fe90..7263ec5 100644 --- a/NectarRCON/Resources/Languages/zh_tw.xaml +++ b/NectarRCON/Resources/Languages/zh_tw.xaml @@ -26,6 +26,8 @@ 斷綫自動重連 斷線不回到主頁 文本編碼 + 清除程式日誌 + 您是否要清除程式日誌? 連線 編輯 diff --git a/NectarRCON/ViewModels/MainWindowViewModel.cs b/NectarRCON/ViewModels/MainWindowViewModel.cs index dd8a070..31d024c 100644 --- a/NectarRCON/ViewModels/MainWindowViewModel.cs +++ b/NectarRCON/ViewModels/MainWindowViewModel.cs @@ -1,13 +1,18 @@ -using CommunityToolkit.Mvvm.ComponentModel; +using System; +using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Messaging; using NectarRCON.Interfaces; using NectarRCON.Models; using System.Collections.ObjectModel; +using System.IO; +using System.Windows; +using Serilog; using Wpf.Ui.Common; using Wpf.Ui.Controls; using Wpf.Ui.Controls.Interfaces; using Wpf.Ui.Mvvm.Contracts; +using MessageBox = System.Windows.MessageBox; namespace NectarRCON.ViewModels { @@ -16,6 +21,7 @@ public partial class MainWindowViewModel : ObservableObject [ObservableProperty] private ObservableCollection _navigationItems = new(); private readonly INavigationService _navigationService; + private readonly ILanguageService _languageService; [ObservableProperty] private bool _mainPageIsLoaded; public MainWindowViewModel(INavigationService navigationService, ILanguageService languageService) @@ -60,6 +66,7 @@ public MainWindowViewModel(INavigationService navigationService, ILanguageServic } }; _navigationService = navigationService; + _languageService = languageService; WeakReferenceMessenger.Default.Register(this, OnMainPageChange); } public void OnMainPageChange(object sender, MainPageLoadValueMessage message) @@ -67,19 +74,39 @@ public void OnMainPageChange(object sender, MainPageLoadValueMessage message) MainPageIsLoaded = message.IsLoaded; } [RelayCommand] - public void OnLoad() + private void OnLoad() { _navigationService.Navigate(2); } [RelayCommand] - public void ClearButtonClick() + private void ClearButtonClick() { WeakReferenceMessenger.Default.Send(new ClearLogValueMessage()); } [RelayCommand] - public void ChangePage(string index) + private void ChangePage(string index) { _navigationService.Navigate(int.Parse(index)); } + + [RelayCommand] + private void ClearProgramLogs() + { + if (MessageBox.Show(_languageService.GetKey("ui.menu.log.clear_program.ask"), "NectarRcon", MessageBoxButton.YesNo, + MessageBoxImage.Question) != MessageBoxResult.Yes) return; + Log.Information("Clear program logs"); + foreach (var logFile in Directory.GetFiles(Path.Combine(Environment.CurrentDirectory, "logs", "program"), "*.log")) + { + try + { + Log.Information("Delete log file: {0}", logFile); + File.Delete(logFile); + } + catch(Exception ex) + { + Log.Error(ex, "Delete log file failed: {0}", logFile); + } + } + } } } diff --git a/NectarRCON/Windows/MainWindow.xaml b/NectarRCON/Windows/MainWindow.xaml index 7668738..cb62f9c 100644 --- a/NectarRCON/Windows/MainWindow.xaml +++ b/NectarRCON/Windows/MainWindow.xaml @@ -1,37 +1,37 @@  + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:i="http://schemas.microsoft.com/xaml/behaviors" + xmlns:local="clr-namespace:NectarRCON" + mc:Ignorable="d" + Title="{DynamicResource ui.window.title}" + ExtendsContentIntoTitleBar="True" + WindowBackdropType="Mica" + WindowCornerPreference="Round" + WindowStartupLocation="CenterScreen" + MinHeight="690" + MinWidth="650" + Height="690" + Width="650"> - + - - - + + + - + Grid.Row="0" /> @@ -39,77 +39,47 @@ Focusable="False" Header="{DynamicResource ui.menu.server}"> - - - - - - + Focusable="False" + Header="{DynamicResource ui.menu.server_list}" + CommandParameter="2" + Command="{Binding ViewModel.ChangePageCommand}" /> + - - - - - - + Focusable="False" + Header="{DynamicResource ui.menu.groups}" + CommandParameter="4" + Command="{Binding ViewModel.ChangePageCommand}" /> - - - - - - - + Command="{Binding ViewModel.ClearButtonClickCommand}" + Header="{DynamicResource ui.menu.log.clear}" /> - - - - - - - - - + - - - - - - - + + Header="{DynamicResource ui.menu.program.check_update}" /> + + Frame="{Binding ElementName=MainFrame,Mode=OneWay}" /> - + - + - - + + Text="{DynamicResource text.server.connect.ing}" /> - + \ No newline at end of file From bd19740c07dcb275c6547176c86a79b5b3aa0084 Mon Sep 17 00:00:00 2001 From: zkhssb Date: Fri, 26 Jan 2024 02:19:09 +0800 Subject: [PATCH 7/9] =?UTF-8?q?add:=20=E5=85=A8=E5=B1=80=E5=BC=82=E5=B8=B8?= =?UTF-8?q?=E6=8B=A6=E6=88=AA=E5=92=8C=E4=BF=A1=E6=81=AF=E8=BE=93=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NectarRCON/App.xaml.cs | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/NectarRCON/App.xaml.cs b/NectarRCON/App.xaml.cs index fec374f..22e1879 100644 --- a/NectarRCON/App.xaml.cs +++ b/NectarRCON/App.xaml.cs @@ -6,6 +6,7 @@ using NectarRCON.ViewModels; using NectarRCON.Windows; using System; +using System.IO; using System.Linq; using System.Text; using System.Windows; @@ -16,27 +17,31 @@ using Wpf.Ui.Mvvm.Services; namespace NectarRCON; + /// /// Interaction logic for App.xaml /// public partial class App { private static readonly ILoggerFactory LoggerFactory = new LoggerFactory(); + private static string LogFileName = $"logs/program/log{DateTime.Now:yyyyMMddhhmm}.log"; + private static readonly IHost Host = Microsoft.Extensions.Hosting.Host .CreateDefaultBuilder() .ConfigureLogging(builder => { Log.Logger = new LoggerConfiguration() - .WriteTo.File($"logs/program/log{DateTime.Now:yyyyMMddhhmm}.log", rollingInterval: RollingInterval.Infinite, flushToDiskInterval: TimeSpan.FromSeconds(1)) + .WriteTo.File(LogFileName, + rollingInterval: RollingInterval.Infinite, flushToDiskInterval: TimeSpan.FromSeconds(1)) .CreateLogger(); - + builder.AddSerilog(); }) .ConfigureServices((context, services) => { services.AddSingleton(LoggerFactory); services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); - + services.AddHostedService(); services.AddSingleton(); @@ -66,8 +71,8 @@ public partial class App services.AddTransient(); services.AddTransient(); - }).Build(); + public static T GetService() where T : class { @@ -75,7 +80,7 @@ public static T GetService() } public static T GetService(Type type) - where T : class + where T : class { return Host.Services.GetServices().FirstOrDefault(t => t.GetType() == type)!; } @@ -88,13 +93,26 @@ private async void OnStartup(object sender, StartupEventArgs e) { rconEncoding.GetEncoding(); } - + + AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; await Host.StartAsync(); } + private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) + { + var exception = e.ExceptionObject as Exception; + Log.Error("未经处理的异常: {0}", exception); + + MessageBox.Show( + exception + + $"\n\n程序遇到异常,即将退出!\n建议前往Github提交Issue\n请前往日志查看详细信息!\nCheck log: {Path.Combine(Environment.CurrentDirectory, LogFileName).Replace("\\", "/")}", + "程序崩溃", MessageBoxButton.OK, MessageBoxImage.Error); + Environment.Exit(1); + } + private async void OnExit(object sender, ExitEventArgs e) { await Host.StopAsync(); Host.Dispose(); } -} +} \ No newline at end of file From 5773b98de935ce92fc8b7a061fd7e24c98cd8ea1 Mon Sep 17 00:00:00 2001 From: zkhssb Date: Fri, 26 Jan 2024 02:20:25 +0800 Subject: [PATCH 8/9] =?UTF-8?q?upd:=20=E4=BF=AE=E6=94=B9=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E5=8F=B7=E5=88=B01.0.0-beta5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NectarRCON/App.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NectarRCON/App.xaml b/NectarRCON/App.xaml index e71476f..0b3f82b 100644 --- a/NectarRCON/App.xaml +++ b/NectarRCON/App.xaml @@ -14,7 +14,7 @@ - 1.0.0-beta4 + 1.0.0-beta5 From 2bf3023413a6e860195c91b8f3b01b091c91348f Mon Sep 17 00:00:00 2001 From: zkhssb Date: Fri, 26 Jan 2024 02:21:29 +0800 Subject: [PATCH 9/9] =?UTF-8?q?oops:=20=E4=BF=AE=E6=94=B9=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E8=AE=BE=E7=BD=AE=E4=B8=AD=E7=A8=8B=E5=BA=8F=E7=9A=84?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E5=8F=B7=E5=88=B01.0.0-beta5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NectarRCON/NectarRCON.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NectarRCON/NectarRCON.csproj b/NectarRCON/NectarRCON.csproj index 8460697..4aeb40f 100644 --- a/NectarRCON/NectarRCON.csproj +++ b/NectarRCON/NectarRCON.csproj @@ -7,7 +7,7 @@ true Resources\Icon.ico app.manifest - 1.0.0-beta3 + 1.0.0-beta5 12