mirror of
https://github.com/duplicati/duplicati.git
synced 2026-05-06 07:16:38 -04:00
Merge pull request #6842 from duplicati/feature/added-crash-dialog-window
Add crash dialog
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
// Copyright (C) 2025, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Themes.Fluent;
|
||||
using ScrollBarVisibility = Avalonia.Controls.Primitives.ScrollBarVisibility;
|
||||
|
||||
namespace Duplicati.GUI.TrayIcon
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper class for showing error dialogs
|
||||
/// </summary>
|
||||
public static class ErrorDialog
|
||||
{
|
||||
/// <summary>
|
||||
/// Shows an error dialog for the crash, being very defensive to avoid additional crashes.
|
||||
/// This should only be called when the hosted server instance is crashing.
|
||||
/// </summary>
|
||||
/// <param name="ex">The exception to show</param>
|
||||
public static void ShowErrorDialog(Exception ex)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
// Build a simple Avalonia application to show the dialog
|
||||
var builder = AppBuilder
|
||||
.Configure<Application>()
|
||||
.UsePlatformDetect();
|
||||
|
||||
var app = builder.SetupWithoutStarting().Instance;
|
||||
if (app == null)
|
||||
return;
|
||||
|
||||
// Apply a simple theme so controls look native
|
||||
app.Styles.Add(new FluentTheme());
|
||||
|
||||
// Create the message box window
|
||||
var window = new Window
|
||||
{
|
||||
Title = "Duplicati TrayIcon Error",
|
||||
Width = 600,
|
||||
Height = 400,
|
||||
WindowStartupLocation = WindowStartupLocation.CenterScreen,
|
||||
CanResize = true,
|
||||
ShowInTaskbar = false,
|
||||
Topmost = true
|
||||
};
|
||||
|
||||
// Create the content
|
||||
var stackPanel = new StackPanel
|
||||
{
|
||||
Margin = new Thickness(20),
|
||||
Spacing = 10
|
||||
};
|
||||
|
||||
var titleBlock = new TextBlock
|
||||
{
|
||||
Text = "A fatal error occurred",
|
||||
FontSize = 16,
|
||||
FontWeight = FontWeight.Bold,
|
||||
TextWrapping = TextWrapping.Wrap
|
||||
};
|
||||
|
||||
var messageBlock = new TextBlock
|
||||
{
|
||||
Text = ex.Message,
|
||||
TextWrapping = TextWrapping.Wrap
|
||||
};
|
||||
|
||||
// Details label
|
||||
var detailsLabel = new TextBlock
|
||||
{
|
||||
Text = "Details:",
|
||||
FontWeight = FontWeight.Bold,
|
||||
Margin = new Thickness(0, 10, 0, 0)
|
||||
};
|
||||
|
||||
// Scrollable text area with full exception details
|
||||
var exceptionText = new TextBox
|
||||
{
|
||||
Text = ex.ToString(),
|
||||
IsReadOnly = true,
|
||||
TextWrapping = TextWrapping.NoWrap,
|
||||
AcceptsReturn = true,
|
||||
FontFamily = new FontFamily("Consolas, Monaco, Courier New, monospace"),
|
||||
FontSize = 10
|
||||
};
|
||||
|
||||
// Explicitly wrap in a ScrollViewer for proper scrolling
|
||||
var scrollViewer = new ScrollViewer
|
||||
{
|
||||
Content = exceptionText,
|
||||
HorizontalScrollBarVisibility = ScrollBarVisibility.Auto,
|
||||
VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
|
||||
Height = 200
|
||||
};
|
||||
|
||||
var buttonPanel = new StackPanel
|
||||
{
|
||||
Orientation = Orientation.Horizontal,
|
||||
HorizontalAlignment = HorizontalAlignment.Center,
|
||||
Margin = new Thickness(0, 20, 0, 0)
|
||||
};
|
||||
|
||||
var okButton = new Button
|
||||
{
|
||||
Content = "OK",
|
||||
Width = 100,
|
||||
HorizontalContentAlignment = HorizontalAlignment.Center
|
||||
};
|
||||
|
||||
okButton.Click += (_, _) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
window.Close();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore errors closing window
|
||||
}
|
||||
};
|
||||
buttonPanel.Children.Add(okButton);
|
||||
|
||||
stackPanel.Children.Add(titleBlock);
|
||||
stackPanel.Children.Add(messageBlock);
|
||||
stackPanel.Children.Add(detailsLabel);
|
||||
stackPanel.Children.Add(scrollViewer);
|
||||
stackPanel.Children.Add(buttonPanel);
|
||||
|
||||
window.Content = stackPanel;
|
||||
|
||||
app.Run(window);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,6 +98,22 @@ namespace Duplicati.GUI.TrayIcon
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
public static int Main(string[] _args)
|
||||
{
|
||||
try
|
||||
{
|
||||
return RunMain(_args);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Library.Crashlog.CrashlogHelper.LogCrashException(ex);
|
||||
ErrorDialog.ShowErrorDialog(ex);
|
||||
|
||||
Environment.Exit(1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static int RunMain(string[] _args)
|
||||
{
|
||||
PreloadSettingsLoader.ConfigurePreloadSettings(ref _args, PackageHelper.NamedExecutable.TrayIcon);
|
||||
var args = new List<string>(_args);
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
using Duplicati.Library.Crashlog;
|
||||
|
||||
namespace Duplicati.GUI.TrayIcon.Net10
|
||||
{
|
||||
@@ -26,6 +25,6 @@ namespace Duplicati.GUI.TrayIcon.Net10
|
||||
public static class Program
|
||||
{
|
||||
public static int Main(string[] args)
|
||||
=> CrashlogHelper.WrapWithCrashLog(() => Duplicati.GUI.TrayIcon.Program.Main(args));
|
||||
=> Duplicati.GUI.TrayIcon.Program.Main(args);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user