Windows 的修炼之道
小哲的公司后端和 Android 都有了——老板又要做 Windows 桌面端:给运营的效率工具、给客户的桌面客户端。小哲没写过桌面应用,周师傅说:Windows 是个「四十年的江湖」,技术栈从 C 的 Win32 一路进化到 C# 的 WinUI 3,选对栈、懂消息循环、会打包签名,才算入门。这一本,从系统架构讲到上架分发。
桌面端的江湖
Windows 开发全景:系统 + 语言 + UI + 分发师傅!老板要我们做 Windows 桌面端——运营效率工具 + 给客户的桌面客户端。我写过 Web 和 Android,桌面端要从哪学起?听同事说什么 Win32、WPF、WinUI……好乱!
乱就对了——Windows 有 40 年历史,技术栈「层层叠叠」:老的还在用、新的不断出。先给你一张「地图」,再带你逐层点亮:
- 系统层:Win32 API、消息循环——Windows 一切的地基(懂它,什么都懂了)。
- 语言层:C# + .NET——现代 Windows 开发的绝对主力。
- UI 层:WPF(经典王者)→ WinUI 3(新方向)→ .NET MAUI(跨平台)。
- 工程层:Visual Studio、打包、签名、分发——桌面开发的规矩。
来,十站路线——
记住一句话:Windows 开发 = 懂系统(消息循环/句柄)+ 选对栈(场景匹配)+ C# 打底 + 会打包签名。走,第一站,先把「地基」挖开。
平台架构:系统怎么组织
NT 内核 · Win32 API · 消息循环 · 句柄 · 进程线程Web 和 Android 都有「平台底层」——Windows 的底层是 Win32 API + 消息循环。理解它,你就理解了「为什么 Windows 程序长这样」。
Windows 平台四层:
- NT 内核:地基——进程/线程/内存管理(和 Linux 内核是「两个门派」)。
- Win32 API:系统给程序提供的「函数库」——创建窗口、画界面、读文件全靠它(C 语言时代的遗产,现在还在)。
- 消息循环(消息泵):Windows 程序的「心脏」——鼠标点一下、键盘敲一下,都变成「消息」发给窗口;程序循环取消息、处理消息。这是桌面 UI 和 Web 最大的不同!
- 句柄(Handle):窗口/文件/进程的「身份证号」——一切资源都用句柄操作。
还有两个概念:用户模式 vs 内核模式(程序不能直接碰硬件,要过 API 这道门——安全设计)、注册表(系统配置的「大字典」)、Windows 服务(开机自启的后台程序)。
【一个 Win32 程序(C 语言,最底层的样子)】
WinMain()
① 注册窗口类(告诉系统窗口长啥样)
② 创建窗口(CreateWindow → 拿到句柄 HWND)
③ 进入消息循环:
while (GetMessage(&msg)) {
TranslateMessage(&msg); // 翻译键盘消息
DispatchMessage(&msg); // 派发给窗口函数
}
④ 窗口函数处理消息(WndProc):
点鼠标 → WM_LBUTTONDOWN → 处理
画窗口 → WM_PAINT → 画内容
关窗口 → WM_CLOSE → 退出循环
【为什么懂它很重要】
一切 Windows UI 框架(WPF/WinUI)底层都是它
消息循环 → 理解「UI 必须单线程」的根源(第7站)
句柄 → 资源管理的概念(关闭句柄防泄漏)
【现代开发还需要 C 写 Win32 吗?】
不需要!现代框架全封装了——但「懂原理」帮你理解
为什么 Dispatcher 必须这样用、为什么 UI 卡顿
【用户模式 vs 内核模式】
程序不能直接操作硬件/内核数据
一切通过 Win32 API(系统调用)——安全边界
平台术语
- NT 内核:Windows 的底层——进程/线程/内存管理。
- Win32 API:系统函数库——程序的「系统接口」。
- 消息循环:事件驱动的泵——Windows 程序的心脏。
- 句柄(Handle):资源的「身份证号」——窗口/文件/进程。
- 用户/内核模式:程序与内核的安全边界。
- 注册表:系统配置的大字典——软件配置常存这。
- Windows 服务:开机自启的后台程序(无界面)。
本站收获:平台地基 = Win32 API(系统接口)+ 消息循环(事件驱动的心脏)+ 句柄(资源身份证)。现代开发不直接写它,但「消息循环 → UI 单线程」这条因果链,是一切桌面 UI 的根源。
技术栈演进:选型地图
Win32 · MFC · WPF · UWP · WinUI 3 · MAUI · Qt · Electron「Windows 开发用什么技术?」——答案是一张「历史地图」。40 年演进的每一代都还在江湖上活着,选型全看场景。
按时间线认识「家族成员」:
- Win32(C):祖宗——直接调 API,性能极致但开发慢(今天:驱动、底层工具、老系统维护)。
- MFC(C++):Win32 的 C++ 封装——老一代桌面软件的主力(维护老项目会碰到)。
- WPF(C#/XAML):2006 年至今的「经典王者」——声明式 UI + 数据绑定,企业桌面软件的主流。
- UWP(C#):微软推的「商店化」尝试——生态没起来,基本退场(了解即可)。
- WinUI 3(C#):新方向——现代 Fluent 设计 + 桌面原生能力,微软官方力推。
- .NET MAUI(C#):跨平台(Windows/Mac/iOS/Android)——一套代码多端。
- Qt(C++/QML):跨平台 C++ 框架——专业软件(CAD/工业)常见。
- Electron(Web):用 HTML/CSS/JS 做桌面——VS Code/钉钉都是它,重但开发快。
【技术栈家族树】
原生(性能/系统能力):
C/Win32 → 底层工具、驱动、极老系统
C++/MFC → 老桌面软件维护
C#/WPF → 企业桌面软件(现在的主流!)
C#/WinUI3 → 新桌面应用(微软力推的新方向)
跨平台:
C#/.NET MAUI → 一套代码多端(Win/Mac/iOS/Android)
C++/Qt → 专业软件(CAD/工业/嵌入式)
Web 技术:
Electron → 重 UI 应用、快速开发(VS Code/钉钉)
Tauri → 轻量 Electron 替代(Rust 后端,新宠)
【选型决策(按场景)】
企业内部工具(轻量) → WPF 或 WinUI 3
企业级桌面产品 → WPF(生态最成熟)
新桌面应用 → WinUI 3(微软力推)
需要跨平台(含手机) → .NET MAUI / Qt / Electron
已有 Web 团队 → Electron / Tauri
追求极致性能 → C++/Win32(或 Rust)
【学习建议】
必学:C# + WPF(就业面最广、资料最多)
关注:WinUI 3(未来方向)
了解:MAUI / Electron(跨平台场景)
技术栈术语
- Win32 / MFC:C/C++ 时代——底层但开发慢。
- WPF:XAML + C#——2006 至今的桌面王者。
- UWP:商店化尝试——基本退场。
- WinUI 3:现代 Fluent + 原生能力——微软新方向。
- .NET MAUI:一套 C# 代码多端(Win/Mac/手机)。
- Qt / Electron / Tauri:跨平台 C++ / Web 技术 / 轻量 Web。
- 选型口诀:企业桌面用 WPF,新应用看 WinUI 3,跨平台按团队选。
本站收获:技术栈地图 = Win32/MFC 是历史、WPF 是当下主流、WinUI 3 是未来、MAUI/Qt/Electron 是跨平台选项。先看懂地图,再选路——别一上来就纠结「学哪个」,先问「做什么」。
C# 与 .NET:现代主力
CLR · GC · LINQ · async/await · NuGet · 依赖注入Windows 现代开发的语言是 C#,平台是 .NET——语法像 Java、写起来像 Kotlin 一样舒服,还有 LINQ 这种「查询神器」。有 Java/Kotlin 底子,C# 上手飞快。
C# 六大看点:
- CLR 运行时:C# 编译成 IL 中间语言,CLR 负责跑(GC 自动回收——第十四本 Java JVM 的「微软表亲」)。
- 语法像 Java:类/接口/继承/泛型/异常——你在 Java 学的全能用上。
- LINQ:查询语法——对集合「筛/排/投影」一行搞定(比 Java Stream 更顺)。
- async/await:异步编程一等公民(第十六本协程、第四本 JS 同款思路)。
- NuGet:包管理——.NET 世界的「pip/Maven」(第十六本老朋友)。
- 依赖注入内置:.NET 自带 DI 容器——不用引第三方(第十四/十六本 IoC 老朋友)。
// 类和属性(属性 = 字段+getter/setter 的语法糖)
public class User {
public int Id { get; set; } // 自动属性
public string Name { get; set; } = "";
public string? Phone { get; set; } // 可空引用类型(Kotlin 空安全!)
}
// LINQ:查询集合(Java Stream / Kotlin 高阶函数的老朋友)
var adults = users
.Where(u => u.Age >= 18) // 筛选
.OrderBy(u => u.Name) // 排序
.Select(u => u.Name) // 投影
.ToList();
// async/await:异步(UI 不卡的关键,第7站展开)
public async Task<List<Order>> LoadOrdersAsync() {
return await _api.GetOrdersAsync(); // 挂起不阻塞
}
// 依赖注入(.NET 内置)
builder.Services.AddSingleton<IOrderService, OrderService>();
builder.Services.AddTransient<MainWindow>();
【C# vs Java vs Kotlin(三兄弟对比)】
语法:三者几乎同源(类/接口/泛型)
C# 特色:LINQ、属性、async 一等公民
Kotlin 特色:空安全、扩展函数、协程
→ 会任何一个,另两个上手都很快!
【.NET 版本(LTS 是王道,Java 同款哲学)】
.NET 6/8(LTS):现役主流——新项目用 .NET 8
每 11 月一个大版本——生产用 LTS
C# 术语
- CLR / IL:运行时 / 中间语言——GC 自动管理内存。
- 属性(Property):字段 + 访问器的语法糖——比 Java getter/setter 简洁。
- 可空引用类型(?):C# 8+ 的空安全——Kotlin 同款思路。
- LINQ:集合查询语法——Where/OrderBy/Select 链式调用。
- async/await / Task:异步编程——UI 不卡的关键。
- NuGet:包管理——.NET 生态的「应用商店」。
- DI 内置:依赖注入容器——AddSingleton/AddTransient。
本站收获:C# = Java 语法底子 + Kotlin 的空安全 + LINQ 查询神器 + 内置 DI。会 Java/Kotlin 的你,C# 三天上手——.NET 就是「微软版的 Java 生态」。
WPF:桌面 UI 经典
XAML · 数据绑定 · MVVM · 控件 · DispatcherWPF 是 Windows 桌面软件的「常青树」——声明式 XAML 写界面、数据绑定驱动更新、MVVM 组织代码。Android 学过 Compose 的你,会觉得很亲切。
WPF 四件套:
- XAML:声明式 UI 语言——和 Android 的 Compose「同宗不同源」(都是声明式:界面 = 描述,不是命令)。
- 数据绑定(Binding):界面和数据「自动同步」——数据变界面自动更新(状态驱动的 WPF 版)。
- MVVM:ViewModel + 数据绑定——逻辑和界面彻底分离(第十七本 MVVM 完全同构!)。
- Dispatcher:UI 线程的「调度员」——后台线程改 UI 必须通过它(消息循环的现代封装,第 1 站埋的梗在这收)。
控件生态:DataGrid(表格)、TreeView、TabControl……企业软件的「富控件」全都有。
<!-- XAML:声明式界面(对照 Android Compose)-->
<Window x:Class="Ledger.MainWindow" ...>
<Grid Margin="20">
<StackPanel>
<TextBlock Text="{Binding TotalText}"
FontSize="28" FontWeight="Bold"/>
<DataGrid ItemsSource="{Binding Orders}"
AutoGenerateColumns="False">
<DataGridTextColumn Header="标题" Binding="{Binding Title}"/>
<DataGridTextColumn Header="金额" Binding="{Binding Amount}"/>
</DataGrid>
<Button Content="刷新" Command="{Binding RefreshCommand}"/>
</StackPanel>
</Grid>
</Window>
// ViewModel:逻辑与界面分离(INotifyPropertyChanged 通知界面)
public class MainViewModel : INotifyPropertyChanged {
public ObservableCollection<Order> Orders { get; } = new();
private string _totalText = "合计 ¥0.00";
public string TotalText {
get => _totalText;
set { _totalText = value; OnPropertyChanged(); } // 通知界面更新
}
public ICommand RefreshCommand => new RelayCommand(async () => {
var data = await _service.LoadAsync(); // 后台加载
Orders.Clear();
foreach (var o in data) Orders.Add(o);
});
}
// Dispatcher:后台线程更新 UI 必须回 UI 线程
// (WPF 里 MVVM + 数据绑定自动处理大部分,手写时用 Dispatcher.Invoke)
【WPF vs Android Compose(对照学)】
XAML(声明式) ≈ Compose(声明式)
数据绑定 Binding ≈ 状态驱动(mutableStateOf)
MVVM ≈ MVVM(一模一样!)
Dispatcher ≈ 主线程限制(协程 Main dispatcher)
→ 学过 Compose 的人学 WPF 很快!
WPF 术语
- XAML:声明式 UI 语言——界面即描述。
- 数据绑定(Binding):界面数据自动同步——状态驱动。
- MVVM:ViewModel + 绑定——职责分离(第十七本同款)。
- INotifyPropertyChanged:属性变化通知——界面的「刷新信号」。
- ICommand:命令模式——按钮动作绑到 ViewModel。
- Dispatcher:UI 线程调度——后台改 UI 的入口。
- 样式 / 模板 / 资源:控件外观的「CSS」——主题统一。
本站收获:WPF = XAML 声明式 + 数据绑定 + MVVM + Dispatcher。和第十七本 Compose 的 MVVM 完全同构——桌面端和移动端的架构,最后长成了同一个样子。
WinUI 3:新方向
Fluent Design · Windows App SDK · MSIX · 与 WPF 对比WPF 是「经典王者」,但微软的新方向是 WinUI 3——现代 Fluent 设计 + 原生性能 + 桌面全能力。新项目怎么选?这一站讲清楚。
WinUI 3 是什么:
- Fluent Design:微软的现代设计语言——圆角、层次、动效、深色模式(对标 Material Design)。
- Windows App SDK:WinUI 3 的「工具箱」——把系统能力(通知、存储、多窗口)统一打包,桌面应用想用啥有啥。
- MSIX 打包:现代安装包格式——干净安装/卸载、自动更新、权限声明(对标 Android 的 App 包)。
- XAML 语法同款:会 WPF 就会 WinUI 3——语法几乎一样,控件更现代。
对比 WPF:WinUI 3 界面更现代、微软持续投入;WPF 生态更成熟、老项目多。新项目建议 WinUI 3,企业存量维护继续 WPF。
<!-- WinUI 3 XAML(和 WPF 同源,控件更现代)-->
<Window x:Class="Ledger.MainWindow" ...>
<StackPanel Spacing="12" Padding="24">
<TextBlock Text="本月支出" Style="{StaticResource TitleTextBlockStyle}"/>
<InfoBar Message="支出超预算 20%!" IsOpen="True"
Severity="Warning"/> <!-- Fluent 新控件 -->
<ListView ItemsSource="{x:Bind ViewModel.Orders}">...</ListView>
<Button Content="刷新" Command="{x:Bind ViewModel.Refresh}"/>
</StackPanel>
</Window>
【Fluent Design 关键词】
Mica/亚克力材质(半透明背景)、圆角、阴影层次
深色/浅色主题自适应、流畅动效
→ 界面「现代感」的主要来源
【Windows App SDK 能力】
系统通知(Toast)、多窗口、任务栏集成
存储访问、桌面快捷方式、自动更新(App Installer)
→ 桌面应用的「系统级工具箱」
【MSIX 打包(现代分发)】
干净安装/卸载(不留垃圾)、增量更新
权限声明、企业批量部署支持
→ 替代老 InstallShield 的现代方案
【选型结论】
新桌面应用 → WinUI 3(微软力推,现代)
企业存量维护 → WPF(生态成熟,资料多)
快速交付 → WPF 或 Electron(看团队)
→ 技能互通:XAML 学一次,两栈通吃
WinUI 3 术语
- WinUI 3:现代 Windows 原生 UI 框架——微软新方向。
- Fluent Design:微软设计语言——Mica 材质/圆角/动效。
- Windows App SDK:桌面能力工具箱——通知/多窗口/存储。
- MSIX:现代安装包格式——干净安装/自动更新。
- InfoBar / NavigationView:Fluent 新控件——现代交互组件。
- x:Bind:编译期绑定——比 Binding 更快。
- 深色模式:主题自适应——现代应用的标配。
本站收获:WinUI 3 = Fluent 现代设计 + Windows App SDK 全能力 + MSIX 干净分发。XAML 学一次两栈通吃——新项目看 WinUI 3,存量维护靠 WPF,技能是通的。
数据层:文件与数据库
文件 IO · EF Core · SQLite · 配置 · JSON桌面应用的数据住哪?——小数据用文件/JSON,结构化数据用 SQLite/EF Core,配置放 AppSettings。这一站,桌面端的数据层。
数据层四件套:
- 文件 IO:读写文件(文本/二进制/JSON)——导出报表、日志、配置。
- EF Core:.NET 的 ORM——类映射表,自动迁移(第十六本 SQLAlchemy、第十四本 JPA 的 .NET 版)。
- SQLite:桌面应用的事实数据库——单文件、免安装、零配置(手机 App 同款)。
- 配置(AppSettings/JSON):appsettings.json + 依赖注入绑定——配置外置(全系列老朋友)。
桌面特有:数据通常本地优先——用户的数据在自己机器上,隐私敏感度更高(第 10 站合规)。
// ① 实体(类 = 表)
public class Order {
public int Id { get; set; }
public string Title { get; set; } = "";
public decimal Amount { get; set; }
}
// ② DbContext(数据库会话)
public class AppDbContext : DbContext {
public DbSet<Order> Orders => Set<Order>();
protected override void OnConfiguring(DbContextOptionsBuilder b)
=> b.UseSqlite("Data Source=ledger.db"); // 单文件数据库!
}
// ③ 增删改查(LINQ 查询,不用拼 SQL)
await using var db = new AppDbContext();
db.Orders.Add(new Order { Title = "办公用品", Amount = 299.00m });
await db.SaveChangesAsync();
var bigOrders = await db.Orders
.Where(o => o.Amount > 100)
.OrderByDescending(o => o.Amount)
.ToListAsync();
// ④ 迁移(表结构版本管理,第16本 Alembic 同款)
// dotnet ef migrations add AddOrderTable
// dotnet ef database update
【配置文件(appsettings.json)】
{
"ConnectionStrings": { "Default": "Data Source=ledger.db" },
"Logging": { "LogLevel": { "Default": "Information" } }
}
// 程序里:builder.Configuration.GetConnectionString("Default")
【JSON 序列化(System.Text.Json)】
var json = JsonSerializer.Serialize(orders); // 对象 → JSON
var back = JsonSerializer.Deserialize<List<Order>>(json);
【桌面数据要点】
本地优先:数据存在用户机器(离线可用)
用户数据目录:%AppData%/你的应用/——标准位置
大文件/二进制:FileStream 流式读写(别全载内存)
数据层术语
- EF Core:.NET ORM——LINQ 查数据库,自动迁移。
- SQLite:单文件数据库——桌面应用标配。
- System.Text.Json:官方 JSON 序列化。
- appsettings.json:配置文件——配置外置。
- 本地优先:数据在用户机器——离线可用、隐私敏感。
- %AppData%:用户数据标准目录。
- 迁移(EF Migrations):表结构版本管理——git 式演进。
本站收获:数据层 = EF Core + SQLite(本地数据库)+ JSON/文件(小数据)+ appsettings(配置)。和十六/十四本的 ORM 世界完全同构——桌面端只是「默认本地存储」。
并发异步:UI 线程规则
UI 线程 · Dispatcher · async/await · Task · 死锁桌面 UI 的铁律:UI 只能由 UI 线程更新(第 1 站消息循环的根源)——后台任务要回 UI 线程才能改界面。async/await 让这件事优雅到「写起来像同步」。
三条铁律:
- UI 单线程:界面更新必须发生在 UI 线程——别的线程碰控件会崩(第 1 站消息循环的因果)。
- async/await:异步操作的现代写法——`await` 挂起不阻塞 UI,完成后自动回 UI 线程继续。
- Task:异步任务的载体——Task.Run 丢后台、Task.WhenAll 等全部(第十六本 Task/线程池的 .NET 版)。
经典坑:死锁——UI 线程等 Task,Task 又等回 UI 线程(.ConfigureAwait(false) 的用武之地);还有「后台改 UI」的跨线程异常。
// ✅ 正确:async/await,UI 不卡
private async void RefreshButton_Click(object sender, RoutedEventArgs e) {
// await 前:UI 线程(显示加载中)
statusText.Text = "加载中...";
var data = await Task.Run(() => service.LoadLargeData());
// await 后:自动回到 UI 线程!更新界面安全
ordersList.ItemsSource = data; // 安全更新 UI
statusText.Text = $"加载完成:{data.Count} 条";
}
// ❌ 错误:同步阻塞 UI(界面冻结)
private void Bad_Click(object sender, RoutedEventArgs e) {
var data = service.LoadLargeData(); // UI 冻结!几秒无响应
}
// 并发三件套
var t1 = Task.Run(() => Work1());
var t2 = Task.Run(() => Work2());
await Task.WhenAll(t1, t2); // 并行等待
// 死锁坑:UI 线程同步等待异步(经典错误)
// var data = service.LoadAsync().Result; ← 死锁!别这么写
// 正确:全程 await,别用 .Result/.Wait()
【async/await 心法】
async 方法里遇到 await → 挂起(不占线程)→ 完成后回来
上下文(UI 线程)自动恢复——这就是「UI 不卡」的秘密
同步上下文:WPF/WinUI 有 UI 同步上下文,await 自动回主线程
【和第十六本 Python 协程对比】
Python asyncio:事件循环 + 挂起
C# async/await:同步上下文 + 挂起
→ 思想一模一样,语法略不同
并发术语
- UI 线程(消息循环):界面更新的唯一线程——第 1 站的因果。
- Dispatcher / SynchronizationContext:回 UI 线程的「通道」。
- async/await:异步一等公民——挂起不阻塞。
- Task.Run / WhenAll:后台任务 / 并行等待。
- 死锁:.Result/.Wait() 同步等待异步——UI 经典坑。
- ConfigureAwait(false):不强制回原上下文——库代码防死锁。
- 跨线程异常:后台改 UI——崩溃现场。
本站收获:并发 = await 挂起不阻塞 + UI 线程规则(改界面回主线程)+ Task.Run 丢后台。记住:永远别用 .Result 同步等待——async/await 全程到底,UI 永不卡。
工程化:构建与分发
Visual Studio · NuGet · 单元测试 · MSIX 打包 · 自动更新桌面开发的工程化:IDE 全家桶、测试保障、打包分发、自动更新——「能编译」和「能交付」之间隔着一整套流程。
工程化五件事:
- Visual Studio:Windows 开发的事实 IDE——调试器、IntelliSense、可视化设计器(XAML 拖拽)。
- NuGet + 项目引用:包管理 + 模块化(多项目解决方案:App/Core/Data 分层)。
- 单元测试(xUnit/NUnit):测 ViewModel/业务逻辑——十六/十七本测试老朋友。
- 打包(MSIX):现代安装包——干净安装卸载、自动更新通道(第 5 站讲过)。
- 自动更新:桌面软件的「持续交付」——检查更新 → 下载 → 安装 → 重启(App Installer/自建更新服务)。
CI/CD:Azure Pipelines / GitHub Actions——提交代码自动构建、测试、打包(第二本老朋友)。
【解决方案结构(多项目分层)】
Ledger.sln
├── src/
│ ├── Ledger.App/ # WPF/WinUI 主程序(UI 层)
│ ├── Ledger.Core/ # 领域模型(纯逻辑,无 UI 依赖)
│ └── Ledger.Data/ # EF Core 数据层(Repository)
└── tests/
└── Ledger.Core.Tests/ # 单元测试
【xUnit 测试(十六本 pytest 的 .NET 版)】
[Fact]
public void 金额格式化_千分位正确() {
var vm = new MainViewModel();
Assert.Equal("¥1,299.00", vm.FormatAmount(1299.00m));
}
【打包发布(MSIX)】
Windows 应用打包项目 → 生成 .msix/.msixbundle
功能:干净安装/卸载、增量更新、证书签名
→ 企业分发:内部服务器 / 应用商店 / Intune
【自动更新方案】
① 商店更新(微软商店自动处理)
② App Installer(.appinstaller 文件 + Web 托管)
③ 自建更新服务(检查版本 → 下载 → 静默安装)
【CI/CD 流水线(GitHub Actions 简版)】
git push → dotnet test(测试全绿?)
→ dotnet publish(发布构建)
→ 打 MSIX 包 → 签名 → 上传分发渠道
→ 客户端自动更新(第9站讲签名)
工程化术语
- Visual Studio:Windows 开发 IDE——调试/设计器/IntelliSense。
- 解决方案(sln):多项目组织——App/Core/Data 分层。
- xUnit / NUnit:.NET 单元测试框架。
- MSIX 打包:现代安装包——干净安装/自动更新。
- 自动更新:App Installer / 自建更新服务——持续交付。
- CI/CD:Azure Pipelines / GitHub Actions——自动构建测试打包。
- 发布配置:Debug(调试)/ Release(发布)——签名混淆优化。
本站收获:工程化 = VS 开发 + 多项目分层 + xUnit 测试 + MSIX 打包 + 自动更新 + CI/CD。桌面软件的「交付感」:用户双击安装包,从此自动更新——像商店 App 一样省心。
系统集成:平台能力
P/Invoke · 注册表 · Windows 服务 · 托盘 · 文件关联 · COM桌面软件和 Web/手机最大的不同:它能「住进系统里」——开机自启、托盘常驻、文件关联、注册表配置。这一站,桌面端的「特权」。
系统集成七件套:
- P/Invoke:C# 调用 Win32 API——框架没封装的系统能力直接调(第 1 站 API 的现代入口)。
- 注册表:读写系统配置——软件设置/文件关联/开机启动(操作要小心,权限有边界)。
- Windows 服务:无界面后台程序——开机自启、常驻运行(监控/同步工具)。
- 托盘(NotifyIcon):任务栏右下角图标——后台常驻软件的「门面」(QQ/网盘都这样)。
- 文件关联:双击 .csv 用你的程序打开——注册文件类型关联。
- 启动项:开机自启(注册表/启动文件夹)——要克制,别惹用户烦。
- COM 组件:老牌组件模型——调 Office/系统组件(老技术,了解)。
// ① P/Invoke:C# 调 Win32 API(第1站 API 的现代入口)
[DllImport("user32.dll")]
static extern int MessageBox(IntPtr hWnd, string text,
string caption, uint type);
MessageBox(IntPtr.Zero, "你好,Windows!", "Ledger", 0);
// ② 托盘图标:后台常驻
var icon = new NotifyIcon {
Icon = SystemIcons.Application,
Text = "轻记账助手",
Visible = true,
};
icon.ContextMenuStrip = new ContextMenuStrip();
icon.ContextMenuStrip.Items.Add("打开主界面", null, (s, e) => ShowMain());
icon.ContextMenuStrip.Items.Add("退出", null, (s, e) => Exit());
// ③ 文件关联:双击 .ledger 打开
// 注册表注册(HKEY_CLASSES_ROOT\.ledger → 关联你的 exe)
// ④ 开机自启(注册表方式)
// HKCU\Software\Microsoft\Windows\CurrentVersion\Run
// 注意:别偷偷自启!用户知情 + 设置里可关闭
【系统集成注意事项】
权限边界:注册表 HKCU(当前用户)可写;HKLM(全机)要管理员
服务 vs 托盘:常驻后台用服务(无 UI);用户可见用托盘
启动项克制:偷偷自启 = 被卸载的理由(流氓软件画像)
卸载干净:不留注册表垃圾(MSIX 打包自动处理,第8站)
【桌面特权(对比 Web/手机)】
Web:没有系统能力(沙箱)
Android:权限申请制(动态申请)
Windows 桌面:能力最开放——也最需要自律
系统集成术语
- P/Invoke:C# 调 Win32 API——系统能力的入口。
- 注册表:系统配置字典——HKCU 可写、HKLM 要管理员。
- Windows 服务:无界面常驻程序——开机自启。
- NotifyIcon(托盘):任务栏图标——后台常驻的门面。
- 文件关联:双击文件用你的程序打开。
- 开机自启:启动项——克制使用,别惹人烦。
- COM:老牌组件模型——调 Office 等(了解)。
本站收获:系统集成 = P/Invoke 调 API + 注册表管配置 + 托盘做常驻 + 文件关联接文件。桌面能力最开放,也最需要自律——「能力越大,越要克制」。
安全质量:桌面规矩
UAC · 代码签名 · SmartScreen · 崩溃监控 · 兼容桌面软件上线前有一道「鬼门关」:用户下载后被 SmartScreen 拦、杀毒软件报毒、兼容性翻车——这一站,把桌面的规矩讲透。
桌面安全五件事:
- UAC(用户账户控制):需要管理员权限的操作弹窗确认——程序默认普通权限,别乱要管理员(第 1 站「用户/内核模式」的现代形态)。
- 代码签名(证书):给 exe/安装包签名——证明「我是正经开发者」;不签名 = SmartScreen 拦 + 杀软误报。
- SmartScreen / Defender:Windows 的「安全检查」——未签名的新软件会被警告,用户吓跑。
- 崩溃监控(WER/日志):Windows 错误报告 + 自己的日志——崩溃自动上报(和 Android Crashlytics 同思路)。
- 版本兼容:Windows 10/11 双版本 + 32/64 位——发布前兼容性测试(第十八本 Android 适配的 Windows 版)。
再加隐私合规:桌面软件收集用户数据同样受个保法约束(第八本老朋友)——收集要告知、可删除。
【代码签名流程(软件过审的关键)】
① 买代码签名证书(OV/EV 级别,几百到几千元/年)
② 用证书给 exe/MSIX 签名(signtool)
③ 签名后:SmartScreen 不再「未知发布者」
→ 用户下载安装的信任成本大降
(没签名 = 下载被警告 = 用户流失!)
【UAC 正确姿势】
默认普通权限运行(别要求「以管理员运行」)
真需要管理员的操作(写 HKLM/装驱动)→ 弹 UAC 单独提权
→ 乱要管理员 = 用户警惕 + 安全审计风险
【崩溃监控方案】
Windows WER(系统级错误上报)+ 自建日志
崩溃日志:全局异常捕获 → 写本地日志 → 下次启动上传
→ 和 Android Crashlytics 同思路(第十八本老朋友)
【版本兼容清单】
□ Windows 10 / 11 都测过
□ 32 位 / 64 位(x86/x64/ARM64)
□ 高分屏(DPI 缩放)、深色模式
□ 中文/英文系统(路径/编码 Unicode)
【隐私合规(第八本老朋友)】
□ 收集数据有隐私政策 + 首次告知
□ 数据只存本机(本地优先)——别偷偷上传!
□ 提供「删除我的数据」入口
→ 桌面软件的信任,建立在「不偷数据」上
轻记账桌面版第一版没签名——用户下载后 SmartScreen 弹「Windows 已保护你的电脑」,一半用户被吓跑。整改:买 EV 证书 → 签名 → 重新打包 → 用户下载不再警告,安装率提升 3 倍。「代码签名」是桌面软件的第一张信任状。
安全术语
- UAC:用户账户控制——提权弹窗确认。
- 代码签名:证书签名 exe/MSIX——SmartScreen 不拦的钥匙。
- SmartScreen:Windows 安全过滤——未签名软件被警告。
- WER / 崩溃日志:系统错误上报 + 自建日志——崩溃可追踪。
- 版本兼容:Win10/11、32/64 位、高分屏——发布前必测。
- 隐私合规:个保法——本地优先 + 不偷传数据。
- 信任状:签名证书 = 桌面软件的「身份证」。
本站收获:安全 = 代码签名保信任 + UAC 克制提权 + 崩溃监控盯质量 + 兼容性测试保覆盖 + 隐私合规守底线。桌面软件的规矩,第一条就是「让用户敢装」。
知识点速查 + 面试高频题
面试/交付前最后一页Windows 开发知识全景表
| 领域 | 核心知识点 | 一句话人话 |
|---|---|---|
| 平台架构 | Win32 API、消息循环、句柄、用户/内核模式 | 系统怎么组织 |
| 技术栈 | Win32→MFC→WPF→UWP→WinUI 3→MAUI/Qt/Electron | 40 年选型地图 |
| C#/.NET | CLR、LINQ、async/await、NuGet、DI | 现代主力语言 |
| WPF | XAML、数据绑定、MVVM、Dispatcher | 桌面 UI 经典王者 |
| WinUI 3 | Fluent、Windows App SDK、MSIX | 新方向 |
| 数据层 | EF Core、SQLite、JSON、appsettings | 本地优先存储 |
| 并发异步 | UI 线程、async/await、Task、死锁 | UI 永不卡 |
| 工程化 | VS、xUnit、MSIX、自动更新、CI/CD | 从源码到安装包 |
| 系统集成 | P/Invoke、注册表、托盘、文件关联、服务 | 住进系统里 |
| 安全质量 | UAC、代码签名、SmartScreen、崩溃监控、兼容 | 让用户敢装 |
面试高频题速记
- Windows 程序的消息循环是什么?→ 事件驱动泵——窗口消息取→派发→处理,UI 单线程的根源。
- WPF 和 WinUI 3 区别?→ 经典成熟 vs 现代 Fluent——XAML 语法同源,新项目选 WinUI 3。
- 为什么 UI 只能在主线程更新?→ 消息循环 + 线程安全——后台改 UI 会崩,用 Dispatcher/await。
- async/await 怎么做到 UI 不卡?→ await 挂起不占线程,完成后自动回 UI 同步上下文。
- C# 的 LINQ 是什么?→ 集合查询语法——Where/Select/OrderBy 链式(Java Stream 亲戚)。
- 什么是死锁?→ .Result/.Wait() 同步等异步 + UI 上下文——永远全程 await。
- 为什么代码要签名?→ SmartScreen 信任 + 防篡改——不签名用户不敢装。
- WPF 的 MVVM 是什么?→ ViewModel + 数据绑定——界面逻辑分离(Android 同款)。
- 桌面数据存哪?→ SQLite(单文件数据库)+ %AppData%——本地优先。
- UAC 是什么?→ 用户账户控制——提权弹窗,程序默认普通权限。
一半是技术,一半是「规矩」。
四十年的技术栈层层叠叠,但底层的道理从未变过:
桌面开发的本质,是「住进用户的电脑里,还让他放心」。