上个月一个做设备厂的老朋友找我,他那套医疗设备上位机还是十年前的 WinForms,客户催着改版,他犹豫是要一步跳到微软最新的界面框架还是干脆转 Linux。这问题不是他一个人纠结。这两年我帮几个团队做过嵌入式人机界面的技术选型,发现大家对“微软到底用什么做嵌入式界面”这件事普遍很模糊:有人以为 WinForms 还能再战十年,有人跟风试了 WPF 半途而废,还有人以为微软嵌入式只剩 Linux 一条路。
这篇文章想把微软当前嵌入式界面开发这条技术线完整捋一遍:系统层用什么、界面层用什么、工具链是什么、硬件交互怎么做、部署和量产有哪些坑,以及在什么场景下你根本不该选微软。先给结论:微软在嵌入式界面上的主推组合是 Windows 11 IoT Enterprise + WinUI 3(基于 Windows App SDK)+ Visual Studio,配合 .NET 的 NativeAOT 和 MSIX 打包。这组合不是给 8 美元单片机的 HMI 准备的,它服务的是工业平板、工控机、医疗设备里的触摸屏电脑这类“有 Windows 底层能力”的嵌入式设备。
1. 微软嵌入式界面开发的技术地图:系统、框架、工具三条线
真正的嵌入式界面开发在微软生态里,从来不是单一技术,而是三条线叠出来的。第一层是系统,负责在设备上提供运行时环境;第二层是界面框架,决定了你用什么 API 写界面;第三层是工具链,决定你开发、调试、部署的体验。这三条线的现状分别是什么?我把每一层单独拆开讲。
1.1 系统层:Windows 11 IoT Enterprise 才是主角
这几年很多嵌入式工程师听到“微软嵌入式”第一反应是 Windows 10 IoT Core,那个轻量版系统跑在树莓派和若干 SBC 上,当年确实火过一阵。但微软在嵌入式产品线上做了很大的策略调整,现在真正的承载体是 Windows 11 IoT Enterprise。这个系统不是一个新的轻量内核,而是完整的 Windows 企业版,为专用设备做了定制和授权优化。这是很关键的一个认知:微软现在默认你跑的嵌入式设备,底层是一个能做完整桌面应用的 Windows,上面那一层 UI 你完全可以换成工业 HMI。
Windows 11 IoT Enterprise 有几个对界面开发特别重要的特性。首先是 LTSC 长期服务通道,提供长达 10 年的安全更新,这对医疗、工控这类不能频繁动系统的场景诱惑力非常大。其次是 Shell Launcher 外壳锁定,开机直接进你的 HMI,不出现桌面和任务栏。再就是 Assigned Access 单一应用限制,设备只能运行指定应用。这些能力在普通 Windows 上没有,或者要改注册表、写一堆脚本才能勉强接近,但 IoT Enterprise 把它们做成了系统级功能。所以如果你看到的硬件是一台工控板卡配一块触摸屏,系统是定制的 Windows,大概率就是这类产品形态。
1.2 界面层:WinUI 3 与 Windows App SDK
系统之上,界面框架是开发者最先关心的。微软当前主推的方案是 WinUI 3 和整套 Windows App SDK。WinUI 3 简单说就是 Fluent Design 风格的原生 Windows 界面框架,基于 XAML 语言,代码和 UI 分离,可以跑 C#(.NET)也可以跑 C++。Windows App SDK 则是承载 WinUI 3 的运行时和工具包,它把过去 UWP 里那些控件、渲染管线、部署机制抽出来,让开发者可以脱离应用商店,像传统 Win32 程序一样自由地打包、安装、分发。
对嵌入式工程师来说,WinUI 3 最大的价值是“现代界面 + 原生性能 + 老式分发自由”这三件事兼得。过去很多人不敢用 UWP,因为要上商店、包格式封闭、签名验证麻烦。现在 Windows App SDK 支持自包含部署,应用把运行库直接打包进安装目录,目标机器不需要预装任何额外运行时,这对封闭的嵌入式设备非常友好。WinUI 3 的界面渲染走的是 DirectX 合成管线,性能上远优于 WinForms 的 GDI 绘制,也比 WPF 在低功耗平台上更流畅。后面第二章我会专门讲性能实测。
1.3 工具链:Visual Studio 依然是核心
工具链是很多人忽略但实际影响开发效率的一环。微软这套方案你绕不开 Visual Studio,装的时候记得勾选“通用 Windows 平台开发”和“.NET 桌面开发”两个工作负载。VS 里的 XAML 设计器可以实时预览界面,虽然我对这种设计器一直持保留态度,复杂界面它经常渲染不准,但用来调布局、查属性还是很有用。
调试方面,WinUI 3 项目支持直接 F5 部署到本地运行,也可以用远程调试器部署到目标工控机,局域网内配合固定 IP 使用,体验和本机调试基本一致。比较坑的一点是,首次创建 WinUI 3 项目时 NuGet 包还原会比较慢,建议提前把 NuGet 镜像源配好,或者搭建本地缓存,否则团队里每个人的开发机上建项目都要卡十几分钟。我见过一个团队因为这个把项目初始化时间从“午休前”拖到“第二天上班”,排查下来就是网络源不稳定,换了镜像后问题立刻消失。
2. WinUI 3 凭什么接棒嵌入式界面开发:架构真相与性能数据
这一层我要从架构上解释清楚为什么 WinUI 3 能接棒,以及它在嵌入式设备上实际表现如何。这部分内容看懂了,你就能判断它到底适不适合自己的项目。
2.1 XAML 渲染管线的底层逻辑
WinUI 3 界面的呈现机制和传统 Win32/GDI 程序完全不同。WinForms 每画一个控件基本都是交给 GDI 画点画线,窗口一多、刷新一频繁就卡;WPF 引入了保留模式渲染,DependencyProperty 和 Visual Tree 概念让界面维护更方便,但它在老设备上吃了很多年性能亏。WinUI 3 在 XAML 基础上把合成阶段放到了 DirectComposition 层,控件树变化后系统会增量更新合成图块,而不是整帧重绘。体现在嵌入式低功耗设备上,就是打开页面、滚动列表、切换动画这些高频操作,CPU 占用比 WPF 平稳许多。
不过要说清楚,WinUI 3 不是全场景性能冠军。它启动比 WinForms 慢,因为 XAML 解析和 Composition 初始化本身有成本;初始化一个复杂页面如果过度依赖值转换器和绑定级联,在低配 CPU 上也可能出现明显卡顿。我的经验是,嵌入式设备上不该追求炫酷动画,应该把动画量降到最低,用普通硬件换稳定帧率。客户看到的永远应该是稳定、不闪烁的数据面板,而不是界面框架自己有多炫。
2.2 WinUI 3 vs WPF vs WinForms:嵌入式场景的实测对比
很多团队纠结要不要从老框架迁移。我做过一个粗糙的基准测试:在 Intel 赛扬 J1900、4GB 内存、分辨率 1280x800 的工控机上,同样的仪表盘页面,WinForms 渲染一个 60 个控件的监控面板,拖动和刷新基本没压力,但一旦涉及自适应布局和多个图表实时刷新,GDI 的刷新率明显下滑;WPF 在同样条件下首次加载大约 1.2 秒到 2 秒;WinUI 3 首次加载大约 1.5 秒到 2.5 秒,但是滚动画布、更新实时数据时 CPU 曲线更平稳,不会像 WPF 那样出现残影。
换句话说,如果只是十几个按钮、几个文本框的简单界面,WinForms 依然够用,没必要迁;如果你要做的是数据密集型、图表多、视觉要求高的现代 HMI,WinUI 3 才是值得投入的方向。这里还要提一个容易被忽略的点:WinUI 3 控件库的视觉风格是 Fluent,屏幕密度、字体渲染、触摸热区这些特性天然为现代触屏优化,而不是十年前那种鼠标优先的桌面观感。对于要面向客户展示的设备,这个差别其实很影响观感,甚至影响客户对你产品专业度的判断。
2.3 自包含部署和 NativeAOT:给嵌入式场景的两剂强心针
部署环节是嵌入式项目的老大难。传统 WPF 程序在目标机上一堆依赖,.NET Framework 版本不对就起不来。Windows App SDK 支持自包含发布,把 WinUI 运行时和 .NET 运行时都塞进应用目录,目标设备只需要有 Windows 系统本身。另一个新工具是 .NET 的 NativeAOT,可以把程序直接编译成原生二进制,没有 JIT 预热、内存占用更小、启动更快。我在设备上试过 NativeAOT 和普通 JIT 模式,启动时间能省 30% 左右,冷启动大概从 2 秒降到 1.3 秒。
代价是 NativeAOT 对反射、动态代码生成的限制比较多,一些依赖库会不兼容,比如某些依赖 JSON 反射的组件,需要提前加RuntimeTypeModel配置或者换编译时生成方案。我建议在项目早期就做一次 NativeAOT 技术验证,别等到开发后期再切,否则你会面临“所有功能都正常,就是发布出来跑不了”的尴尬局面。
提示:NativeAOT 和 WinUI 3 的组合在部分场景下依然有兼容性问题,生产环境我建议先做技术验证,不要直接在核心项目上全量切换。至少留一条 JIT 发布的退路。
3. 动手搭一个工业触摸屏 HMI:从创建工程到多屏适配
聊完理论,进入实操。这里我把一条完整的、可以直接照着做的路线写出来,目标是搭一个能够在工业平板上运行的 HMI 工程。这套流程我没有用任何小众工具,全部是微软官方链路,方便你后面自己维护。
3.1 环境准备与工程创建
开发机上需要安装 Visual Studio 2022 或更新版本,工作负载至少包含“通用 Windows 平台开发”和“.NET 桌面开发”,Windows SDK 版本选择 10.0.22621 以上。目标机建议预先装好 Windows 11 IoT Enterprise LTSC,开启开发者模式(设置 -> 隐私和安全性 -> 开发者选项),把局域网 IP 固定下来,方便远程调试。
创建项目时选Blank App, Packaged (WinUI 3 in Desktop)模板,注意不是 UWP 项目。两个模板在项目结构上很相近,但部署模型完全不同,选错了后面会卡在包权限问题上。项目创建之后,我建议先把解决方案配置从 Debug 切到 x64——嵌入式设备绝大多数是 x64 工控机,默认的 AnyCPU 在某些情况下会引发本机库加载兼容问题,浪费时间。
3.2 工程结构和 MVVM 拆分
WinUI 3 项目天然就是 MVVM 友好的工程结构。我会把代码分成三块:Views放页面 XAML,ViewModels放界面状态和行为,Services放硬件通信、日志、配置等业务服务。嵌入式 HMI 一般没有特别复杂的导航,用 Frame + NavigationView 就够了,不用上 Prism 那套重框架。如果你是在给触屏设备做单页面的设备控制面板,甚至可以只有一个 MainWindow,再加几个 UserControl 做区域拆分。
依赖注入建议直接用 Microsoft.Extensions.DependencyInjection,不需要引入独立的第三方容器。在 App.xaml.cs 里注册服务,在窗口构造函数里解析 ViewModel。数据绑定方面,要实现INotifyPropertyChanged;社区里好用的CommunityToolkit.Mvvm包可以在编译期生成绑定代码,减少手写样板量。我用过之后强烈建议嵌入式项目用这个,代码量减少不说,绑定错误也少了。注意这个包和 WinUI 3 的绑定模型没有冲突,可以放心用。
3.3 触控大屏的布局与交互适配
嵌入式 HMI 最大的交互特点是“用户手指粗、环境光线亮、屏幕未必标准”。所以布局上有几点经验:
- 最小触摸热区做到 48x48 逻辑像素,重要按钮要做到 64px 以上,不要迷信设计稿上的精致小按钮,现场工人戴着手套操作会让你崩溃。
- 避免白色高亮背景,工业现场户外强光下白色界面容易看不清,用深色主题 + 高对比度前景色反而耐看。
- 多语言文本要考虑翻译后的长度变化,给文本块设置自动换行和留白,不要写死宽度。德文和中文的界面宽度差异能差出 40%。
- 字体用微软雅黑系列,字号不要小于 16px,工业平板上很多人是隔着一米看的,不是趴在屏幕上点的。
WinUI 3 对高 DPI 的处理是自动的,但你要注意在嵌入式设备上有时系统缩放没设置好,XAML 的布局和实际像素对不上,界面元素会被裁掉。我建议在目标机上把显示缩放固定为 100% 或 150%,并关闭 Windows 的自动缩放建议,不要依赖系统去猜你的屏幕。
3.4 多屏与异形屏:WinUI 3 能处理到什么程度
工业设备经常有双屏需求:一块触摸屏人机交互,一块屏显示状态或者工艺参数。WinUI 3 目前对多窗口的支持是有的,AppWindow配合Window类可以创建多个窗口,但和 WPF 比还是有限制,尤其是在某个窗口关闭后对其他窗口的生命周期管理要自己处理。
我的建议是:如果双屏内容差异不大,用同一个 Window 里的两个区域分别绑定数据源,用DisplayArea的 API 去获取两个显示器的边界,手动定位窗口,简单又稳。如果两块屏内容差异很大,那就老老实实开两个窗口,配合系统 Display 设置,在启动时把两个窗口分别移动到对应的显示器上。这套方案我在 IoT Enterprise 上实测过,稳定可靠。异形屏的话,WinUI 3 没有针对特殊形状屏幕的专门适配,你需要自己计算安全区域,把内容限制在屏幕的实际显示区域内,和 WPF 时代的手工处理方式差不多。
4. 界面和硬件之间的数据通道:串口、TCP 与实时性取舍
WinUI 3 解决的是“界面展示”问题,但对嵌入式设备来说,界面的灵魂在于数据。这一章讲清楚怎么把硬件数据接进来,怎么保证数据流动时界面不卡、不崩、不乱。
4.1 分层:永远不要让 UI 直接碰驱动
做嵌入式界面开发最容易犯的错误,是在 ViewModel 里直接 new 一个串口对象,然后在界面上处理断线重连、字节解析。这个架构在原型阶段很快,但项目到了中后期就是灾难。
正确做法是把硬件通信抽象成IHardwareService或IDeviceClient接口,UI 只依赖接口方法,具体的实现可以基于串口、TCP、Modbus、甚至模拟器。这样在没有真实硬件的时候,你可以用一个 Mock 服务跑通整个界面,这对调试和客户演示简直是救命能力。我见过一个医疗设备团队,整个开发周期前四个月都没有拿到最终样机,全靠 Mock 服务在界面上模拟各种报警和状态变化,最后硬件到位后两天就联调通了,这就是分层带来的回报。
4.2 串口与 TCP 的异步模型
嵌入式设备最常见的两种通信方式是串口和 TCP。在 WinUI 3 里,串口可以用System.IO.Ports.SerialPort,TCP 可以用TcpClient。这里的关键点在于:所有 I/O 操作都要走异步模式,用ReadAsync、WriteAsync,结果通过事件或回调再推到 UI 线程。
WinUI 3 的 DispatcherQueue 取代了老式 WPF 的 Dispatcher 概念,代码上差不多,但要注意本地窗口的DispatcherQueue.TryEnqueue不是永远可用,如果窗口还没创建好就去 post,容易空引用。我的习惯是把事件调度逻辑封装成一个UiThreadService,集中处理所有从后台线程回到 UI 线程的调用,避免到处散落 DispatcherQueue 代码。这个服务类大概 30 行,但能帮你省掉大量重复且容易写错的调度逻辑。
协议层是另一个容易翻车的地方。Modbus RTU 的 CRC 校验、TCP 的粘包分包处理,这些问题和用不用 WinUI 3 没有关系,但你可以借助库来减少工作量。NModbus这类社区库基本够用,工业现场如果走 OPC UA,C# 生态里也有官方客户端库可用,只是部署依赖稍重,在低配工控机上要评估内存占用。我一般建议通信协议本身不要过度封装,保持“收发字节 + 解析帧”的简单模型,复杂业务放到上层服务里。
4.3 UI 线程与实时数据的平衡
HMI 面板上最常见的是曲线、状态灯、参数数字。这些数据如果是定时轮询,频率一般在 50ms 到 500ms 之间。我推荐的做法是:后台线程轮询,把原始数据放进一个轻量缓冲区,UI 侧用DispatcherTimer或CompositionTarget.Rendering按固定节拍刷新界面,不要在每次硬件数据到达时立刻更新 UI。
这样做的好处是 UI 刷新频率稳定在 10 到 20 FPS 就已经很平滑,而且 CPU 占用不会像“来了一个数据刷新一次”那样忽高忽低。硬实时要求高的控制逻辑,本来也不应该放在界面程序里,应该由 PLC 或 MCU 完成,上位机只做显示和参数下发。这一点最好在项目启动时就跟客户拉扯清楚,否则后患无穷——客户会拿控制时序的抖动来质疑你的程序写得差,实际上那本来就不是界面程序该管的事。
4.4 一个串口采集界面的分层示例
简单给一个伪代码示意,不追求完整,重点是分层结构:
public interface IDeviceService { event EventHandler<DeviceDataEventArgs> DataReceived; Task<bool> ConnectAsync(string portName, int baudRate); void Disconnect(); Task SendCommandAsync(byte[] payload); } public class HmiViewModel : ObservableObject { private readonly IDeviceService _device; public HmiViewModel(IDeviceService device) { _device = device; _device.DataReceived += OnDeviceDataReceived; } private void OnDeviceDataReceived(object? sender, DeviceDataEventArgs e) { // 解析数据并更新属于界面状态的属性 UiThreadService.Post(() => { Temperature = e.Temperature; Pressure = e.Pressure; }); } }关键就一句话:硬件事件进来先解码,再通过统一调度切回 UI 线程,最后才更新绑定属性。这个顺序反了会出很多怪问题——直接在事件回调里改界面属性,轻则界面刷新明显掉帧,重则抛出跨线程访问异常直接闪退。而且这种问题带有随机性,客户现场跑三天才复现一次,排查起来非常痛苦。代码里宁可多写几行调度逻辑,也绝不要图省事走捷径。
5. 从开发机到产线:部署、启动与远程维护的完整套路
界面开发完成了,硬件通信也跑通了,接下来才是嵌入式交付最麻烦的部分:怎么让这台设备在现场稳定跑起来、怎么升级、怎么排查问题。这一章的内容很多是文档里看不到的,属于量产阶段反复踩坑攒下来的经验。
5.1 MSIX 打包与签名
WinUI 3 默认的打包格式是 MSIX,它自带安装包依赖管理、自动更新能力,但嵌入式现场常常没有网络、没有证书服务器。我一般建议用带签名的 MSIX 包,证书用自己的测试证书或公司内部证书,安装到设备时先将证书加入本机受信任列表。
如果设备数量大,可以写一个 PowerShell 脚本批量安装,或者用winget批量处理。没有签名的 MSIX 在部分环境下会被 SmartScreen 拦截,量产机上白白浪费时间。这点务必提前处理好,不要在客户现场第一次部署时才想起来测签名流程。
5.2 开机自启动与外壳锁定
嵌入式界面程序的启动方式是分级别的。最小改动方案是,把应用程序快捷方式放到系统的启动文件夹,再在 IoT Enterprise 上配置自动登录账户。这个方案的缺点是用户还是可能退到桌面,或者不小心把程序关掉。
更专业一点用 Shell Launcher,这是 IoT Enterprise 提供的功能,可以把系统外壳从explorer.exe换成你的 HMI 应用,开机直接启动你的程序,没有桌面、没有任务栏,普通用户根本退不出去,只能重启电源。Shell Launcher 的配置不复杂,官方文档有现成的 PowerShell 脚本,但要注意:配置之前必须创建标准账户并启用自动登录;如果应用崩溃退出,系统会停留在黑屏状态,所以你的应用里必须做全局异常捕获,并在 Main 入口设计自动重启逻辑。我见过一个方案,在 Main 里套了一个while(true)循环,程序退出就重新拉起进程,同时做最大重试次数限制,避免死循环刷日志。
5.3 远程日志与版本更新
设备卖出去之后,界面程序崩溃了怎么办?纯封装的设备要远程维护,日志系统和升级通道必须提前设计。我见过很多团队做嵌入式 Windows 程序时根本不写日志,出问题只能去现场,一个项目拖几个月。
建议至少用Microsoft.Extensions.Logging加文件输出,滚动保留最近 7 天;进阶可以接云端日志平台,但很多嵌入式设备现场网络受限,文件日志 + 定期回收是底线。日志里至少要包含:启动/退出事件、硬件连接状态、协议解析错误、UI 页面切换。不要什么都打,否则日志文件膨胀得很快,反而掩盖了真正有用的信息。
版本升级方面,如果设备有外网权限,可以用 MSIX 的自动更新;如果设备在隔离内网,我建议做一个简单的升级服务:应用启动时检查本地固定目录的更新包,从 U 盘或者内网管理系统拷贝文件下来,校验哈希后解压、替换、重启。这个过程听起来不够“高级”,但在实际工业项目里是最稳的,网络不稳定时不会把设备搞成砖。
5.4 我在量产阶段踩过的几个坑
有一件事我记忆很深:某批次工控机显卡驱动版本不一样,WinUI 3 在部分机器上启动时合成器初始化失败,界面黑屏。查了很久才发现是 DirectX 驱动兼容性问题,最后方案是升级目标机器的显卡驱动,并在应用启动前做一次 GPU 能力检测,不行就强制软件渲染兜底。所以强烈建议在你的部署清单里加一条“检查显卡驱动版本”。
另一个坑是系统更新。IoT Enterprise LTSC 虽然更新少,但偶尔也会推送。设备厂家如果不想被半夜自动更新重启打断生产,一定要设置 Active Hours 或者用组策略禁用自动重启。这个不做,客户半夜打电话骂的都是你。
还有一个小坑,容易被忽略:WinUI 3 应用在无网络环境下首次启动时,如果Microsoft.WindowsAppSDK的某些组件尝试检查更新,可能出现数秒延迟。解决方法是提前在部署机上禁用该组件的更新检查,或者用自包含部署把所有依赖钉死在应用目录里。
6. 什么时候别选微软:选型对比与我的建议
最后聊一个更难听但更重要的问题:什么时候你根本不应该选微软这套方案。
6.1 一个对比表:微软方案 vs 开源方案
我把几种常见技术栈做了一个横向对比,参数是从实际项目里总结的,不具备严格基准意义,但方向可以参考:
| 维度 | WinUI 3 + IoT Enterprise | Linux + Qt (QML) | Linux + Electron / Web | WinForms 遗留 |
|---|---|---|---|---|
| 启动速度 | 中(首次加载较慢) | 快 | 较慢 | 最快 |
| 界面现代感 | 高(Fluent) | 高(可高度定制) | 高(Web 技术) | 低 |
| 硬件能力封装 | 强,Windows 驱动生态全 | 中,驱动适配看厂商 | 中,串口等需要中间层 | 强 |
| 设备成本 | 高,要 Windows 授权 | 中,硬件需评估 | 中 | 高 |
| 部署复杂度 | 中,MSIX 写脚本较麻烦 | 中,交叉编译较麻烦 | 低,打包相对简单 | 低 |
| 长期维护 | 10 年 LTSC 支持 | 依赖社区和自建能力 | 依赖社区和自建能力 | 只能自己扛 |
| 适合场景 | 医疗/工业平板/面板 PC | 网关/嵌入式盒子/专用设备 | 带屏幕的 IoT 设备 | 简单老系统/不打算升级 |
我发现一个规律:客户预算充足、设备尺寸在 7 寸以上、现场要 Windows 驱动生态(接打印机、扫码枪、数据库),基本就是微软方案的天下;反之,如果是一个小盒子跑网关、成本敏感、Linux 驱动社区成熟,Qt 或 Web 技术栈才是公道选择。
6.2 我给出的选型清单
我一般会问四个问题:
- 你的设备要不要跑外设驱动?比如打印机、扫码枪、读卡器、指纹仪,这类 Windows 的驱动生态是最全的。
- 你的 UI 复杂度是“状态按钮 + 数据表”还是“动态图表 + 大量交互”?前者 WinForms 或简单框架即可,后者才值得上 WinUI 3。
- 客户承诺的软件生命周期是几年?如果超过 5 年且不允许频繁变更,IoT Enterprise LTSC 的 10 年支持是巨大优势。
- 团队熟悉什么技术栈?C# 团队转 WinUI 3 的学习曲线比 C++ 团队转 Qt 短很多,这一点往往比技术本身更影响项目成败。
这四个问题走下来,基本结论就清楚了。需要说明的是,WinUI 3 还在持续迭代,版本变化有时比较大,从 Windows App SDK 老版本升过来偶发破坏性变更。建议固定 SDK 版本,并在项目中期不要频繁升级,把版本升级当成独立任务排期处理,不要顺手就点“更新 NuGet 包”。
6.3 一点个人体会
换个角度说,微软这套“最新嵌入式界面开发技术”的本质,其实不是做出某个跨时代的新东西,而是把 Windows 系统的成熟生态、现代界面框架的开发效率和嵌入式设备的交付约束这三个本来看起来矛盾的事情,用 Windows App SDK、IoT Enterprise 和工具链叠成了一种可行的组合。它不适合所有人,但如果你做的是面向专业场景的带屏设备,现在确实到了值得认真评估的时间点。我自己在接下来的新项目里,也会把 WinUI 3 作为首选方案去验证,但一定会先跑通 NativeAOT 和硬件驱动这两个最容易翻车的环节再做决定。