Xamarin.Forms UWP开机自启崩溃求助:OnActivated初始化时闪退
解决UWP应用开机启动(OnActivated)崩溃的问题
你遇到的核心问题其实是两个关键错误叠加导致的:错误的类型强制转换和async void异步方法的异常无法捕获,这直接触发了开机启动时的崩溃。咱们一步步拆解修复:
1. 先解决OnActivated里的类型转换错误
当系统通过StartupTask启动应用时,传入OnActivated的参数是StartupTaskActivatedEventArgs,而不是你强制转换的LaunchActivatedEventArgs——这个类型转换失败就是崩溃的直接导火索。
先修改OnActivated方法,正确判断激活类型:
protected override async void OnActivated(IActivatedEventArgs e) { base.OnActivated(e); // 区分激活类型,针对性处理 if (e.Kind == ActivationKind.StartupTask) { // 处理开机启动的激活逻辑 await InitializeAppForActivation(e); } else if (e is LaunchActivatedEventArgs launchArgs) { // 兼容手动启动等其他Launch类型激活 await InitializeApp(launchArgs); } }
2. 把async void改成async Task,避免异常逃逸
async void方法的异常无法被上层代码捕获,会直接导致应用崩溃。我们需要重构初始化方法,改用async Task来封装逻辑,同时添加异常捕获便于排查:
// 处理手动启动的初始化(保留原逻辑,改为async Task) async Task InitializeApp(LaunchActivatedEventArgs e) { try { Frame rootFrame = Window.Current.Content as Frame; if (rootFrame == null) { rootFrame = new Frame(); rootFrame.NavigationFailed += OnNavigationFailed; var assembliesToInclude = new List<Assembly>() { typeof(CachedImage).GetTypeInfo().Assembly, typeof(CachedImageRenderer).GetTypeInfo().Assembly }; Xamarin.Forms.Forms.Init(e, assembliesToInclude); Window.Current.Content = rootFrame; } if (rootFrame.Content == null) { rootFrame.Navigate(typeof(MainPage), e.Arguments); } Window.Current.Activate(); if (session == null) { session = new ExtendedExecutionSession(); session.Reason = ExtendedExecutionReason.Unspecified; session.Revoked += (s, a) => { }; var result = await session.RequestExtensionAsync(); if (result == ExtendedExecutionResult.Denied) System.Diagnostics.Debug.WriteLine("EXTENDED EXECUTION DENIED"); } } catch (Exception ex) { // 记录异常日志,方便排查 System.Diagnostics.Debug.WriteLine($"手动启动初始化失败: {ex.Message}\n{ex.StackTrace}"); throw; } } // 新增开机启动专用的初始化方法 async Task InitializeAppForActivation(IActivatedEventArgs e) { try { Frame rootFrame = Window.Current.Content as Frame; if (rootFrame == null) { rootFrame = new Frame(); rootFrame.NavigationFailed += OnNavigationFailed; var assembliesToInclude = new List<Assembly>() { typeof(CachedImage).GetTypeInfo().Assembly, typeof(CachedImageRenderer).GetTypeInfo().Assembly }; // 非Launch类型激活时,Forms.Init第一个参数传null即可 Xamarin.Forms.Forms.Init(null, assembliesToInclude); Window.Current.Content = rootFrame; } if (rootFrame.Content == null) { // 开机启动无启动参数,传空字符串 rootFrame.Navigate(typeof(MainPage), string.Empty); } Window.Current.Activate(); if (session == null) { session = new ExtendedExecutionSession(); session.Reason = ExtendedExecutionReason.Unspecified; session.Revoked += (s, a) => { }; var result = await session.RequestExtensionAsync(); if (result == ExtendedExecutionResult.Denied) System.Diagnostics.Debug.WriteLine("EXTENDED EXECUTION DENIED"); } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"开机启动初始化失败: {ex.Message}\n{ex.StackTrace}"); throw; } }
3. 额外排查小技巧
- 打开Visual Studio的异常设置(Debug -> Windows -> Exception Settings),勾选「Common Language Runtime Exceptions」,调试时能直接捕获到具体异常信息,快速定位问题。
- 确认
CachedImage相关程序集在开机启动时能正常加载——有时候开机启动的应用加载上下文和手动启动略有差异,必要时可以在初始化前提前加载这些程序集。
这样修改后,类型转换错误被避免,异步方法的异常也能被捕获排查,应该就能解决开机启动崩溃的问题了。
内容的提问来源于stack exchange,提问作者sme
相关产品推荐
相关产品推荐

