-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.cs
More file actions
127 lines (108 loc) · 4.33 KB
/
Copy pathProgram.cs
File metadata and controls
127 lines (108 loc) · 4.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
using System;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.SignalR;
using PylonStream.Hubs;
namespace PylonStream
{
internal static class Program
{
[STAThread]
static void Main()
{
// Prevent multiple instances (optional but good practice)
string processName = Process.GetCurrentProcess().ProcessName;
Process[] processes = Process.GetProcessesByName(processName);
if (processes.Length > 1)
{
MessageBox.Show("The application is already running.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
ApplicationConfiguration.Initialize();
// 1. Initialize exception captions
InitialExceptionCaption();
// 2. Load settings
Modules.Config = AppConfig.Load();
Modules.SystemLogger.AddLog("System settings loaded.", "INFO");
// 3. Initialize Kestrel Web Server in background
InitialWeb();
// 4. Run the WinForms UI main loop
Application.Run(new MainForm());
// 5. Clean shutdown when WinForms closes
ShutdownAll();
}
private static void InitialWeb()
{
var webThread = new Thread(() =>
{
try
{
int port = Modules.Config.WebApiPort;
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
ContentRootPath = AppContext.BaseDirectory
});
// Add ASP.NET Core services
builder.Services.AddSignalR();
builder.Services.AddControllers();
var app = builder.Build();
Modules.WebApp = app;
// Enable serving default files (index.html) and static files from wwwroot
app.UseDefaultFiles();
app.UseStaticFiles();
// Setup HTTP request pipeline
app.MapHub<StreamHub>("/streamHub");
app.MapControllers();
// Save the SignalR HubContext for global log broadcasting
Modules.WebHubContext = app.Services.GetRequiredService<IHubContext<StreamHub>>();
Modules.SystemLogger.AddLog($"Web Server starting on http://0.0.0.0:{port}");
app.Run($"http://0.0.0.0:{port}");
}
catch (Exception ex)
{
Modules.SystemLogger.AddLog($"Web Server failed to start: {ex.Message}", "ERROR");
}
});
webThread.IsBackground = true;
webThread.Start();
}
private static void ShutdownAll()
{
try
{
Modules.SystemLogger.AddLog("Shutting down all services...", "INFO");
Modules.CameraMgr.StopAll();
Modules.MediaMTXMgr.Stop();
// Elegant stop ASP.NET Core Kestrel Web server to release port 5000 immediately
if (Modules.WebApp != null)
{
Modules.SystemLogger.AddLog("Stopping Web Server...", "INFO");
Modules.WebApp.StopAsync().GetAwaiter().GetResult();
}
Modules.SystemLogger.AddLog("Shutdown completed.", "INFO");
}
catch (Exception ex)
{
Console.WriteLine($"Error during shutdown: {ex.Message}");
}
}
private static void InitialExceptionCaption()
{
AppDomain.CurrentDomain.UnhandledException += (s, e) =>
{
if (e.ExceptionObject is Exception ex)
{
Modules.SystemLogger?.AddLog($"[UnhandledException] {ex.Message}\r\n{ex.StackTrace}", "ERROR");
}
};
Application.ThreadException += (s, e) =>
{
Exception ex = e.Exception;
Modules.SystemLogger?.AddLog($"[ThreadException] {ex.Message}\r\n{ex.StackTrace}", "ERROR");
};
}
}
}