diff --git a/Source/AppScaffolding/LibationScaffolding.cs b/Source/AppScaffolding/LibationScaffolding.cs
index 251a05e4..10732bcd 100644
--- a/Source/AppScaffolding/LibationScaffolding.cs
+++ b/Source/AppScaffolding/LibationScaffolding.cs
@@ -256,18 +256,21 @@ namespace AppScaffolding
private static void logStartupState(Configuration config)
{
+#if DEBUG
+ var mode = "Debug";
+#else
+ var mode = "Release";
+#endif
+ if (System.Diagnostics.Debugger.IsAttached)
+ mode += " (Debugger attached)";
+
// begin logging session with a form feed
Log.Logger.Information("\r\n\f");
Log.Logger.Information("Begin. {@DebugInfo}", new
{
AppName = EntryAssembly.GetName().Name,
Version = BuildVersion.ToString(),
-#if DEBUG
- Mode = "Debug",
-#else
- Mode = "Release",
-#endif
-
+ Mode = mode,
LogLevel_Verbose_Enabled = Log.Logger.IsVerboseEnabled(),
LogLevel_Debug_Enabled = Log.Logger.IsDebugEnabled(),
LogLevel_Information_Enabled = Log.Logger.IsInformationEnabled(),
diff --git a/Source/LibationWinForms/Dialogs/AccountsDialog.cs b/Source/LibationWinForms/Dialogs/AccountsDialog.cs
index 944516f9..e2a90e2a 100644
--- a/Source/LibationWinForms/Dialogs/AccountsDialog.cs
+++ b/Source/LibationWinForms/Dialogs/AccountsDialog.cs
@@ -124,7 +124,7 @@ namespace LibationWinForms.Dialogs
}
catch (Exception ex)
{
- MessageBoxLib.ShowAdminAlert("Error attempting to save accounts", "Error saving accounts", ex);
+ MessageBoxLib.ShowAdminAlert(this, "Error attempting to save accounts", "Error saving accounts", ex);
}
}
diff --git a/Source/LibationWinForms/Dialogs/EditTemplateDialog.cs b/Source/LibationWinForms/Dialogs/EditTemplateDialog.cs
index 693072f7..3848c2c1 100644
--- a/Source/LibationWinForms/Dialogs/EditTemplateDialog.cs
+++ b/Source/LibationWinForms/Dialogs/EditTemplateDialog.cs
@@ -46,7 +46,7 @@ namespace LibationWinForms.Dialogs
if (template is null)
{
- MessageBoxLib.ShowAdminAlert($"Programming error. {nameof(EditTemplateDialog)} was not created correctly", "Edit template error", new NullReferenceException($"{nameof(template)} is null"));
+ MessageBoxLib.ShowAdminAlert(this, $"Programming error. {nameof(EditTemplateDialog)} was not created correctly", "Edit template error", new NullReferenceException($"{nameof(template)} is null"));
return;
}
diff --git a/Source/LibationWinForms/Dialogs/RemoveBooksDialog.cs b/Source/LibationWinForms/Dialogs/RemoveBooksDialog.cs
index 558095f0..84e5ff51 100644
--- a/Source/LibationWinForms/Dialogs/RemoveBooksDialog.cs
+++ b/Source/LibationWinForms/Dialogs/RemoveBooksDialog.cs
@@ -77,6 +77,7 @@ namespace LibationWinForms.Dialogs
catch (Exception ex)
{
MessageBoxLib.ShowAdminAlert(
+ this,
"Error scanning library. You may still manually select books to remove from Libation's library.",
"Error scanning library",
ex);
diff --git a/Source/LibationWinForms/Form1.Export.cs b/Source/LibationWinForms/Form1.Export.cs
index ae538cd2..4451a7c6 100644
--- a/Source/LibationWinForms/Form1.Export.cs
+++ b/Source/LibationWinForms/Form1.Export.cs
@@ -40,7 +40,7 @@ namespace LibationWinForms
}
catch (Exception ex)
{
- MessageBoxLib.ShowAdminAlert("Error attempting to export your library.", "Error exporting", ex);
+ MessageBoxLib.ShowAdminAlert(this, "Error attempting to export your library.", "Error exporting", ex);
}
}
}
diff --git a/Source/LibationWinForms/Form1.ScanManual.cs b/Source/LibationWinForms/Form1.ScanManual.cs
index 1ba25b6f..4b9215d9 100644
--- a/Source/LibationWinForms/Form1.ScanManual.cs
+++ b/Source/LibationWinForms/Form1.ScanManual.cs
@@ -126,6 +126,7 @@ namespace LibationWinForms
catch (Exception ex)
{
MessageBoxLib.ShowAdminAlert(
+ this,
"Error importing library. Please try again. If this still happens after 2 or 3 tries, stop and contact administrator",
"Error importing library",
ex);
diff --git a/Source/LibationWinForms/MessageBoxLib.cs b/Source/LibationWinForms/MessageBoxLib.cs
index 926cf747..040a9293 100644
--- a/Source/LibationWinForms/MessageBoxLib.cs
+++ b/Source/LibationWinForms/MessageBoxLib.cs
@@ -4,22 +4,27 @@ using System.Linq;
using System.Windows.Forms;
using DataLayer;
using Dinah.Core.Logging;
+using Dinah.Core.Threading;
using LibationWinForms.Dialogs;
using Serilog;
namespace LibationWinForms
{
- public static class MessageBoxLib
+ public static class MessageBoxLib
{
///
/// Logs error. Displays a message box dialog with specified text and caption.
///
+ /// Form calling this method.
/// The text to display in the message box.
/// The text to display in the title bar of the message box.
- /// Exception to log
- /// One of the System.Windows.Forms.DialogResult values.
- public static DialogResult ShowAdminAlert(string text, string caption, Exception exception)
+ /// Exception to log.
+ public static void ShowAdminAlert(System.ComponentModel.ISynchronizeInvoke owner, string text, string caption, Exception exception)
{
+ // for development and debugging, show me what broke!
+ if (System.Diagnostics.Debugger.IsAttached)
+ throw exception;
+
try
{
Serilog.Log.Logger.Error(exception, "Alert admin error: {@DebugText}", new { text, caption });
@@ -27,10 +32,22 @@ namespace LibationWinForms
catch { }
using var form = new MessageBoxAlertAdminDialog(text, caption, exception);
- return form.ShowDialog();
+
+ if (owner is not null)
+ {
+ try
+ {
+ owner.UIThreadSync(() => form.ShowDialog());
+ return;
+ }
+ catch { }
+ }
+
+ // synchronizeInvoke is null or previous attempt failed. final try
+ form.ShowDialog();
}
- public static void VerboseLoggingWarning_ShowIfTrue()
+ public static void VerboseLoggingWarning_ShowIfTrue()
{
// when turning on debug (and especially Verbose) to share logs, some privacy settings may not be obscured
if (Log.Logger.IsVerboseEnabled())
diff --git a/Source/LibationWinForms/Program.cs b/Source/LibationWinForms/Program.cs
index 1263f2a3..ecf2344a 100644
--- a/Source/LibationWinForms/Program.cs
+++ b/Source/LibationWinForms/Program.cs
@@ -49,7 +49,7 @@ namespace LibationWinForms
#if !DEBUG
checkForUpdate();
#endif
-
+ // logging is init'd here
AppScaffolding.LibationScaffolding.RunPostMigrationScaffolding(config);
}
catch (Exception ex)
@@ -58,14 +58,17 @@ namespace LibationWinForms
var body = "An unrecoverable error occurred. Since this error happened before logging could be initialized, this error can not be written to the log file.";
try
{
- MessageBoxLib.ShowAdminAlert(body, title, ex);
+ MessageBoxLib.ShowAdminAlert(null, body, title, ex);
}
catch
{
MessageBox.Show($"{body}\r\n\r\n{ex.Message}\r\n\r\n{ex.StackTrace}", title, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return;
- }
+ }
+
+ // global exception handling (ShowAdminAlert) attempts to use logging. only call it after logging has been init'd
+ postLoggingGlobalExceptionHandling();
Application.Run(new Form1());
}
@@ -170,7 +173,7 @@ namespace LibationWinForms
}
catch (Exception ex)
{
- MessageBoxLib.ShowAdminAlert("Error checking for update", "Error checking for update", ex);
+ MessageBoxLib.ShowAdminAlert(null, "Error checking for update", "Error checking for update", ex);
return;
}
@@ -182,5 +185,16 @@ namespace LibationWinForms
Updater.Run(upgradeProperties.LatestRelease, upgradeProperties.ZipUrl);
}
+
+ private static void postLoggingGlobalExceptionHandling()
+ {
+ // this line is all that's needed for strict handling
+ AppDomain.CurrentDomain.UnhandledException += (_, e) => MessageBoxLib.ShowAdminAlert(null, "Libation has crashed due to an unhandled error.", "Application crash!", (Exception)e.ExceptionObject);
+
+ // these 2 lines makes it graceful. sync (eg in main form's ctor) and thread exceptions will still crash us, but event (sync, void async, Task async) will not
+ Application.ThreadException += (_, e) => MessageBoxLib.ShowAdminAlert(null, "Libation has encountered an unexpected error.", "Unexpected error", e.Exception);
+ // I never found a case where including made a difference. I think this enum is default and including it will override app user config file
+ Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
+ }
}
}
diff --git a/Source/LibationWinForms/Updater.cs b/Source/LibationWinForms/Updater.cs
index 032ed07b..1506f924 100644
--- a/Source/LibationWinForms/Updater.cs
+++ b/Source/LibationWinForms/Updater.cs
@@ -43,7 +43,7 @@ namespace LibationWinForms
}
catch (Exception ex)
{
- MessageBoxLib.ShowAdminAlert("Error downloading update", "Error downloading update", ex);
+ MessageBoxLib.ShowAdminAlert(null, "Error downloading update", "Error downloading update", ex);
}
}
}