Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

日志更新和一些问题的尝试性修复 #10

Merged
merged 9 commits into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion NectarRCON/App.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<ui:ControlsDictionary />
<ResourceDictionary Source="pack://application:,,,/NectarRCON;component/Resources/Languages/zh_cn.xaml" />
<ResourceDictionary>
<sys:String x:Key="app.version">1.0.0-beta4</sys:String>
<sys:String x:Key="app.version">1.0.0-beta5</sys:String>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Expand Down
52 changes: 42 additions & 10 deletions NectarRCON/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/// <summary>
/// Interaction logic for App.xaml
/// </summary>
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<ApplicationHostService>();

services.AddSingleton<ILanguageService, LanguageService>();
Expand Down Expand Up @@ -52,18 +71,18 @@ public partial class App

services.AddTransient<AddServerWindow>();
services.AddTransient<AddServerWindowViewModel>();

}).Build();

public static T GetService<T>()
where T : class
{
return (_host.Services.GetService(typeof(T)) as T)!;
return (Host.Services.GetService(typeof(T)) as T)!;
}

public static T GetService<T>(Type type)
where T : class
where T : class
{
return (_host.Services.GetServices<T>().Where(t => t.GetType() == type).FirstOrDefault())!;
return Host.Services.GetServices<T>().FirstOrDefault(t => t.GetType() == type)!;
}

private async void OnStartup(object sender, StartupEventArgs e)
Expand All @@ -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();
}
}
}
5 changes: 4 additions & 1 deletion NectarRCON/NectarRCON.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<UseWPF>true</UseWPF>
<ApplicationIcon>Resources\Icon.ico</ApplicationIcon>
<ApplicationManifest>app.manifest</ApplicationManifest>
<Version>1.0.0-beta3</Version>
<Version>1.0.0-beta5</Version>
<LangVersion>12</LangVersion>
</PropertyGroup>

Expand All @@ -24,6 +24,9 @@
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.0" />
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.39" />
<PackageReference Include="Serilog" Version="3.1.2-dev-02097" />
<PackageReference Include="Serilog.Extensions.Logging" Version="8.0.1-dev-10370" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.1-dev-00972" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
<PackageReference Include="WPF-UI" Version="2.0.3" />
</ItemGroup>
Expand Down
41 changes: 18 additions & 23 deletions NectarRCON/Rcon/RconMultiConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,28 @@
using System.Security.Authentication;
using System.Windows.Controls;
using NectarRCON.Dp;
using Serilog;

namespace NectarRCON.Services
{
/// <summary>
/// Rcon多客户端连接服务
/// </summary>
internal class RconMultiConnection : IRconConnection, IDisposable
internal class RconMultiConnection(
IServerPasswordService serverPasswordService,
ILanguageService languageService,
IRconConnectionInfoService rconConnectionInfoService,
IMessageBoxService messageBoxService)
: IRconConnection, IDisposable
{
private readonly RconSettingsDp _settingsDp = DpFile.LoadSingleton<RconSettingsDp>();
public event MessageEvent? OnMessage;
public event RconEvent? OnClosed;
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<ServerInformation,IRconAdapter> _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()
{
Expand All @@ -54,7 +47,7 @@ public void Connect()
{
Close();
_isConnecting = true;
var servers = _rconConnectionInfoService.GetInformation();
var servers = rconConnectionInfoService.GetInformation();
try
{
foreach (ServerInformation info in servers)
Expand All @@ -64,17 +57,19 @@ 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客户端实例
// 目前支支持了Minecraft,后期会支持更多(嘛..主要是懒)
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);
Expand All @@ -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}\"");
}

//设置编码
Expand All @@ -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;
Expand All @@ -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"));
}
}
}
Expand Down
48 changes: 24 additions & 24 deletions NectarRCON/Rcon/RconSingleConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<RconSettingsDp>();
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;
Expand All @@ -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
Expand All @@ -64,17 +59,19 @@ 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客户端实例
// 目前支支持了Minecraft,后期会支持更多(嘛..主要是懒)
_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))
Expand All @@ -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
{
Expand All @@ -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);
}
}
}
2 changes: 2 additions & 0 deletions NectarRCON/Resources/Languages/en_us.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
<sys:String x:Key="ui.settings.rcon.auto_reconnect">Auto Reconnect</sys:String>
<sys:String x:Key="ui.settings.rcon.is_keep_connection_window_open">KeepConnectionWindowOpen</sys:String>
<sys:String x:Key="ui.settings.rcon.encoding">Encoding</sys:String>
<sys:String x:Key="ui.menu.log.clear_program">Clear Program Logs</sys:String>
<sys:String x:Key="ui.menu.log.clear_program.ask">Do you want to clear program logs?</sys:String>

<sys:String x:Key="ui.server_page.menu.open">Connect</sys:String>
<sys:String x:Key="ui.server_page.menu.edit">Edit</sys:String>
Expand Down
2 changes: 2 additions & 0 deletions NectarRCON/Resources/Languages/zh_cn.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
<sys:String x:Key="ui.settings.rcon.auto_reconnect">掉线自动重连</sys:String>
<sys:String x:Key="ui.settings.rcon.is_keep_connection_window_open">掉线不回到主页</sys:String>
<sys:String x:Key="ui.settings.rcon.encoding">文本编码</sys:String>
<sys:String x:Key="ui.menu.log.clear_program">清理程序日志</sys:String>
<sys:String x:Key="ui.menu.log.clear_program.ask">是否清理程序日志?</sys:String>

<sys:String x:Key="ui.server_page.menu.open">连接</sys:String>
<sys:String x:Key="ui.server_page.menu.edit">编辑</sys:String>
Expand Down
2 changes: 2 additions & 0 deletions NectarRCON/Resources/Languages/zh_tw.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
<sys:String x:Key="ui.settings.rcon.auto_reconnect">斷綫自動重連</sys:String>
<sys:String x:Key="ui.settings.rcon.is_keep_connection_window_open">斷線不回到主頁</sys:String>
<sys:String x:Key="ui.settings.rcon.encoding">文本編碼</sys:String>
<sys:String x:Key="ui.menu.log.clear_program">清除程式日誌</sys:String>
<sys:String x:Key="ui.menu.log.clear_program.ask">您是否要清除程式日誌?</sys:String>

<sys:String x:Key="ui.server_page.menu.open">連線</sys:String>
<sys:String x:Key="ui.server_page.menu.edit">編輯</sys:String>
Expand Down
Loading
Loading