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

如何用PowerShell拦截Windows关机并执行预关机命令?

方案可行性分析与实现方法

这个方案是完全可行的,Windows原生支持进程拦截关机请求并执行自定义操作后放行,完全匹配你描述的流程。

对应流程的实际机制说明

  • 用户点击关机按钮后,Windows启动关机流程,向所有运行中的进程发送WM_QUERYENDSESSION系统消息(对应你说的步骤4:脚本接收关机信号)
  • 当你的脚本返回“阻止关机”的响应后,Windows会显示“正在阻止关机”的提示(步骤3),同时可能进入黑屏过渡状态(步骤2)
  • 脚本完成自定义命令执行后,取消关机阻止或主动退出,Windows检测到无拦截进程时,会继续完成关机(步骤5、6)

PowerShell实现代码示例

要实现这个逻辑,需要借助.NET的窗体消息处理机制,让PowerShell脚本能够监听并响应系统关机信号:

Add-Type @"
using System;
using System.Windows.Forms;

public class ShutdownInterceptor : Form
{
    private bool _shutdownAllowed = false;

    protected override void WndProc(ref Message m)
    {
        // 监听WM_QUERYENDSESSION消息(系统关机/注销时触发)
        const int WM_QUERYENDSESSION = 0x0011;
        if (m.Msg == WM_QUERYENDSESSION)
        {
            if (!_shutdownAllowed)
            {
                // 返回0阻止关机
                m.Result = IntPtr.Zero;
                // 启动后台线程执行自定义操作,避免阻塞系统消息循环
                System.Threading.ThreadPool.QueueUserWorkItem(_ => {
                    // --------------------------
                    // 这里替换为你的关机前命令
                    Write-Host "执行关机前清理操作..."
                    Start-Sleep -Seconds 3  # 模拟操作耗时
                    // --------------------------
                    
                    // 操作完成后允许关机
                    _shutdownAllowed = true;
                    // 重新触发关机流程(强制关闭所有进程)
                    System.Diagnostics.Process.Start("shutdown.exe", "/s /f /t 0").WaitForExit();
                });
            }
            else
            {
                // 返回1允许关机
                m.Result = new IntPtr(1);
            }
        }
        base.WndProc(ref m);
    }
}
"@

// 初始化拦截器(隐藏窗体,避免干扰用户)
$interceptor = New-Object ShutdownInterceptor
$interceptor.WindowState = [System.Windows.Forms.FormWindowState]::Minimized
$interceptor.ShowInTaskbar = $false
// 启动消息循环,保持脚本持续运行
[System.Windows.Forms.Application]::Run($interceptor)

关键注意事项

  • 脚本必须以管理员权限运行,否则可能无法正常拦截关机信号或执行高权限命令
  • 自定义操作的总耗时不要超过Windows的关机超时阈值(默认约30秒),超时后系统会强制终止脚本并继续关机
  • 代码中用shutdown.exe /s /f /t 0重新触发关机是必要的:第一次拦截后,Windows不会自动恢复关机流程,需要主动发起
  • 隐藏窗体的设置是为了让脚本在后台静默运行,不影响用户操作

内容的提问来源于stack exchange,提问作者Silloky

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 19:52:21