Skip to content

Commit 154ec05

Browse files
committed
Fix crash when shutting down or restarting #1782
1 parent 8d23f49 commit 154ec05

3 files changed

Lines changed: 90 additions & 69 deletions

File tree

‎QuickLook/App.xaml‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44
xmlns:local="clr-namespace:QuickLook"
55
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
66
xmlns:vio="http://schemas.lepo.co/wpfui/2022/xaml/violeta"
7-
Exit="App_OnExit"
8-
ShutdownMode="OnExplicitShutdown"
9-
Startup="Application_Startup">
7+
ShutdownMode="OnExplicitShutdown">
108
<Application.Resources>
119
<ResourceDictionary>
1210
<ResourceDictionary.MergedDictionaries>

‎QuickLook/App.xaml.cs‎

Lines changed: 64 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,21 @@ static IEnumerable<string> FetchFiles(string rootPath, string targetFileName)
114114

115115
protected override void OnStartup(StartupEventArgs e)
116116
{
117+
if (!EnsureOSVersion()
118+
|| !EnsureFirstInstance(e.Args)
119+
|| !EnsureFolderWritable(SettingHelper.LocalDataPath))
120+
{
121+
_cleanExit = false;
122+
Shutdown();
123+
return;
124+
}
125+
126+
RunListener(e);
127+
128+
// First instance: run and preview this file
129+
if (e.Args.Any() && (Directory.Exists(e.Args.First()) || File.Exists(e.Args.First())))
130+
PipeServerManager.SendMessage(PipeMessages.Toggle, e.Args.First());
131+
117132
// Exception handling events which are not caught in the Task thread
118133
TaskScheduler.UnobservedTaskException += (_, e) =>
119134
{
@@ -202,31 +217,41 @@ protected override void OnStartup(StartupEventArgs e)
202217

203218
// Set initial theme based on system settings
204219
ThemeManager.Apply(OSThemeHelper.AppsUseDarkTheme() ? ApplicationTheme.Dark : ApplicationTheme.Light);
205-
SystemEvents.UserPreferenceChanged += (_, _) =>
206-
ThemeManager.Apply(OSThemeHelper.AppsUseDarkTheme() ? ApplicationTheme.Dark : ApplicationTheme.Light);
207-
UxTheme.ApplyPreferredAppMode();
220+
UxTheme.ApplyPreferredAppMode(isTracked: true);
221+
SystemEvents.SessionEnding += OnSessionEnding;
208222

209223
// Initialize MessageBox patching
210224
MessageBoxPatcher.Initialize();
225+
226+
CheckUpdate();
211227
}
212228

213-
private void Application_Startup(object sender, StartupEventArgs e)
229+
protected virtual void OnSessionEnding(object sender, SessionEndingEventArgs e)
214230
{
215-
if (!EnsureOSVersion()
216-
|| !EnsureFirstInstance(e.Args)
217-
|| !EnsureFolderWritable(SettingHelper.LocalDataPath))
218-
{
219-
_cleanExit = false;
220-
Shutdown();
231+
SystemEvents.SessionEnding -= OnSessionEnding;
232+
233+
// You must unsubscribe from SystemEvents events before your application exits, or the application may crash
234+
// https://github.com/QL-Win/QuickLook/issues/1782
235+
UxTheme.ApplyPreferredAppMode(isTracked: false);
236+
}
237+
238+
protected override void OnExit(ExitEventArgs e)
239+
{
240+
// You must unsubscribe from SystemEvents events before your application exits, or the application may crash
241+
// https://github.com/QL-Win/QuickLook/issues/1782
242+
UxTheme.ApplyPreferredAppMode(isTracked: false);
243+
244+
base.OnExit(e);
245+
246+
if (!_cleanExit)
221247
return;
222-
}
223248

224-
CheckUpdate();
225-
RunListener(e);
249+
_isRunning.ReleaseMutex();
226250

227-
// First instance: run and preview this file
228-
if (e.Args.Any() && (Directory.Exists(e.Args.First()) || File.Exists(e.Args.First())))
229-
PipeServerManager.SendMessage(PipeMessages.Toggle, e.Args.First());
251+
PipeServerManager.GetInstance().Dispose();
252+
TrayIconManager.GetInstance().Dispose();
253+
KeystrokeDispatcher.GetInstance().Dispose();
254+
ViewWindowManager.GetInstance().Dispose();
230255
}
231256

232257
private bool EnsureOSVersion()
@@ -257,6 +282,28 @@ private bool EnsureFolderWritable(string folder)
257282
return true;
258283
}
259284

