You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 01:15:45