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
diff --git a/NectarRCON/App.xaml.cs b/NectarRCON/App.xaml.cs
index 314c866..22e1879 100644
--- a/NectarRCON/App.xaml.cs
+++ b/NectarRCON/App.xaml.cs
@@ -6,23 +6,42 @@
using NectarRCON.ViewModels;
using NectarRCON.Windows;
using System;
+using System.IO;
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;
namespace NectarRCON;
+
///
/// Interaction logic for App.xaml
///
public partial class App
{
- private static readonly IHost _host = Host
+ 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(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();
@@ -52,18 +71,18 @@ public partial class App
services.AddTransient();
services.AddTransient();
-
}).Build();
+
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
+ 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)
@@ -74,13 +93,26 @@ private async void OnStartup(object sender, StartupEventArgs e)
{
rconEncoding.GetEncoding();
}
-
- await _host.StartAsync();
+
+ 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();
+ await Host.StopAsync();
+ Host.Dispose();
}
-}
+}
\ No newline at end of file
diff --git a/NectarRCON/NectarRCON.csproj b/NectarRCON/NectarRCON.csproj
index c205304..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
@@ -24,6 +24,9 @@
+
+
+
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/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/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();
}
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
{
diff --git a/NectarRCON/ViewModels/MainPageViewModel.cs b/NectarRCON/ViewModels/MainPageViewModel.cs
index 9b0888d..8344764 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;
@@ -74,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();
}
@@ -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,9 +175,15 @@ private async Task ConnectAsync()
IsDisconnection = !_rconConnectService.IsConnected();
}
+ partial void OnIsDisconnectionChanged(bool value)
+ {
+ Log.Information("当前客户端状态: {0}", _rconConnectService.IsConnected() ? "在线" : "离线");
+ }
+
private void OnConnected(ServerInformation info)
{
- LogText += _logService.Log($"$ {info.Name}\t{_languageService.GetKey("text.server.connected")}");
+ Log.Information("[OnConnected] {name}({adapter})", info.Name, string.IsNullOrEmpty(info.Adapter) ? "TCPRcon" : info.Adapter);
+ LogText += _logService.Log($"$ {info.Name} {_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}");
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/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 @@
+
+
+
+
+
+
+
+
+
+ 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" />
+ Frame="{Binding ElementName=MainFrame,Mode=OneWay}" />
-
+
-
+
-
-
+
+ Text="{DynamicResource text.server.connect.ing}" />
-
+
\ No newline at end of file