285+
private bool EnsureFirstInstance(string[] args)
286+
{
287+
_isRunning = new Mutex(true, "QuickLook.App.Mutex", out bool isFirst);
288+
289+
if (isFirst)
290+
return true;
291+
292+
// Second instance: preview this file
293+
if (args.Any() && (Directory.Exists(args.First()) || File.Exists(args.First())))
294+
{
295+
PipeServerManager.SendMessage(PipeMessages.Toggle, args.First(), [.. args.Skip(1)]);
296+
}
297+
// Second instance: duplicate
298+
else
299+
{
300+
MessageBox.Show(TranslationHelper.Get("APP_SECOND_TEXT"), TranslationHelper.Get("APP_SECOND"),
301+
MessageBoxButton.OK, MessageBoxImage.Information);
302+
}
303+
304+
return false;
305+
}
306+
260307
private void CheckUpdate()
261308
{
262309
if (SettingHelper.Get("DisableAutoUpdateCheck", false))
@@ -265,7 +312,7 @@ private void CheckUpdate()
265312
if (DateTime.Now.Ticks - SettingHelper.Get<long>("LastUpdateTicks") < TimeSpan.FromDays(30).Ticks)
266313
return;
267314

268-
Task.Delay(120 * 1000).ContinueWith(_ => Updater.CheckForUpdates(true));
315+
_ = Task.Delay(120 * 1000).ContinueWith(_ => Updater.CheckForUpdates(true));
269316
SettingHelper.Set("LastUpdateTicks", DateTime.Now.Ticks);
270317
}
271318

@@ -284,39 +331,4 @@ private void RunListener(StartupEventArgs e)
284331
KeystrokeDispatcher.GetInstance();
285332
PipeServerManager.GetInstance();
286333
}
287-
288-
private void App_OnExit(object sender, ExitEventArgs e)
289-
{
290-
if (!_cleanExit)
291-
return;
292-
293-
_isRunning.ReleaseMutex();
294-
295-
PipeServerManager.GetInstance().Dispose();
296-
TrayIconManager.GetInstance().Dispose();
297-
KeystrokeDispatcher.GetInstance().Dispose();
298-
ViewWindowManager.GetInstance().Dispose();
299-
}
300-
301-
private bool EnsureFirstInstance(string[] args)
302-
{
303-
_isRunning = new Mutex(true, "QuickLook.App.Mutex", out bool isFirst);
304-
305-
if (isFirst)
306-
return true;
307-
308-
// Second instance: preview this file
309-
if (args.Any() && (Directory.Exists(args.First()) || File.Exists(args.First())))
310-
{
311-
PipeServerManager.SendMessage(PipeMessages.Toggle, args.First(), [.. args.Skip(1)]);
312-
}
313-
// Second instance: duplicate
314-
else
315-
{
316-
MessageBox.Show(TranslationHelper.Get("APP_SECOND_TEXT"), TranslationHelper.Get("APP_SECOND"),
317-
MessageBoxButton.OK, MessageBoxImage.Information);
318-
}
319-
320-
return false;
321-
}
322334
}

‎QuickLook/NativeMethods/UxTheme.cs‎

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ internal static class UxTheme
4848

4949
public enum PreferredAppMode : int { Default, AllowDark, ForceDark, ForceLight, Max };
5050

51-
public static void ApplyPreferredAppMode()
51+
public static void ApplyPreferredAppMode(bool isTracked = true)
5252
{
5353
// Enable dark mode for context menus if using dark theme
5454
if (Environment.OSVersion.Version.Build >= 18362) // Windows 10 1903
@@ -65,20 +65,31 @@ public static void ApplyPreferredAppMode()
6565
FlushMenuThemes();
6666
}
6767

68-
// Synchronize the theme with system settings
69-
SystemEvents.UserPreferenceChanged += (_, _) =>
68+
// If you want to follow the system theme
69+
if (isTracked)
7070
{
71-
if (OSThemeHelper.SystemUsesDarkTheme())
72-
{
73-
SetPreferredAppMode(PreferredAppMode.ForceDark);
74-
FlushMenuThemes();
75-
}
76-
else
77-
{
78-
SetPreferredAppMode(PreferredAppMode.ForceLight);
79-
FlushMenuThemes();
80-
}
81-
};
71+
// Synchronize the theme with system settings
72+
SystemEvents.UserPreferenceChanged -= OnUserPreferenceChanged;
73+
SystemEvents.UserPreferenceChanged += OnUserPreferenceChanged;
74+
}
75+
else
76+
{
77+
SystemEvents.UserPreferenceChanged -= OnUserPreferenceChanged;
78+
}
79+
}
80+
81+
static void OnUserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
82+
{
83+
if (OSThemeHelper.SystemUsesDarkTheme())
84+
{
85+
SetPreferredAppMode(PreferredAppMode.ForceDark);
86+
FlushMenuThemes();
87+
}
88+
else
89+
{
90+
SetPreferredAppMode(PreferredAppMode.ForceLight);
91+
FlushMenuThemes();
92+
}
8293
}
8394
}
8495
}

0 commit comments

Comments
 (0)