33// See the LICENSE file in the project root for more information.
44
55using System . Diagnostics . CodeAnalysis ;
6+ using System . Reflection ;
67using System . Windows ;
8+ using System . Windows . Threading ;
79using BlazorDesktop . Wpf ;
810using WebView2 . Runtime . AutoInstaller ;
911
@@ -17,28 +19,34 @@ namespace BlazorDesktop.Services;
1719/// </remarks>
1820/// <param name="lifetime">The <see cref="IHostApplicationLifetime"/>.</param>
1921/// <param name="services">The <see cref="IServiceProvider"/>.</param>
22+ /// <param name="logger">The <see cref="ILogger{TCategoryName}"/>.</param>
2023/// <param name="webViewInstaller">The <see cref="WebViewInstaller"/>.</param>
21- public class BlazorDesktopService ( IHostApplicationLifetime lifetime , IServiceProvider services , WebViewInstaller webViewInstaller ) : IHostedService , IDisposable
24+ public partial class BlazorDesktopService ( IHostApplicationLifetime lifetime , IServiceProvider services , ILogger < BlazorDesktopService > logger , WebViewInstaller webViewInstaller ) : IHostedService , IDisposable
2225{
2326 /// <summary>
24- /// The cancellation token registration .
27+ /// The application lifetime .
2528 /// </summary>
26- private CancellationTokenRegistration _applicationStoppingRegistration ;
29+ private readonly IHostApplicationLifetime _lifetime = lifetime ;
2730
2831 /// <summary>
29- /// The application lifetime .
32+ /// The services .
3033 /// </summary>
31- private readonly IHostApplicationLifetime _lifetime = lifetime ;
34+ private readonly IServiceProvider _services = services ;
35+
36+ /// <summary>
37+ /// The <see cref="ILogger{TCategoryName}"/>.
38+ /// </summary>
39+ private readonly ILogger < BlazorDesktopService > _logger = logger ;
3240
3341 /// <summary>
3442 /// The web view installer.
3543 /// </summary>
3644 private readonly WebViewInstaller _webViewInstaller = webViewInstaller ;
3745
3846 /// <summary>
39- /// The services .
47+ /// The cancellation token registration .
4048 /// </summary>
41- private readonly IServiceProvider _services = services ;
49+ private CancellationTokenRegistration _applicationStoppingRegistration ;
4250
4351 /// <summary>
4452 /// Starts the service.
@@ -69,6 +77,15 @@ public Task StopAsync(CancellationToken cancellationToken)
6977 return Task . CompletedTask ;
7078 }
7179
80+ /// <summary>
81+ /// Logs an unhanded component exception,
82+ /// </summary>
83+ /// <param name="logger">The <see cref="ILogger"/>.</param>
84+ /// <param name="message">The message.</param>
85+ /// <param name="exception">The <see cref="Exception"/>.</param>
86+ [ LoggerMessage ( 0 , LogLevel . Critical , "Unhandled exception rendering component: {Message}" , EventName = "ExceptionRenderingComponent" ) ]
87+ private static partial void LogUnhandledExceptionRenderingComponent ( ILogger logger , string message , Exception exception ) ;
88+
7289 /// <summary>
7390 /// The application thread.
7491 /// </summary>
@@ -79,10 +96,15 @@ private void ApplicationThread()
7996
8097 app . Startup += OnApplicationStartup ;
8198 app . Exit += OnApplicationExit ;
99+ app . DispatcherUnhandledException += OnApplicationException ;
82100
83101 app . MainWindow = mainWindow ;
84102
85103 app . Run ( ) ;
104+
105+ app . DispatcherUnhandledException -= OnApplicationException ;
106+ app . Exit -= OnApplicationExit ;
107+ app . Startup -= OnApplicationStartup ;
86108 }
87109
88110 /// <summary>
@@ -109,6 +131,25 @@ private void OnApplicationExit(object? sender, ExitEventArgs e)
109131 _lifetime . StopApplication ( ) ;
110132 }
111133
134+ /// <summary>
135+ /// Occurs when the application throws an exception.
136+ /// </summary>
137+ /// <param name="sender">The sending object.</param>
138+ /// <param name="e">The arguments.</param>
139+ private void OnApplicationException ( object sender , DispatcherUnhandledExceptionEventArgs e )
140+ {
141+ if ( e . Exception is TargetInvocationException && e . Exception . InnerException is not null )
142+ {
143+ LogUnhandledExceptionRenderingComponent ( _logger , e . Exception . InnerException . Message , e . Exception . InnerException ) ;
144+ }
145+ else
146+ {
147+ LogUnhandledExceptionRenderingComponent ( _logger , e . Exception . Message , e . Exception ) ;
148+ }
149+
150+ e . Handled = true ;
151+ }
152+
112153 /// <summary>
113154 /// Occurs when the application is stopping.
114155 /// </summary>
0 commit comments