WinUI 3 (以下简称 WinUI)框架发布后的二进制文件过大的问题存在了很长时间,我在这篇文章中有过详细的讨论,好在 Windows App SDK v1.2 就已经支持剪裁发布,但是我却一直没有成功实现,直到最近才发现了问题所在。

坑在哪

在 WinUI 上使用云母或亚克力材质的时候,一般会照抄微软文档中提供的方法。问题就出在这,这一页最后更新于 2022-09-24,那时 WinUI 还不支持剪裁,文档中的方法自然不会有问题。

// 仅包含关键代码
class WindowsSystemDispatcherQueueHelper
{
// ... object m_dispatcherQueueController = null; [DllImport("CoreMessaging.dll")]
private static extern int CreateDispatcherQueueController([In] DispatcherQueueOptions options, [In, Out, MarshalAs(UnmanagedType.IUnknown)] ref object dispatcherQueueController); // 此方法在设置云母或亚克力前调用
public void EnsureWindowsSystemDispatcherQueueController()
{
// ... if (m_dispatcherQueueController == null)
{
DispatcherQueueOptions options;
// ...
CreateDispatcherQueueController(options, ref m_dispatcherQueueController);
}
}
}

在这里通过 P/Invoke 调用了一个外部 COM 函数,而开启剪裁后,编译器会警告:Trim analysis warning IL2050: P/invoke method 'WindowsSystemDispatcherQueueHelper.CreateDispatcherQueueController' declares a parameter with COM marshalling. Correctness of COM interop cannot be guaranteed after trimming. Interfaces and interface members might be removed. 剪裁后无法保证 COM 互操作的正确性,可能会删除接口和接口成员。事实证明剪裁后确实出错了。

查看函数 CreateDispatcherQueueController 的定义,第二个参数返回的是一个指针,同时我们也不关心 COM 对象内容的细节,那解决方法就很简单,使用 IntPtr 替换 object 即可。

HRESULT CreateDispatcherQueueController(
[in] DispatcherQueueOptions options,
[out] PDISPATCHERQUEUECONTROLLER *dispatcherQueueController
);

修改后的代码如下:

class WindowsSystemDispatcherQueueHelper
{
// 改为 nint
nint m_dispatcherQueueController; [DllImport("CoreMessaging.dll")]
// 删除互操作相关的特性
private static extern int CreateDispatcherQueueController(in DispatcherQueueOptions options, out nint dispatcherQueueController); public void EnsureWindowsSystemDispatcherQueueController()
{
if (m_dispatcherQueueController == 0)
{
DispatcherQueueOptions options; _ = CreateDispatcherQueueController(options, out m_dispatcherQueueController);
}
}
}

在最新的 Windows App SDK v1.3 实验版 1 中引入了新的 API,大大简化了设置背景材质的流程,并且这个新 API 不存在上述问题。

发布设置

WinUI 支持了剪裁,这为我们发布小体积应用创造了条件,不过这里的坑也很多。

需要注意的是,.NET 7 修改了剪裁粒度的默认值,默认剪裁全部程序集,所以发布时一定要把 TrimMode 设置为 partial。这是一个比较粗糙的解决办法,可能有更优的方案,但是我没有深入研究。

WinUI 运行依赖 Windows App Runtime,这个组件没有内置在系统中,并且更新还很频繁。当发布为 Msix 包时,无论是否上架微软商店,安装应用的过程中商店服务都会自动下载并安装 Runtime(可能会因为网络问题安装失败)。但是不上架商店的 Msix 包安装起来就很麻烦,发布为非打包的二进制程序更为合适。

发布为非打包的二进制程序时,可以选择是否包含 Windows App Runtime,如果不包含并且按照以下设置发布:

<!--  不打包  -->
<WindowsPackageType>None</WindowsPackageType>
<!-- 启用剪裁 -->
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>partial</TrimMode>
<!-- 自包含 .NET 运行时 -->
<SelfContained>true</SelfContained>
<!-- 单文件 -->
<PublishSingleFile>true</PublishSingleFile>
<!-- 关闭 ReadyToRun -->
<PublishReadyToRun>false</PublishReadyToRun>
<!-- 不包含 Windows App Runtime -->
<WindowsAppSDKSelfContained>false</WindowsAppSDKSelfContained>
<!-- 压缩发布的文件 -->
<EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>
<!-- 单文件包含原生库 -->
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>

空模板项目最终生成三个文件,“小而美”,但是运行后会弹窗提醒下载安装 Windows App Runtime,在这个网页中没有引导真的很难找到正确的下载链接。

如果选择发布时包含 Windows App Runtime,就不能在发布的单文件中包含原生库,否则会出现无法打开的情况,相关讨论参考 issue。结果就是发布后的文件很繁杂,整个 Runtime 都在发布文件夹中,并且还存在着非常多的语言相关文件夹。经过我的测试只需要保留 en-usMicrosoft.UI.Xaml 这两个文件夹,删除其他文件夹不影响使用。这样一个空模板项目的大小最终是 58 MB。

总结

没有总结。

最新文章

  1. tyvj1468 清理垃圾
  2. EntityFramework之Log(五)
  3. 用Python遍历目录
  4. Linux rsync实现断点续传
  5. Autolayout学习(1)-了解Autoreszing
  6. Android_bug之Default Activity not found
  7. [DNX]解决dnu restore时找不到Newtonsoft.Json的问题
  8. H264(NAL简介与I帧判断)
  9. 运用预加载提升H5移动页面的用户体验
  10. Hbase 学习笔记(一) Hbase的物理模型 Hbase为每个值维护了一个多级索引,即&lt;key, column family, column name, timestamp&gt;
  11. java interface
  12. 07-Vue的基础使用
  13. 【Linux基础】iconv命令详解(编码转换)
  14. e lisp 自定义函数
  15. H5 32-百度首页
  16. Sorting(好题)
  17. 650. 2 Keys Keyboard
  18. Linux系统中的vi/vim指令【详解】
  19. Eclipse插件开发_异常_01_java.lang.RuntimeException: No application id has been found.
  20. 290. Word Pattern 单词匹配模式

热门文章

  1. Ubuntu20.04创建快捷方式(CLion)
  2. BFS算法套路框架
  3. java抽象类的定义和使用
  4. &lt;七&gt;lambda表达式实现原理
  5. 回溯法求解n皇后问题(复习)
  6. windows GO语言环境配置
  7. DFS深度优先搜索例题分析
  8. BBS项目(二): 登录功能 首页导航条搭建 首页主体部分 个人站点页面搭建 文章分类与标签 日期归档
  9. [seaborn] seaborn学习笔记5-小提琴图VIOLINPLOT
  10. ArcGIS工具 - 批量删除空图层