diff --git a/ShareX.HelpersLib/Native/NativeEnums.cs b/ShareX.HelpersLib/Native/NativeEnums.cs index cf501f446..b9a569f90 100644 --- a/ShareX.HelpersLib/Native/NativeEnums.cs +++ b/ShareX.HelpersLib/Native/NativeEnums.cs @@ -3131,4 +3131,42 @@ public enum CreateProcessFlags : uint PROFILE_SERVER = 0x40000000, CREATE_IGNORE_SYSTEM_DEFAULT = 0x80000000, } + + [Flags] + public enum RegisterApplicationRestartFlags : uint + { + /// + /// Do not restart the process if it terminates due to an unhandled exception. + /// + RESTART_NO_CRASH = 1, + /// + /// Do not restart the process if it terminates due to the application not responding. + /// + RESTART_NO_HANG = 2, + /// + /// Do not restart the process if it terminates due to the installation of an update. + /// + RESTART_NO_PATCH = 4, + /// + /// Do not restart the process if the computer is restarted as the result of an update. + /// + RESTART_NO_REBOOT = 8 + } + + [Flags] + public enum EndSessionReasons : uint + { + /// + /// The application is using a file that must be replaced, the system is being serviced, or system resources are exhausted. + /// + ENDSESSION_CLOSEAPP = 0x1, + /// + /// The application is forced to shut down. + /// + ENDSESSION_CRITICAL = 0x40000000, + /// + /// The user is logging off. + /// + ENDSESSION_LOGOFF = 0x80000000 + } } \ No newline at end of file diff --git a/ShareX.HelpersLib/Native/NativeMethods.cs b/ShareX.HelpersLib/Native/NativeMethods.cs index 91065e23c..46435842b 100644 --- a/ShareX.HelpersLib/Native/NativeMethods.cs +++ b/ShareX.HelpersLib/Native/NativeMethods.cs @@ -316,6 +316,9 @@ public static extern bool CreateProcess(string lpApplicationName, string lpComma [return: MarshalAs(UnmanagedType.Bool)] public static extern bool IsWow64Process([In] IntPtr hProcess, [Out] out bool lpSystemInfo); + [DllImport("kernel32.dll", PreserveSig = false)] + public static extern void RegisterApplicationRestart(string pwzCommandline, RegisterApplicationRestartFlags dwFlags); + #endregion kernel32.dll #region gdi32.dll diff --git a/ShareX/Forms/ActionsToolbarForm.cs b/ShareX/Forms/ActionsToolbarForm.cs index deab3c559..4c2d4291f 100644 --- a/ShareX/Forms/ActionsToolbarForm.cs +++ b/ShareX/Forms/ActionsToolbarForm.cs @@ -404,7 +404,8 @@ private void tslTitle_MouseDown(object sender, MouseEventArgs e) if (e.Button == MouseButtons.Left && !Program.Settings.ActionsToolbarLockPosition) { NativeMethods.ReleaseCapture(); - NativeMethods.DefWindowProc(Handle, (uint)WindowsMessages.SYSCOMMAND, (UIntPtr)NativeConstants.MOUSE_MOVE, IntPtr.Zero); + var m = Message.Create(Handle, (int)WindowsMessages.SYSCOMMAND, new IntPtr(NativeConstants.MOUSE_MOVE), IntPtr.Zero); + DefWndProc(ref m); } } diff --git a/ShareX/Forms/MainForm.cs b/ShareX/Forms/MainForm.cs index 82409b764..6af24c66f 100644 --- a/ShareX/Forms/MainForm.cs +++ b/ShareX/Forms/MainForm.cs @@ -298,6 +298,36 @@ public void UpdateControls() IsReady = true; } + protected override void WndProc(ref Message m) + { + if (m.Msg == (int)WindowsMessages.QUERYENDSESSION) + { + var reason = (EndSessionReasons)m.GetLParam(typeof(EndSessionReasons)); + if (reason.HasFlag(EndSessionReasons.ENDSESSION_CLOSEAPP)) + { + // Register for restart. This allows our application to automatically restart when it is installing an update from the Store. + // Also allows it to restart if it gets terminated for other reasons (see description of ENDSESSION_CLOSEAPP). + // Add the silent switch to avoid ShareX popping up in front of the user when the application restarts. + NativeMethods.RegisterApplicationRestart("-silent", 0); + } + m.Result = new IntPtr(1); // "Applications should respect the user's intentions and return TRUE." + } + else if (m.Msg == (int)WindowsMessages.ENDSESSION) + { + if (m.WParam != IntPtr.Zero) + { + // If wParam is not equal to false (0), the application can be terminated at any moment after processing this message + // thus should save its data while processing the message. + SettingManager.SaveAllSettings(); + } + m.Result = IntPtr.Zero; // "If an application processes this message, it should return zero." + } + else + { + base.WndProc(ref m); + } + } + private void AfterShownJobs() { if (!Program.Settings.ShowMostRecentTaskFirst && lvUploads.Items.Count > 0)