Compare commits

...

2 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
41ecf12abb 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>
2025-10-21 04:02:09 +00:00
copilot-swe-agent[bot]
16712cf508 Initial plan 2025-10-21 03:55:33 +00:00
2 changed files with 72 additions and 5 deletions

View File

@@ -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">
<Application.Resources>

View File

@@ -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)