diff --git a/RolandK.AvaloniaExtensions.sln b/RolandK.AvaloniaExtensions.sln
index a7c630c..922365c 100644
--- a/RolandK.AvaloniaExtensions.sln
+++ b/RolandK.AvaloniaExtensions.sln
@@ -15,6 +15,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RolandK.AvaloniaExtensions.
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RolandK.AvaloniaExtensions.ExceptionHandling", "src\RolandK.AvaloniaExtensions.ExceptionHandling\RolandK.AvaloniaExtensions.ExceptionHandling.csproj", "{FC6CF99C-571A-454F-B385-52F0DEC21BFA}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RolandK.AvaloniaExtensions.TestApp.ExceptionViewer", "src\RolandK.AvaloniaExtensions.TestApp.ExceptionViewer\RolandK.AvaloniaExtensions.TestApp.ExceptionViewer.csproj", "{ED908FBE-7113-4E38-A725-89AA6B4BA9C2}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -45,6 +47,10 @@ Global
{FC6CF99C-571A-454F-B385-52F0DEC21BFA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC6CF99C-571A-454F-B385-52F0DEC21BFA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC6CF99C-571A-454F-B385-52F0DEC21BFA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {ED908FBE-7113-4E38-A725-89AA6B4BA9C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {ED908FBE-7113-4E38-A725-89AA6B4BA9C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {ED908FBE-7113-4E38-A725-89AA6B4BA9C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {ED908FBE-7113-4E38-A725-89AA6B4BA9C2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/RolandK.AvaloniaExtensions.ExceptionHandling/GlobalErrorReporting.cs b/src/RolandK.AvaloniaExtensions.ExceptionHandling/GlobalErrorReporting.cs
index a5e0778..d6b4492 100644
--- a/src/RolandK.AvaloniaExtensions.ExceptionHandling/GlobalErrorReporting.cs
+++ b/src/RolandK.AvaloniaExtensions.ExceptionHandling/GlobalErrorReporting.cs
@@ -33,12 +33,15 @@ public static async Task ShowGlobalExceptionDialogAsync(
///
/// Tries to show an error dialog with some exception details.
/// If it is not possible for any reason, this method simply does nothing.
+ ///
+ /// This call is a blocking call. It es meant to be called within a global
+ /// try-catch block in Program.cs
///
/// The exception to be shown to the user.
/// This should be a technical name, the method uses it to create a temporary directory in the filesystem.
/// The project name of the executable showing the error dialog.
/// If null, a default collection of IExceptionAnalyzers ist used.
- public static void TryShowGlobalExceptionDialogInAnotherProcess(
+ public static void TryShowBlockingGlobalExceptionDialogInAnotherProcess(
Exception exception,
string applicationTempDirectoryName,
string exceptionViewerExecutableProjectName,
diff --git a/src/RolandK.AvaloniaExtensions.TestApp.ExceptionViewer/App.axaml b/src/RolandK.AvaloniaExtensions.TestApp.ExceptionViewer/App.axaml
new file mode 100644
index 0000000..796ddca
--- /dev/null
+++ b/src/RolandK.AvaloniaExtensions.TestApp.ExceptionViewer/App.axaml
@@ -0,0 +1,8 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/RolandK.AvaloniaExtensions.TestApp.ExceptionViewer/App.axaml.cs b/src/RolandK.AvaloniaExtensions.TestApp.ExceptionViewer/App.axaml.cs
new file mode 100644
index 0000000..9c39079
--- /dev/null
+++ b/src/RolandK.AvaloniaExtensions.TestApp.ExceptionViewer/App.axaml.cs
@@ -0,0 +1,12 @@
+using Avalonia.Markup.Xaml;
+using RolandK.AvaloniaExtensions.ExceptionHandling;
+
+namespace RolandK.AvaloniaExtensions.TestApp.ExceptionViewer;
+
+public partial class App : ExceptionViewerApplication
+{
+ public override void Initialize()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+}
\ No newline at end of file
diff --git a/src/RolandK.AvaloniaExtensions.TestApp.ExceptionViewer/Program.cs b/src/RolandK.AvaloniaExtensions.TestApp.ExceptionViewer/Program.cs
new file mode 100644
index 0000000..966ab55
--- /dev/null
+++ b/src/RolandK.AvaloniaExtensions.TestApp.ExceptionViewer/Program.cs
@@ -0,0 +1,21 @@
+using Avalonia;
+using System;
+
+namespace RolandK.AvaloniaExtensions.TestApp.ExceptionViewer;
+
+internal class Program
+{
+ // Initialization code. Don't use any Avalonia, third-party APIs or any
+ // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
+ // yet and stuff might break.
+ [STAThread]
+ public static void Main(string[] args) => BuildAvaloniaApp()
+ .StartWithClassicDesktopLifetime(args);
+
+ // Avalonia configuration, don't remove; also used by visual designer.
+ public static AppBuilder BuildAvaloniaApp()
+ => AppBuilder.Configure()
+ .UsePlatformDetect()
+ .WithInterFont()
+ .LogToTrace();
+}
\ No newline at end of file
diff --git a/src/RolandK.AvaloniaExtensions.TestApp.ExceptionViewer/RolandK.AvaloniaExtensions.TestApp.ExceptionViewer.csproj b/src/RolandK.AvaloniaExtensions.TestApp.ExceptionViewer/RolandK.AvaloniaExtensions.TestApp.ExceptionViewer.csproj
new file mode 100644
index 0000000..c8df37f
--- /dev/null
+++ b/src/RolandK.AvaloniaExtensions.TestApp.ExceptionViewer/RolandK.AvaloniaExtensions.TestApp.ExceptionViewer.csproj
@@ -0,0 +1,22 @@
+
+
+ WinExe
+ net8.0
+ enable
+ false
+ copyused
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/RolandK.AvaloniaExtensions.TestApp/MainWindow.axaml b/src/RolandK.AvaloniaExtensions.TestApp/MainWindow.axaml
index cc30298..3e5d769 100644
--- a/src/RolandK.AvaloniaExtensions.TestApp/MainWindow.axaml
+++ b/src/RolandK.AvaloniaExtensions.TestApp/MainWindow.axaml
@@ -35,6 +35,14 @@
Command="{Binding Path=RecreateTestDataCommand}"/>
+
+
+
+
+
diff --git a/src/RolandK.AvaloniaExtensions.TestApp/MainWindow.axaml.cs b/src/RolandK.AvaloniaExtensions.TestApp/MainWindow.axaml.cs
index bbb33c3..a1dc699 100644
--- a/src/RolandK.AvaloniaExtensions.TestApp/MainWindow.axaml.cs
+++ b/src/RolandK.AvaloniaExtensions.TestApp/MainWindow.axaml.cs
@@ -1,3 +1,6 @@
+using System;
+using Avalonia.Interactivity;
+using RolandK.AvaloniaExtensions.ExceptionHandling;
using RolandK.AvaloniaExtensions.Mvvm.Controls;
namespace RolandK.AvaloniaExtensions.TestApp;
@@ -8,4 +11,36 @@ public MainWindow()
{
this.InitializeComponent();
}
+
+ private async void OnMnu_ShowDummyException_ThisProcess_Click(object? sender, RoutedEventArgs e)
+ {
+ try
+ {
+ throw new InvalidOperationException("Dummy exception");
+ }
+ catch (Exception ex)
+ {
+ await GlobalErrorReporting.ShowGlobalExceptionDialogAsync(ex, this);
+ }
+ }
+
+ private void OnMnu_ShowDummyException_OtherProcess_Click(object? sender, RoutedEventArgs e)
+ {
+ try
+ {
+ throw new InvalidOperationException("Dummy exception");
+ }
+ catch (Exception ex)
+ {
+ GlobalErrorReporting.TryShowBlockingGlobalExceptionDialogInAnotherProcess(
+ ex,
+ ".RKAvaloniaExtensions.TestApp",
+ "RolandK.AvaloniaExtensions.TestApp.ExceptionViewer");
+ }
+ }
+
+ private void OnMnu_SimulateUnhandledException_Click(object? sender, RoutedEventArgs e)
+ {
+ throw new InvalidOperationException("Dummy exception");
+ }
}
diff --git a/src/RolandK.AvaloniaExtensions.TestApp/Program.cs b/src/RolandK.AvaloniaExtensions.TestApp/Program.cs
index ba9a430..4d7f355 100644
--- a/src/RolandK.AvaloniaExtensions.TestApp/Program.cs
+++ b/src/RolandK.AvaloniaExtensions.TestApp/Program.cs
@@ -2,6 +2,7 @@
using Avalonia;
using Microsoft.Extensions.DependencyInjection;
using RolandK.AvaloniaExtensions.DependencyInjection;
+using RolandK.AvaloniaExtensions.ExceptionHandling;
using RolandK.AvaloniaExtensions.TestApp.Services;
namespace RolandK.AvaloniaExtensions.TestApp;
@@ -12,8 +13,21 @@ public static class Program
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
- public static void Main(string[] args) => BuildAvaloniaApp()
- .StartWithClassicDesktopLifetime(args);
+ public static void Main(string[] args)
+ {
+ try
+ {
+ BuildAvaloniaApp()
+ .StartWithClassicDesktopLifetime(args);
+ }
+ catch (Exception ex)
+ {
+ GlobalErrorReporting.TryShowBlockingGlobalExceptionDialogInAnotherProcess(
+ ex,
+ ".RKAvaloniaExtensions.TestApp",
+ "RolandK.AvaloniaExtensions.TestApp.ExceptionViewer");
+ }
+ }
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
diff --git a/src/RolandK.AvaloniaExtensions.TestApp/RolandK.AvaloniaExtensions.TestApp.csproj b/src/RolandK.AvaloniaExtensions.TestApp/RolandK.AvaloniaExtensions.TestApp.csproj
index 2461c58..ab10d27 100644
--- a/src/RolandK.AvaloniaExtensions.TestApp/RolandK.AvaloniaExtensions.TestApp.csproj
+++ b/src/RolandK.AvaloniaExtensions.TestApp/RolandK.AvaloniaExtensions.TestApp.csproj
@@ -30,6 +30,8 @@
+
+