XFEstudio/MyFirstRespo
修复未处理异常问题
08fe41d
代码差异
5 个文件
+242
-19
@@ -11,4 +11,38 @@ public partial class App : Application
11
11
{
12
12
this.InitializeComponent();
13
13
}
14
protected override void OnStartup(StartupEventArgs e)
15
{
16
base.OnStartup(e);
17
18
// 注册 UI 线程未处理异常事件
19
this.DispatcherUnhandledException += new System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(App_DispatcherUnhandledException);
20
21
// 注册非 UI 线程未处理异常事件
22
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
23
24
// 注册任务调度程序未观察到的任务异常事件
25
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
26
}
27
28
void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
29
{
30
// 处理 UI 线程未处理的异常
31
MessageBox.Show("UI线程未处理异常:" + e.Exception.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
32
e.Handled = true; // 设置为 true 表示异常已处理,防止应用程序退出
33
}
34
35
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
36
{
37
// 处理非 UI 线程未处理的异常
38
Exception ex = e.ExceptionObject as Exception;
39
MessageBox.Show("非UI线程未处理异常:" + ex?.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
40
}
41
42
void TaskScheduler_UnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)
43
{
44
// 处理任务调度程序未观察到的任务异常
45
MessageBox.Show("非主线程未处理异常:" + e.Exception.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
46
e.SetObserved(); // 防止程序崩溃
47
}
14
48
}
@@ -0,0 +1,30 @@
1
using XFEExtension.NetCore.CyberComm;
2
3
namespace XFEExtension.NetCore.XFEConsole;
4
5
/// <summary>
6
/// XFE控制台客户端信息
7
/// </summary>
8
/// <param name="clientName">客户端名称</param>
9
/// <param name="clientUUID">客户端唯一标识符</param>
10
/// <param name="password">客户端连接时密码</param>
11
/// <param name="eventArgs">事件参数</param>
12
public class XFEConsoleClientInfo(string clientName, string clientUUID, string password, CyberCommServerEventArgs eventArgs)
13
{
14
/// <summary>
15
/// 客户端名称
16
/// </summary>
17
public string ClientName { get; set; } = clientName;
18
/// <summary>
19
/// 客户端唯一标识符
20
/// </summary>
21
public string ClientUUID { get; set; } = clientUUID;
22
/// <summary>
23
/// 客户端密码
24
/// </summary>
25
public string Password { get; set; } = password;
26
/// <summary>
27
/// 事件参数
28
/// </summary>
29
public CyberCommServerEventArgs EventArgs { get; set; } = eventArgs;
30
}
@@ -0,0 +1,149 @@
1
using System.Net.WebSockets;
2
using XFEExtension.NetCore.CyberComm;
3
using XFEExtension.NetCore.DelegateExtension;
4
5
namespace XFEExtension.NetCore.XFEConsole;
6
7
/// <summary>
8
/// XFE控制台终端服务器
9
/// </summary>
10
public class XFEConsoleTerminalServer
11
{
12
/// <summary>
13
/// 服务器
14
/// </summary>
15
public CyberCommServer Server { get; set; }
16
/// <summary>
17
/// 密码
18
/// </summary>
19
public string Password { get; set; }
20
/// <summary>
21
/// Socket客户端-客户端信息字典
22
/// </summary>
23
public Dictionary<WebSocket, XFEConsoleClientInfo> ClientInfoDictionary { get; set; } = [];
24
/// <summary>
25
/// 客户端连接事件
26
/// </summary>
27
public event XFEEventHandler<XFEConsoleTerminalServer, XFEConsoleClientInfo>? Connected;
28
/// <summary>
29
/// 客户端断开连接事件
30
/// </summary>
31
public event XFEEventHandler<XFEConsoleTerminalServer, XFEConsoleClientInfo>? Disconnected;
32
/// <summary>
33
/// 接收到客户端消息触发
34
/// </summary>
35
public event XFEEventHandler<XFEConsoleClientInfo, string>? MessageReceived;
36
/// <summary>
37
/// 发生错误
38
/// </summary>
39
public event XFEEventHandler<XFEConsoleClientInfo, Exception>? ErrorOccurred;
40
/// <summary>
41
/// 服务器启动事件
42
/// </summary>
43
public event XFEEventHandler<XFEConsoleTerminalServer>? ServerStarted;
44
/// <summary>
45
/// XFE控制台终端服务器
46
/// </summary>
47
/// <param name="port">端口号</param>
48
/// <param name="localOnly">是否只在本地开启</param>
49
/// <param name="password">密码(默认为空)</param>
50
public XFEConsoleTerminalServer(int port, bool localOnly = true, string password = "")
51
{
52
Password = password;
53
if (localOnly)
54
Server = new CyberCommServer($"http://localhost:{port}/");
55
else
56
Server = new CyberCommServer(port);
57
Server.ServerStarted += Server_ServerStarted;
58
Server.ClientConnected += Server_ClientConnected;
59
Server.ConnectionClosed += Server_ConnectionClosed;
60
Server.MessageReceived += Server_MessageReceived;
61
}
62
/// <summary>
63
/// XFE控制台终端服务器
64
/// </summary>
65
/// <param name="ipAddress">IP地址</param>
66
/// <param name="password">密码(默认为空)</param>
67
public XFEConsoleTerminalServer(string[] ipAddress, string password = "")
68
{
69
Password = password;
70
Server = new CyberCommServer(ipAddress);
71
Server.ServerStarted += Server_ServerStarted;
72
Server.ClientConnected += Server_ClientConnected;
73
Server.ConnectionClosed += Server_ConnectionClosed;
74
Server.MessageReceived += Server_MessageReceived;
75
}
76
77
private void Server_MessageReceived(object? sender, CyberCommServerEventArgs e)
78
{
79
switch (e.MessageType)
80
{
81
case BackMessageType.Text:
82
MessageReceived?.Invoke(ClientInfoDictionary[e.CurrentWebSocket], e.TextMessage!);
83
break;
84
case BackMessageType.Binary:
85
break;
86
case BackMessageType.Error:
87
ErrorOccurred?.Invoke(ClientInfoDictionary[e.CurrentWebSocket], e.Exception!);
88
break;
89
default:
90
break;
91
}
92
}
93
94
private void Server_ConnectionClosed(object? sender, CyberCommServerEventArgs e)
95
{
96
if (ClientInfoDictionary.TryGetValue(e.CurrentWebSocket, out XFEConsoleClientInfo? clientInfo))
97
{
98
ClientInfoDictionary.Remove(e.CurrentWebSocket);
99
Disconnected?.Invoke(this, clientInfo);
100
}
101
}
102
103
private async void Server_ClientConnected(object? sender, CyberCommServerEventArgs e)
104
{
105
try
106
{
107
if (e.WSHeader["ClientName"] is not null && e.WSHeader["ClientID"] is not null && e.WSHeader["Password"] is not null)
108
{
109
var password = e.WSHeader["Password"]!;
110
var clientName = e.WSHeader["ClientName"]!;
111
var clientUUID = e.WSHeader["ClientID"]!;
112
if (password == Password)
113
{
114
var clientInfo = new XFEConsoleClientInfo(clientName, clientUUID, password, e);
115
ClientInfoDictionary.Add(e.CurrentWebSocket, clientInfo);
116
Connected?.Invoke(this, clientInfo);
117
}
118
return;
119
}
120
}
121
catch { }
122
try
123
{
124
await e.Close();
125
}
126
catch
127
{
128
try
129
{
130
e.ForceClose();
131
}
132
catch { }
133
}
134
}
135
136
private void Server_ServerStarted(object? sender, EventArgs e)
137
{
138
ClientInfoDictionary = [];
139
ServerStarted?.Invoke(this);
140
}
141
/// <summary>
142
/// 启动服务器
143
/// </summary>
144
/// <returns></returns>
145
public async Task StartServer()
146
{
147
await Server.StartCyberCommServer();
148
}
149
}
@@ -11,7 +11,7 @@ using XFEToolBox.Views.Pages;
11
11
12
12
namespace XFEToolBox.ViewModel;
13
13
14
public partial class ConsolePageViewModel : ObservableObject
14
public partial class ConsolePageViewModel(ConsolePage viewPage) : ObservableObject
15
15
{
16
16
[ObservableProperty]
17
17
private bool canStartServer = true;
@@ -23,14 +23,9 @@ public partial class ConsolePageViewModel : ObservableObject
23
23
private bool canCleanUp = false;
24
24
25
25
private bool lastLineIsEnd = true;
26
public ConsolePage ViewPage { get; set; }
26
public ConsolePage ViewPage { get; set; } = viewPage;
27
27
public XFEConsoleTerminalServer? TerminalServer { get; set; }
28
28
29
public ConsolePageViewModel(ConsolePage viewPage)
30
{
31
ViewPage = viewPage;
32
}
33
34
29
public async Task StartConsoleServer()
35
30
{
36
31
TerminalServer = new XFEConsoleTerminalServer(ConsoleProfile.ConsolePort, ConsoleProfile.LocalOnly, ConsoleProfile.ConsolePassword);
@@ -39,14 +34,24 @@ public partial class ConsolePageViewModel : ObservableObject
39
34
TerminalServer.Disconnected += TerminalServer_Disconnected;
40
35
TerminalServer.MessageReceived += TerminalServer_MessageReceived;
41
36
TerminalServer.ErrorOccurred += TerminalServer_ErrorOccurred;
42
await TerminalServer.StartServer();
37
await Task.Run(async () =>
38
{
39
try
40
{
41
await TerminalServer.StartServer();
42
}
43
catch (Exception ex)
44
{
45
TerminalServer_ErrorOccurred(null!, ex);
46
}
47
});
43
48
}
44
49
45
50
public void ShutDownServer()
46
51
{
47
52
try
48
53
{
49
TerminalServer?.Server.Server.Close();
54
TerminalServer?.Server.Server.Abort();
50
55
}
51
56
catch { }
52
57
TerminalServer = null;
@@ -98,17 +103,23 @@ public partial class ConsolePageViewModel : ObservableObject
98
103
var lastControl = ViewPage.consoleStackPanel.Children.Count > 0 ? ViewPage.consoleStackPanel.Children[^1] : null;
99
104
if (lastControl is TextBlock lastTextBlock)
100
105
{
101
var inLineList = DecoratedTextConverter.ConvertToInlineList(message, defaultColor);
102
lastTextBlock.Inlines.AddRange(inLineList);
103
lastLineIsEnd = isLineEnd;
104
return;
106
ViewPage.Dispatcher.Invoke(() =>
107
{
108
var inLineList = DecoratedTextConverter.ConvertToInlineList(message, defaultColor);
109
lastTextBlock.Inlines.AddRange(inLineList);
110
lastLineIsEnd = isLineEnd;
111
});
105
112
}
113
return;
106
114
}
107
var textBlock = DecoratedTextConverter.ConvertToTextBlock(message, defaultColor);
108
textBlock.TextWrapping = System.Windows.TextWrapping.Wrap;
109
textBlock.FontSize = 13;
110
textBlock.FontFamily = new FontFamily("Consolas");
111
ViewPage.consoleStackPanel.Children.Add(textBlock);
115
ViewPage.Dispatcher.Invoke(() =>
116
{
117
var textBlock = DecoratedTextConverter.ConvertToTextBlock(message, defaultColor);
118
textBlock.TextWrapping = System.Windows.TextWrapping.Wrap;
119
textBlock.FontSize = 13;
120
textBlock.FontFamily = new FontFamily("Consolas");
121
ViewPage.consoleStackPanel.Children.Add(textBlock);
122
});
112
123
lastLineIsEnd = isLineEnd;
113
124
}
114
125
/// <summary>
@@ -37,7 +37,6 @@
37
37
<PackageReference Include="XFEExtension.NetCore.AutoPath" Version="1.0.1" />
38
38
<PackageReference Include="XFEExtension.NetCore.InputSimulator" Version="2.2.0" />
39
39
<PackageReference Include="XFEExtension.NetCore.TodoHighLight" Version="1.0.0" />
40
<PackageReference Include="XFEExtension.NetCore.XFEConsole" Version="1.0.0" />
41
40
</ItemGroup>
42
41
43
42
<ItemGroup>