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

如何在WinUI中阻止Windows关机直至完成指定操作?

如何在WinUI中阻止用户关闭Windows系统直至完成特定操作

可以实现,WinUI(尤其是桌面版)能实现类似WinForms的效果,核心是通过监听系统关闭相关的Win32消息来拦截关闭请求,以下是具体实现方案:

核心思路

系统在关闭前会向所有顶层窗口发送WM_QUERYENDSESSION消息,通过拦截这个消息并返回特定值,就能阻止系统关闭,直到你的特定操作完成。

具体实现(WinUI 3桌面应用)

在WinUI 3桌面应用中,你需要通过窗口句柄注册自定义的消息处理逻辑:

  1. 首先添加必要的引用和导入:
using Microsoft.UI.Xaml;
using System.Runtime.InteropServices;
  1. 在你的主窗口类中实现消息拦截:
private IntPtr _hwnd;
private WndProcDelegate _wndProcDelegate;
private IntPtr _oldWndProc;

// 定义窗口过程委托
private delegate IntPtr WndProcDelegate(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

protected override void OnActivated(WindowActivatedEventArgs args)
{
    base.OnActivated(args);
    // 仅初始化一次窗口消息处理
    if (_hwnd == IntPtr.Zero)
    {
        _hwnd = WindowNative.GetWindowHandle(this);
        _wndProcDelegate = WndProc;
        _oldWndProc = SetWindowLongPtr(_hwnd, GWLP_WNDPROC, Marshal.GetFunctionPointerForDelegate(_wndProcDelegate));
    }
}

private IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
    const uint WM_QUERYENDSESSION = 0x0011;
    const uint WM_ENDSESSION = 0x0016;

    switch (msg)
    {
        case WM_QUERYENDSESSION:
            // 检查特定操作是否完成
            if (!IsCriticalOperationCompleted())
            {
                // 返回0告知系统阻止关闭
                // 同时弹出提示告知用户
                DispatcherQueue.TryEnqueue(() =>
                {
                    var dialog = new ContentDialog
                    {
                        Title = "操作未完成",
                        Content = "请先完成当前的关键操作,再尝试关闭系统。",
                        PrimaryButtonText = "确定",
                        XamlRoot = Content.XamlRoot
                    };
                    _ = dialog.ShowAsync();
                });
                return IntPtr.Zero;
            }
            break;
        case WM_ENDSESSION:
            // 如果允许关闭,这里可以执行收尾清理操作
            break;
    }

    // 调用原窗口处理逻辑
    return CallWindowProc(_oldWndProc, hWnd, msg, wParam, lParam);
}

// 导入Win32 API
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

[DllImport("user32.dll")]
private static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

private const int GWLP_WNDPROC = -4;

// 自定义方法:判断特定操作是否完成
private bool IsCriticalOperationCompleted()
{
    // 替换为你的实际判断逻辑,比如检查任务是否完成、文件是否保存等
    return false;
}

注意事项

  • 该方案仅适用于WinUI 3桌面应用(包括打包为MSIX或非打包的版本);UWP版WinUI受沙箱限制,无法强制阻止系统关闭,只能通过弹窗提示用户。
  • 必须给用户明确的提示,避免用户困惑系统无法关闭的原因。
  • 不要滥用此功能,仅在用户进行未保存的关键操作等必要场景下使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 20:52:44