99using Microsoft . Extensions . DependencyInjection ;
1010using Microsoft . Extensions . Hosting ;
1111using Microsoft . Extensions . Logging ;
12+ using Serilog ;
13+ using System . Windows . Threading ;
1214
1315namespace DesktopApp ;
1416
1517public partial class App : Application
1618{
1719 private IHost ? _host ;
1820
21+ public App ( )
22+ {
23+ // Set up global exception handlers
24+ AppDomain . CurrentDomain . UnhandledException += OnUnhandledException ;
25+ DispatcherUnhandledException += OnDispatcherUnhandledException ;
26+ TaskScheduler . UnobservedTaskException += OnUnobservedTaskException ;
27+ }
28+
1929 protected override void OnStartup ( StartupEventArgs e )
2030 {
21- // Configure dependency injection
22- _host = CreateHostBuilder ( ) . Build ( ) ;
31+ try
32+ {
33+ // Initialize logging first
34+ var logPath = Path . Combine (
35+ Environment . GetFolderPath ( Environment . SpecialFolder . ApplicationData ) ,
36+ "IPTV-Desktop-Browser" ,
37+ "Logs" ,
38+ "app-.log"
39+ ) ;
40+
41+ Log . Logger = new LoggerConfiguration ( )
42+ . MinimumLevel . Information ( )
43+ . WriteTo . File (
44+ logPath ,
45+ rollingInterval : RollingInterval . Day ,
46+ retainedFileCountLimit : 7 ,
47+ outputTemplate : "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] {Message:lj}{NewLine}{Exception}"
48+ )
49+ . CreateLogger ( ) ;
50+
51+ Log . Information ( "=== Application Starting ===" ) ;
52+ Log . Information ( "Version: {Version}" , "2.1.0" ) ;
53+ Log . Information ( "OS: {OS}" , Environment . OSVersion ) ;
54+ Log . Information ( ".NET Version: {DotNetVersion}" , Environment . Version ) ;
55+
56+ // Configure dependency injection
57+ _host = CreateHostBuilder ( ) . Build ( ) ;
58+
59+ // Initialize Session with configuration settings
60+ var apiSettings = _host . Services . GetRequiredService < ApiSettings > ( ) ;
61+ var playerSettings = _host . Services . GetRequiredService < PlayerSettings > ( ) ;
62+ var recordingSettings = _host . Services . GetRequiredService < RecordingSettings > ( ) ;
63+ var epgSettings = _host . Services . GetRequiredService < EpgSettings > ( ) ;
64+ var m3uSettings = _host . Services . GetRequiredService < M3uSettings > ( ) ;
65+ var networkSettings = _host . Services . GetRequiredService < NetworkSettings > ( ) ;
66+
67+ Session . InitializeConfiguration ( apiSettings , playerSettings , recordingSettings , epgSettings , m3uSettings , networkSettings ) ;
68+
69+ // Load settings
70+ SettingsStore . LoadIntoSession ( ) ;
71+
72+ Log . Information ( "Configuration loaded successfully" ) ;
73+
74+ // Start with main window
75+ var mainWindow = _host . Services . GetRequiredService < MainWindow > ( ) ;
76+ mainWindow . Show ( ) ;
77+
78+ Log . Information ( "Main window displayed" ) ;
79+
80+ base . OnStartup ( e ) ;
81+ }
82+ catch ( Exception ex )
83+ {
84+ Log . Fatal ( ex , "Fatal error during application startup" ) ;
85+ MessageBox . Show (
86+ $ "A fatal error occurred during startup:\n \n { ex . Message } \n \n Please check the log file at:\n { GetLogDirectory ( ) } ",
87+ "Application Startup Error" ,
88+ MessageBoxButton . OK ,
89+ MessageBoxImage . Error
90+ ) ;
91+ Log . CloseAndFlush ( ) ;
92+ Shutdown ( 1 ) ;
93+ }
94+ }
2395
24- // Initialize Session with configuration settings
25- var apiSettings = _host . Services . GetRequiredService < ApiSettings > ( ) ;
26- var playerSettings = _host . Services . GetRequiredService < PlayerSettings > ( ) ;
27- var recordingSettings = _host . Services . GetRequiredService < RecordingSettings > ( ) ;
28- var epgSettings = _host . Services . GetRequiredService < EpgSettings > ( ) ;
29- var m3uSettings = _host . Services . GetRequiredService < M3uSettings > ( ) ;
30- var networkSettings = _host . Services . GetRequiredService < NetworkSettings > ( ) ;
96+ private void OnUnhandledException ( object sender , UnhandledExceptionEventArgs e )
97+ {
98+ var exception = e . ExceptionObject as Exception ;
99+ Log . Fatal ( exception , "Unhandled exception in AppDomain" ) ;
100+
101+ if ( e . IsTerminating )
102+ {
103+ MessageBox . Show (
104+ $ "A fatal error occurred:\n \n { exception ? . Message } \n \n The application will now close.\n \n Log location: { GetLogDirectory ( ) } ",
105+ "Fatal Error" ,
106+ MessageBoxButton . OK ,
107+ MessageBoxImage . Error
108+ ) ;
109+ Log . CloseAndFlush ( ) ;
110+ }
111+ }
112+
113+ private void OnDispatcherUnhandledException ( object sender , DispatcherUnhandledExceptionEventArgs e )
114+ {
115+ Log . Error ( e . Exception , "Unhandled dispatcher exception" ) ;
31116
32- Session . InitializeConfiguration ( apiSettings , playerSettings , recordingSettings , epgSettings , m3uSettings , networkSettings ) ;
117+ MessageBox . Show (
118+ $ "An error occurred:\n \n { e . Exception . Message } \n \n Log location: { GetLogDirectory ( ) } ",
119+ "Error" ,
120+ MessageBoxButton . OK ,
121+ MessageBoxImage . Error
122+ ) ;
33123
34- // Load settings
35- SettingsStore . LoadIntoSession ( ) ;
124+ // Mark as handled to prevent application crash
125+ e . Handled = true ;
126+ }
36127
37- // Start with main window
38- var mainWindow = _host . Services . GetRequiredService < MainWindow > ( ) ;
39- mainWindow . Show ( ) ;
128+ private void OnUnobservedTaskException ( object ? sender , UnobservedTaskExceptionEventArgs e )
129+ {
130+ Log . Error ( e . Exception , "Unobserved task exception" ) ;
131+ e . SetObserved ( ) ;
132+ }
40133
41- base . OnStartup ( e ) ;
134+ private static string GetLogDirectory ( )
135+ {
136+ return Path . Combine (
137+ Environment . GetFolderPath ( Environment . SpecialFolder . ApplicationData ) ,
138+ "IPTV-Desktop-Browser" ,
139+ "Logs"
140+ ) ;
42141 }
43142
44143 protected override void OnExit ( ExitEventArgs e )
45144 {
46- SettingsStore . SaveFromSession ( ) ;
47- _host ? . Dispose ( ) ;
145+ try
146+ {
147+ Log . Information ( "Application shutting down" ) ;
148+ SettingsStore . SaveFromSession ( ) ;
149+ _host ? . Dispose ( ) ;
150+ }
151+ catch ( Exception ex )
152+ {
153+ Log . Error ( ex , "Error during application shutdown" ) ;
154+ }
155+ finally
156+ {
157+ Log . CloseAndFlush ( ) ;
158+ }
159+
48160 base . OnExit ( e ) ;
49161 }
50162
@@ -53,12 +165,24 @@ private static IHostBuilder CreateHostBuilder()
53165 return Host . CreateDefaultBuilder ( )
54166 . ConfigureAppConfiguration ( ( context , config ) =>
55167 {
56- // Get the base directory where the executable is located
57- var basePath = AppDomain . CurrentDomain . BaseDirectory ;
168+ // Get configuration path from AppData (auto-creates if missing)
169+ var configPath = Configuration . ConfigurationManager . GetConfigurationPath ( ) ;
170+ var configDir = Path . GetDirectoryName ( configPath ) ?? AppDomain . CurrentDomain . BaseDirectory ;
171+
172+ Log . Information ( "Loading configuration from: {ConfigPath}" , configPath ) ;
58173
59- // Build configuration from appsettings.json
60- config . SetBasePath ( basePath )
61- . AddJsonFile ( "appsettings.json" , optional : false , reloadOnChange : true ) ;
174+ // Build configuration from appsettings.json in AppData
175+ config . SetBasePath ( configDir )
176+ . AddJsonFile ( Path . GetFileName ( configPath ) , optional : true , reloadOnChange : true ) ;
177+
178+ if ( File . Exists ( configPath ) )
179+ {
180+ Log . Information ( "Configuration file loaded successfully from AppData" ) ;
181+ }
182+ else
183+ {
184+ Log . Warning ( "Configuration file not found, using default values" ) ;
185+ }
62186 } )
63187 . ConfigureServices ( ( context , services ) =>
64188 {
@@ -105,17 +229,11 @@ private static IHostBuilder CreateHostBuilder()
105229 services . AddTransient < DashboardWindow > ( ) ;
106230 services . AddTransient < CacheInspectorWindow > ( ) ;
107231
108- // Configure logging from configuration
232+ // Configure logging with Serilog
109233 services . AddLogging ( builder =>
110234 {
111- builder . AddConsole ( ) ;
112- builder . AddDebug ( ) ;
113- builder . SetMinimumLevel ( LogLevel . Warning ) ;
114- // Reduce HTTP client logging noise
115- builder . AddFilter ( "System.Net.Http" , LogLevel . Warning ) ;
116- builder . AddFilter ( "Microsoft.Extensions.Http" , LogLevel . Warning ) ;
117- // Reduce service logging noise
118- builder . AddFilter ( "DesktopApp.Services" , LogLevel . Warning ) ;
235+ builder . ClearProviders ( ) ;
236+ builder . AddSerilog ( dispose : true ) ;
119237 } ) ;
120238 } ) ;
121239 }
0 commit comments