Finalize DI: drop transitional VM ctor; harden disposal

Remove the transitional MainWindowViewModel(AppSettings, IStartupTracer) constructor and the _ownsServices flag now that every caller resolves the view model from the container; the container owns and disposes the hardware monitor (driver unload), so the view model no longer disposes it. Make HardwareMonitorService.Dispose idempotent with a _disposed guard, and run provider disposal in a finally block in MainWindow_Closed so the ring0 driver is always unloaded on real exit even if an earlier teardown step throws.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-06-02 15:25:39 -05:00
co-authored by Copilot
parent dcb6a5b803
commit 5aa7c30a6a
3 changed files with 22 additions and 39 deletions
@@ -456,16 +456,22 @@ public sealed partial class MainWindow : Window
}
_isShuttingDown = true;
_timer.Stop();
_columnMeasurer.StopSettleTimer();
_trayIconService.Dispose();
_secondaryWindows.CloseAll();
_placementService.Save();
// The container owns the view model and domain services. Disposing the provider runs
// MainWindowViewModel.Dispose first (reverse construction order) to persist settings while the
// hardware monitor and web server are still alive, then disposes those services and the tracer.
(_serviceProvider as IDisposable)?.Dispose();
try
{
_timer.Stop();
_columnMeasurer.StopSettleTimer();
_trayIconService.Dispose();
_secondaryWindows.CloseAll();
_placementService.Save();
}
finally
{
// The container owns the view model and domain services. Disposing the provider runs
// MainWindowViewModel.Dispose first (reverse construction order) to persist settings while the
// hardware monitor and web server are still alive, then disposes those services and the tracer.
// This MUST run even if a teardown step above throws, so the ring0 driver is always unloaded.
(_serviceProvider as IDisposable)?.Dispose();
}
}
private void AppWindow_Changed(AppWindow sender, AppWindowChangedEventArgs args)