Windows窗体应用:系统关机挂起进程并取消后恢复的实现方案
解决方案:Windows关机时挂起并恢复WinForm应用
核心逻辑梳理
要实现需求,关键是正确处理系统关机消息,同时用进程挂起/恢复替代你现有RestartApp_方法里的“杀死再重启”逻辑:
- 收到
WM_QUERYENDSESSION时,必须返回true(允许关机),避免系统弹出阻止提示;同时触发进程挂起操作。 - 收到
WM_ENDSESSION时,通过wParam判断关机是否取消:若wParam为0,说明用户取消关机,此时恢复进程运行。
完整代码实现
首先在Form类中添加常量定义、状态标记,并重写WndProc:
using System; using System.Diagnostics; using System.Windows.Forms; public partial class MainForm : Form { // 系统关机相关消息常量 private const int WM_QUERYENDSESSION = 0x0011; private const int WM_ENDSESSION = 0x0016; // 标记进程是否已挂起 private bool _isProcessSuspended = false; // 当前应用进程实例 private Process _currentProcess; public MainForm() { InitializeComponent(); _currentProcess = Process.GetCurrentProcess(); } protected override void WndProc(ref Message m) { base.WndProc(ref m); switch (m.Msg) { case WM_QUERYENDSESSION: // 返回允许关机,避免系统提示进程阻止关机 m.Result = (IntPtr)1; // 挂起当前进程(仅当未挂起时执行) if (!_isProcessSuspended) { SuspendCurrentProcess(); } break; case WM_ENDSESSION: // wParam为0表示关机操作被用户取消 if (m.WParam == IntPtr.Zero && _isProcessSuspended) { // 恢复进程运行 ResumeCurrentProcess(); } break; } } // 挂起当前进程 private void SuspendCurrentProcess() { try { foreach (ProcessThread thread in _currentProcess.Threads) { thread.Suspend(); } _isProcessSuspended = true; } catch (Exception ex) { // 处理权限或其他异常,比如日志记录 MessageBox.Show($"挂起进程失败:{ex.Message}"); } } // 恢复当前进程 private void ResumeCurrentProcess() { try { foreach (ProcessThread thread in _currentProcess.Threads) { thread.Resume(); } _isProcessSuspended = false; } catch (Exception ex) { MessageBox.Show($"恢复进程失败:{ex.Message}"); } } }
关键注意事项
- 权限要求:挂起/恢复进程需要足够的系统权限,建议将应用以管理员身份运行,否则可能抛出权限异常。
- 线程处理:遍历进程的所有线程进行挂起/恢复,确保整个进程完全暂停。
- 状态标记:用
_isProcessSuspended避免重复挂起或恢复操作,防止逻辑混乱。 - WM_ENDSESSION参数判断:必须通过
wParam区分“真正关机”和“取消关机”,只有取消时才恢复进程。
优化原有重启方法(可选)
若后续需要重启场景(而非挂起恢复),可将你的RestartApp_优化为:
static void RestartApp(int pid, string applicationName) { try { var process = Process.GetProcessById(pid); process.WaitForExit(5000); if (!process.HasExited) { process.Kill(); process.WaitForExit(); } Process.Start(applicationName); } catch (Exception ex) { // 异常处理逻辑 } }
内容的提问来源于stack exchange,提问作者Werich Ataliba
相关产品推荐
相关产品推荐

