22using System . Collections . Generic ;
33using System . Diagnostics ;
44using System . IO ;
5+ using System . Threading . Tasks ;
56using System . Windows ;
7+ using System . Windows . Interop ;
8+ using System . Windows . Threading ;
69using System . Xml . Linq ;
710using Walkabout . Configuration ;
811using Walkabout . Help ;
@@ -23,6 +26,10 @@ namespace Walkabout
2326 /// </summary>
2427 public partial class App : Application
2528 {
29+ private ILogger rootLog ;
30+ private Log appLog ;
31+ private string logsLocation ;
32+
2633 private void MyApplicationStartup ( object sender , StartupEventArgs e )
2734 {
2835 Settings settings = null ;
@@ -31,6 +38,16 @@ private void MyApplicationStartup(object sender, StartupEventArgs e)
3138 using ( PerformanceBlock . Create ( ComponentId . Money , CategoryId . View , MeasurementId . AppInitialize ) )
3239 {
3340#endif
41+ var path = Path . Combine ( Path . GetTempPath ( ) , "MyMoney" ) ;
42+ var logs = Path . Combine ( path , "Logs" ) ;
43+ Directory . CreateDirectory ( logs ) ;
44+ this . rootLog = new Log ( logs ) ;
45+ this . appLog = Log . GetLogger ( "App" ) ;
46+ Log . CheckCrashLog ( path ) ;
47+
48+ Debug . WriteLine ( $ "Writing logs to { logs } ") ;
49+ appLog . Info ( "Launching MyMoney.Net" ) ;
50+
3451 HelpService . Initialize ( ) ;
3552
3653 Process currentRunningInstanceOfMyMoney = null ;
@@ -61,7 +78,11 @@ private void MyApplicationStartup(object sender, StartupEventArgs e)
6178 }
6279
6380 // Load the application settings
64- settings = LoadSettings ( noSettings ) ;
81+ settings = this . LoadSettings ( noSettings ) ;
82+
83+ System . Windows . Forms . Application . SetUnhandledExceptionMode ( System . Windows . Forms . UnhandledExceptionMode . CatchException ) ;
84+ AppDomain . CurrentDomain . UnhandledException += new UnhandledExceptionEventHandler ( this . OnAppDomainUnhandledException ) ;
85+ TaskScheduler . UnobservedTaskException += this . TaskScheduler_UnobservedTaskException1 ;
6586
6687#if PerformanceBlocks
6788 }
@@ -72,7 +93,15 @@ private void MyApplicationStartup(object sender, StartupEventArgs e)
7293 mainWindow . Show ( ) ;
7394 }
7495
75- public static Settings LoadSettings ( bool noSettings )
96+ protected override void OnExit ( ExitEventArgs e )
97+ {
98+ this . appLog ? . Info ( $ "App terminating with exit code { e . ApplicationExitCode } ") ;
99+ this . appLog ? . Dispose ( ) ;
100+ this . rootLog ? . Dispose ( ) ;
101+ base . OnExit ( e ) ;
102+ }
103+
104+ public Settings LoadSettings ( bool noSettings )
76105 {
77106 // make sure the directory exists.
78107 ProcessHelper . CreateSettingsDirectory ( ) ;
@@ -100,7 +129,7 @@ public static Settings LoadSettings(bool noSettings)
100129 }
101130 catch ( Exception ex )
102131 {
103- Debug . WriteLine ( "### Error reading settings: " + ex . Message ) ;
132+ this . appLog . Error ( "### Error reading settings: " + ex . Message ) ;
104133 }
105134
106135 Settings . TheSettings = s ;
@@ -214,12 +243,115 @@ private static Process FindCurrentRunningMoneyApplication()
214243 return null ;
215244 }
216245
246+ // stop re-entrancy
247+ private bool handlingException ;
217248
249+ private void OnUnhandledException ( object sender , System . Windows . Threading . DispatcherUnhandledExceptionEventArgs e )
250+ {
251+ this . appLog . Error ( "Unhandled app exception" , e . Exception ) ;
252+ if ( this . handlingException )
253+ {
254+ e . Handled = false ;
255+ }
256+ else
257+ {
258+ this . handlingException = true ;
259+ UiDispatcher . Invoke ( new Action ( ( ) =>
260+ {
261+ try
262+ {
263+ e . Handled = this . HandleUnhandledException ( e . Exception ) ;
264+ }
265+ catch ( Exception )
266+ {
267+ }
268+ this . handlingException = false ;
269+ } ) ) ;
270+ }
271+ }
272+
273+ private void OnAppDomainUnhandledException ( object sender , UnhandledExceptionEventArgs e )
274+ {
275+ this . appLog . Error ( "Unhandled app domain exception" , e . ExceptionObject as Exception ) ;
276+ if ( ! this . handlingException )
277+ {
278+ this . handlingException = true ;
279+ UiDispatcher . Invoke ( new Action ( ( ) =>
280+ {
281+ try
282+ {
283+ this . HandleUnhandledException ( e . ExceptionObject ) ;
284+ }
285+ catch ( Exception )
286+ {
287+ }
288+ this . handlingException = false ;
289+ } ) ) ;
290+ }
291+ }
292+
293+ private void TaskScheduler_UnobservedTaskException1 ( object sender , UnobservedTaskExceptionEventArgs e )
294+ {
295+ this . appLog . Error ( "Unhandled task scheduler exception" , e . Exception ) ;
296+ if ( ! this . handlingException )
297+ {
298+ this . handlingException = true ;
299+ e . SetObserved ( ) ;
300+ UiDispatcher . Invoke ( new Action ( ( ) =>
301+ {
302+ try
303+ {
304+ this . HandleUnhandledException ( e . Exception ) ;
305+ }
306+ catch ( Exception )
307+ {
308+ }
309+ this . handlingException = false ;
310+ } ) ) ;
311+ }
312+ }
218313
314+ public bool HandleUnhandledException ( object exceptionObject )
315+ {
316+ Exception ex = exceptionObject as Exception ;
317+ string message = null ;
318+ string details = null ;
319+ if ( ex == null && exceptionObject != null )
320+ {
321+ ex = new Exception ( exceptionObject . GetType ( ) . FullName + ": " + exceptionObject . ToString ( ) ) ;
322+ }
219323
324+ message = ex . Message ;
325+ details = ex . ToString ( ) ;
220326
327+ try
328+ {
329+ MessageBoxEx . Show ( message + " - " + Log . ReportLogging , "Unhandled Exception" , details , MessageBoxButton . OK , MessageBoxImage . Error ) ;
221330
222- }
331+ MainWindow mw = ( MainWindow ) Application . Current . MainWindow ;
332+ if ( mw != null && mw . IsVisible )
333+ {
334+ mw . SaveIfDirty ( "Unhandled exception, do you want to save your changes?" , null ) ;
335+ }
336+ return true ;
337+ }
338+ catch ( Exception )
339+ {
340+ // hmmm, if we can't show the dialog then perhaps this is some sort of stack overflow.
341+ // save the details to a file, terminate the process
342+ this . appLog . FatalUnhandledException ( message , ex ) ;
343+ return false ;
344+ }
345+ }
223346
347+ private void TaskScheduler_UnobservedTaskException ( object sender , UnobservedTaskExceptionEventArgs e )
348+ {
349+ if ( e . Exception != null )
350+ {
351+ this . HandleUnhandledException ( e . Exception ) ;
352+ }
353+ e . SetObserved ( ) ;
354+ }
224355
356+ }
225357}
0 commit comments