using System.IO; using System.Windows; using System.Windows.Interop; namespace DeskCore; public partial class App : Application { private const string MutexName = "DeskCore.Instanz"; private const string ShowEventName = "DeskCore.Anzeigen"; public static MainWindow? Win { get; private set; } public static Tray? TrayIcon { get; private set; } public static bool Quitting { get; private set; } private static Hotkey? _hotkey; private static Watcher? _watcher; private Mutex? _mutex; private EventWaitHandle? _showEvent; protected override void OnStartup(StartupEventArgs e) { // Nur eine Instanz: eine zweite holt einfach das vorhandene Fenster nach vorne _mutex = new Mutex(true, MutexName, out bool first); if (!first) { try { EventWaitHandle.OpenExisting(ShowEventName).Set(); } catch { } Shutdown(); return; } Migration.Run(); // alte "Desktop Sortierer"-Ordner übernehmen – vor allem anderen _showEvent = new EventWaitHandle(false, EventResetMode.AutoReset, ShowEventName); new Thread(() => { while (_showEvent.WaitOne()) Dispatcher.BeginInvoke(() => Win?.ShowFromBackground()); }) { IsBackground = true, Name = "ShowListener" }.Start(); DispatcherUnhandledException += (_, args) => { var log = Path.Combine(Storage.Root, "fehler.log"); try { File.AppendAllText(log, $"[{DateTime.Now}] {args.Exception}\n\n"); } catch { } MessageBox.Show($"Unerwarteter Fehler:\n\n{args.Exception.Message}\n\nDetails: {log}", "DeskCore", MessageBoxButton.OK, MessageBoxImage.Error); args.Handled = true; }; base.OnStartup(e); ShutdownMode = ShutdownMode.OnExplicitShutdown; Storage.FlushHolding(); // Reste eines Absturzes in den Papierkorb Theme.Init(); Theme.Changed += FenceManager.RefreshAll; Win = new MainWindow(); MainWindow = Win; var hwnd = new WindowInteropHelper(Win).EnsureHandle(); _hotkey = new Hotkey(hwnd); _hotkey.Pressed += () => Win.ToggleFromHotkey(); ApplyHotkey(); TrayIcon = new Tray(); TrayIcon.Clicked += () => Win.ShowFromBackground(); TrayIcon.BalloonClicked += () => Win.ShowFromBackground(); TrayIcon.MenuRequested += () => Win.ShowTrayMenu(); ApplyTray(); _watcher = new Watcher(Dispatcher); _watcher.Changed += () => { Win.OnStorageChanged(); FenceManager.RefreshAll(); }; _watcher.NewOnDesktop += Win.AutoSortNew; Autostart.RefreshPath(); bool minimized = e.Args.Contains("--minimized", StringComparer.OrdinalIgnoreCase); if (!minimized || !AppSettings.Current.TrayEnabled) Win.Show(); FenceManager.Sync(); } /// Tastenkürzel neu registrieren. false = von anderem Programm belegt. public static bool ApplyHotkey() { if (_hotkey is null) return false; var s = AppSettings.Current; if (!s.HotkeyEnabled) { _hotkey.Unregister(); return true; } return _hotkey.Register(s.HotkeyModifiers, s.HotkeyKey); } public static void ApplyTray() { if (TrayIcon is not null) TrayIcon.Visible = AppSettings.Current.TrayEnabled; } public static void Quit() { if (Quitting) return; Quitting = true; Win?.Undo.FlushAll(); FenceManager.CloseAll(); _watcher?.Dispose(); _hotkey?.Dispose(); TrayIcon?.Dispose(); Win?.Close(); Current.Shutdown(); } protected override void OnExit(ExitEventArgs e) { TrayIcon?.Dispose(); _mutex?.Dispose(); base.OnExit(e); } }