非打包WinUI3应用重写默认引导程序及指定WinAppSDK版本适配的技术咨询
非打包WinUI3应用重写默认引导程序及指定WinAppSDK版本适配的技术咨询
这个问题我之前做非打包WinUI3项目的时候也踩过坑,默认引导程序直接跳最新版本确实坑人——用户装了1.7却跑不了1.6的应用,体验极差。下面给你两种解决思路,按需选就行:
一、简单方案:修改默认MddBootstrapAutoInitializer的参数
如果你的需求只是让引导程序只匹配1.6.x版本,暂时不需要自定义错误提示,那直接修改自动生成的MddBootstrapAutoInitializer构造参数就可以,不用写太多自定义代码。
默认模板生成的代码大概在App.xaml.cs里,是这样的:
private Microsoft.Windows.ApplicationModel.DynamicDependency.MddBootstrapAutoInitializer _mddBootstrapAutoInitializer = new Microsoft.Windows.ApplicationModel.DynamicDependency.MddBootstrapAutoInitializer(0);
你把它改成指定版本的重载构造:
private readonly MddBootstrapAutoInitializer _mddBootstrapAutoInitializer = new( majorMinorVersion: "1.6", versionTag: string.Empty, packageFamilyName: "Microsoft.WindowsAppRuntime.1.6" );
不过要注意:这个方案下,当初始化失败时,系统默认的错误弹窗可能还是会引导用户去下载最新版本的WinAppSDK。如果你要完全控制提示内容和下载指引,就得用下面的自定义方案。
二、自定义引导逻辑(推荐,完全掌控版本检查)
这个方案能让你完全控制版本检查的结果,显示自己的错误提示,彻底避免用户被引导到不兼容的版本。
步骤1:移除自动生成的AutoInitializer
先打开App.xaml.cs,找到自动生成的MddBootstrapAutoInitializer字段,把它删掉——因为我们要手动控制初始化流程,不需要自动的了。
步骤2:在应用启动最早期手动调用引导初始化
非打包WinUI3应用的启动入口一般是Program.cs的Main方法(如果模板没生成,你可以自己添加)。这里推荐在Program.cs里处理,因为这是应用启动的最早时机,能避免WinUI控件还没初始化就报错的问题。
示例代码如下:
using Microsoft.UI.Xaml; using Microsoft.Windows.ApplicationModel.DynamicDependency; using System; using System.Windows.Forms; namespace YourWinUI3AppNamespace { internal static class Program { [STAThread] static void Main(string[] args) { // 手动执行WinAppSDK引导初始化,指定1.6.x版本 var initResult = MddBootstrapInitialize( majorMinorVersion: "1.6", versionTag: string.Empty, // 正式版留空,预览版可填"preview"等标识 packageFamilyName: "Microsoft.WindowsAppRuntime.1.6", options: MddBootstrapInitializeOptions.None ); // 处理初始化失败的情况 if (initResult != MddBootstrapInitializeResult.Success) { string errorMsg = initResult switch { MddBootstrapInitializeResult.ErrorPackageNotFound or MddBootstrapInitializeResult.ErrorPackageVersionNotFound => "本应用需要安装WinAppSDK 1.6.x版本的运行环境,请下载对应版本后重试。", MddBootstrapInitializeResult.ErrorPackageInvalid => "已安装的WinAppSDK版本损坏,请重新安装1.6.x版本。", _ => $"应用初始化失败,错误代码:{initResult}" }; // 用Win32的MessageBox显示提示,避免WinUI未初始化的问题 MessageBox.Show(errorMsg, "启动失败", MessageBoxButtons.OK, MessageBoxIcon.Error); Environment.Exit(1); } // 初始化WinUI应用 Application.Start((p) => new App()); // 应用退出时清理引导资源 MddBootstrapShutdown(); } } }
步骤3:别忘了退出时的资源清理
上面代码里的MddBootstrapShutdown()会在应用退出时释放动态依赖的资源,这个步骤不能省,否则可能会出现资源泄漏的问题。
关键注意事项
- 版本参数格式要对:
majorMinorVersion必须是主版本.副版本的格式(比如"1.6"),不能写完整的补丁版本号(比如"1.6.22310.1"),这样才能匹配该主副版本下的所有补丁版本(1.6.0、1.6.1等)。 - 包族名要对应版本:不同版本的WinAppSDK包族名是固定的,正式版1.6的包族名是
Microsoft.WindowsAppRuntime.1.6,如果是预览版,包族名可能会带有"Preview"后缀,需要对应调整。 - 错误提示的兼容性:如果想用WinUI的对话框显示提示,要确保调用对话框前WinUI已经初始化完成,但引导失败时WinUI还没启动,所以用Win32的
MessageBox是更稳妥的选择,或者你也可以先初始化一个极简的WinUI窗口来展示提示。
内容来源于stack exchange
相关产品推荐
相关产品推荐

