From 41ecf12abbb6c37d7282498d91d0502eb4044ce9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 21 Oct 2025 04:02:09 +0000 Subject: [PATCH] Add SessionEnding handler to prevent shutdown errors - Add SessionEnding event handler to gracefully handle Windows shutdown/logoff - Refactor cleanup code into PerformCleanup method with individual error handling - Wrap each disposal operation in try-catch to prevent cascade failures - This fixes exception code c0020001 during Windows 25H2 shutdown Co-authored-by: emako <24737061+emako@users.noreply.github.com> --- QuickLook/App.xaml | 1 + QuickLook/App.xaml.cs | 76 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 72 insertions(+), 5 deletions(-) diff --git a/QuickLook/App.xaml b/QuickLook/App.xaml index eae3a51..862223a 100644 --- a/QuickLook/App.xaml +++ b/QuickLook/App.xaml @@ -5,6 +5,7 @@ xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml" xmlns:vio="http://schemas.lepo.co/wpfui/2022/xaml/violeta" Exit="App_OnExit" + SessionEnding="App_OnSessionEnding" ShutdownMode="OnExplicitShutdown" Startup="Application_Startup"> diff --git a/QuickLook/App.xaml.cs b/QuickLook/App.xaml.cs index e9f0a43..fd6c4d3 100644 --- a/QuickLook/App.xaml.cs +++ b/QuickLook/App.xaml.cs @@ -282,17 +282,83 @@ public partial class App : Application PipeServerManager.GetInstance(); } + private void App_OnSessionEnding(object sender, SessionEndingCancelEventArgs e) + { + // Windows is shutting down or user is logging off + // Clean up resources gracefully to prevent CLR exceptions during shutdown + try + { + PerformCleanup(); + } + catch (Exception ex) + { + // Log the error but don't prevent shutdown + ProcessHelper.WriteLog($"Error during SessionEnding: {ex}"); + } + } + private void App_OnExit(object sender, ExitEventArgs e) { if (!_cleanExit) return; - _isRunning.ReleaseMutex(); + try + { + PerformCleanup(); + } + catch (Exception ex) + { + // Log the error but don't crash during exit + ProcessHelper.WriteLog($"Error during Exit: {ex}"); + } + } - PipeServerManager.GetInstance().Dispose(); - TrayIconManager.GetInstance().Dispose(); - KeystrokeDispatcher.GetInstance().Dispose(); - ViewWindowManager.GetInstance().Dispose(); + private void PerformCleanup() + { + try + { + _isRunning?.ReleaseMutex(); + } + catch (Exception ex) + { + ProcessHelper.WriteLog($"Error releasing mutex: {ex}"); + } + + try + { + PipeServerManager.GetInstance()?.Dispose(); + } + catch (Exception ex) + { + ProcessHelper.WriteLog($"Error disposing PipeServerManager: {ex}"); + } + + try + { + TrayIconManager.GetInstance()?.Dispose(); + } + catch (Exception ex) + { + ProcessHelper.WriteLog($"Error disposing TrayIconManager: {ex}"); + } + + try + { + KeystrokeDispatcher.GetInstance()?.Dispose(); + } + catch (Exception ex) + { + ProcessHelper.WriteLog($"Error disposing KeystrokeDispatcher: {ex}"); + } + + try + { + ViewWindowManager.GetInstance()?.Dispose(); + } + catch (Exception ex) + { + ProcessHelper.WriteLog($"Error disposing ViewWindowManager: {ex}"); + } } private bool EnsureFirstInstance(string[] args)