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

如何阻止MAUI应用被关闭?Windows及Android平台适配问询

MAUI应用阻止关闭及后台运行相关问题

问题描述

我知道当前问题比较宽泛,但有没有办法阻止Windows和Android平台上的MAUI应用被关闭?我注意到MAUI的Window类没法像WPF那样重写OnClosing方法并设置Cancel为true,这应该是MAUI跨平台特性导致的。

另外,能不能把应用转为服务或者用其他方式让它在后台运行,等计算完成后推送通知?

目前我只尝试过重写Window类的OnDestroying方法,但不知道后续该怎么做。

相关代码

App.xaml.cs

public partial class App : Application
{
    public App()
    {
        InitializeComponent();
        
        MainPage = new AppShell(); 
    }

    protected override MyWindow CreateWindow(IActivationState activationState)
    {
        return new MyWindow(MainPage);
    }
}

MyWindow.cs

public class MyWindow : Window
{
    public MyWindow() : base()
    {
    }

    public MyWindow(Page page) : base(page)
    {
    }

    protected override void OnDestroying()
    {
        System.Diagnostics.Debug.WriteLine("Destroying");

    }

    protected override void OnStopped()
    {
        System.Diagnostics.Debug.WriteLine("Stopping");

    }

    protected override void OnDeactivated()
    {
        System.Diagnostics.Debug.WriteLine("Deactivating");
}

生命周期日志异常

我还发现OnStopped的触发早于OnDestroying,这和MAUI官方文档描述的不符,让我很困惑。

输出日志:

Destroying
Stopping
Deactivating
The program '[9736] MauiApp.exe' has exited with code 0 (0x0).

解决方案与说明

一、阻止应用关闭的实现方式

MAUI没有跨平台的OnClosing拦截机制,需针对Windows和Android分别做平台特定处理:

Windows平台

通过挂钩Win32的WM_CLOSE消息拦截窗口关闭:

  1. 获取窗口句柄;
  2. 重写窗口过程(WndProc)拦截WM_CLOSE;
  3. 根据业务逻辑决定是否取消关闭,比如弹出确认对话框,用户选择取消则终止关闭流程。

示例代码(Windows平台项目中实现):

// Platforms/Windows/App.xaml.cs
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
    base.OnLaunched(args);
    var window = Application.Current.Windows[0].Handler.PlatformView as Microsoft.UI.Xaml.Window;
    IntPtr hwnd = WinRT.Interop.WindowNative.GetWindowHandle(window);
    SetWindowLongPtr(hwnd, GWLP_WNDPROC, new IntPtr(WndProcDelegate));
}

private delegate IntPtr WndProcDelegate(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam);
private static WndProcDelegate WndProcDelegate = WndProc;

private static IntPtr WndProc(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam)
{
    if (msg == WM_CLOSE)
    {
        var dialog = new Microsoft.UI.Xaml.Controls.ContentDialog
        {
            Title = "确认关闭?",
            Content = "当前有任务正在运行,确定要关闭吗?",
            PrimaryButtonText = "确定",
            SecondaryButtonText = "取消"
        };
        var result = dialog.ShowAsync().GetAwaiter().GetResult();
        if (result == Microsoft.UI.Xaml.Controls.ContentDialogResult.Secondary)
        {
            // 取消关闭操作
            return IntPtr.Zero;
        }
    }
    return User32.CallWindowProc(IntPtr.Zero, hwnd, msg, wParam, lParam);
}

// Win32 API声明
[DllImport("user32.dll")]
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 const uint WM_CLOSE = 0x0010;

Android平台

Android无法完全阻止用户强制关闭,但可做部分拦截:

  1. 重写Activity的OnBackPressed方法,拦截返回键触发的关闭;
  2. 监听ACTION_CLOSE_SYSTEM_DIALOGS广播,处理最近任务列表的关闭操作(无法阻止系统强制终止);
  3. 若需后台持续运行,申请FOREGROUND_SERVICE权限,将应用转为前台服务。

二、后台运行与通知推送

MAUI需通过平台特定服务实现后台运行,完成计算后推送通知:

Windows平台

创建Windows后台任务(Background Task),将计算逻辑移至后台任务执行,完成后通过ToastNotificationManager发送通知。

Android平台

创建前台服务(Foreground Service),在服务中执行计算任务(前台服务需显示持续通知避免被系统杀死),完成后通过NotificationManager推送通知。

跨平台层面可通过MAUI的DependencyService统一调用各平台实现,保持业务逻辑一致。

三、生命周期触发顺序异常说明

你遇到的OnDestroying先于OnStopped触发的问题,可能是调试环境的特殊情况或平台差异导致。建议在Release模式下测试,并分别验证Windows和Android平台的生命周期事件顺序——MAUI的生命周期事件在不同平台上的映射存在细微差异。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 07:24:12