云计算百科
云计算领域专业知识百科平台

02-02 Windows 软件体系 - 应用程序分类体系与多维划分模型(上)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */
#content_views .toc,
/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */
#content_views.markdown_views > p:empty:has(+ .toc),
#content_views.markdown_views > .toc + p:empty,
/* 富文本旧版目录标记 */
#content_views.htmledit_views #main-toc,
#content_views.htmledit_views #hr-toc,
#content_views.htmledit_views p[id*=\”-toc\”] {
display: none !important;
}
/* 目录去掉后,紧跟的首个标题不再多出一块上边距 */
#content_views.markdown_views > .toc + h1,
#content_views.markdown_views > .toc + h2,
#content_views.markdown_views > .toc + h3,
#content_views.markdown_views > .toc + h4,
#content_views.markdown_views > .toc + p:empty + h1,
#content_views.markdown_views > .toc + p:empty + h2,
#content_views.markdown_views > .toc + p:empty + h3,
#content_views.markdown_views > .toc + p:empty + h4 {
margin-top: 0 !important;
}

应用程序分类体系与多维划分模型

文档定位:本文档是「Windows 软件体系全链路解析」系列的第 02-02 篇,对应原始文档第 2.1.2 节。在上一篇(02-01)明确了应用程序的定义与本质之后,本文档对 Windows 平台上的应用程序进行系统化的多维分类,建立完整的分类体系与划分模型。分类是理解应用程序架构差异、部署要求和安全边界的基石——不同类型的应用在 PE 子系统声明、入口函数、运行时依赖、内存模型、权限边界和生命周期管理上存在根本性差异。本文档以 8 个正交分类维度展开,通过 多张 Mermaid 图表和大量代码级细节,构建一个可操作的多维分类框架。


目录

  • 1. 应用程序分类概述
    • 1.1 分类的必要性与工程价值
    • 1.2 单一维度的局限性
    • 1.3 多维分类模型的概念
    • 1.4 多维分类模型总览图
  • 2. 按用户界面类型分类
    • 2.1 控制台应用(Console Application)
    • 2.2 GUI 桌面应用(GUI Desktop Application)
    • 2.3 Windows 服务(Windows Service)
    • 2.4 UWP 应用(Universal Windows Platform)
    • 2.5 界面类型分类对比
  • 3. 按运行时依赖分类
    • 3.1 原生应用(Native Application)
    • 3.2 .NET 应用(Managed Application)
    • 3.3 Java 应用
    • 3.4 脚本应用(Script Application)
    • 3.5 混合应用(Hybrid Application)
    • 3.6 运行时依赖分类对比
  • 4. 按位宽分类
    • 4.1 32 位应用(x86)
    • 4.2 64 位应用(x64)
    • 4.3 ARM64 应用
    • 4.4 位宽兼容性与 WoW64
  • 5. 按运行模式分类
    • 5.1 交互式应用
    • 5.2 后台服务
    • 5.3 守护进程
    • 5.4 一次性应用
    • 5.5 运行模式分类对比
  • 6. 按部署方式分类
    • 6.1 MSI 安装包
    • 6.2 ClickOnce 部署
    • 6.3 MSIX/AppX 打包
    • 6.4 便携应用(Portable)
    • 6.5 Store 应用
    • 6.6 部署方式对比
  • 7. 按权限级别分类
    • 7.1 普通用户权限
    • 7.2 管理员权限
    • 7.3 UAC 虚拟化
    • 7.4 AppContainer 沙箱
    • 7.5 权限层次模型
  • 8. 按网络通信模式分类
    • 8.1 纯本地应用
    • 8.2 客户端应用
    • 8.3 服务端应用
    • 8.4 P2P 应用
  • 9. 分类维度的交叉组合
    • 9.1 多维交叉的概念
    • 9.2 常见组合的特征分析
    • 9.3 多维交叉矩阵
  • 10. 分类对架构设计的影响
    • 10.1 不同分类在关系链中的差异
    • 10.2 架构选择指南
  • 11. 总结

1. 应用程序分类概述

1.1 分类的必要性与工程价值

在 Windows 平台上,应用程序并非一个同质化的概念。一个用 C 语言编写的命令行工具、一个用 C# 开发的 WPF 桌面程序、一个用 Electron 构建的跨平台编辑器、以及一个注册为 Windows 服务的后台守护进程——它们虽然在操作系统层面都以"进程"的形式存在,但在架构设计、资源消耗、安全模型、部署方式和用户体验上呈现出截然不同的特征。

分类的工程价值体现在以下几个关键方面:

架构决策的基础:在项目启动阶段,技术选型的第一步不是选择编程语言或框架,而是确定应用程序的类型。一个需要 7×24 小时运行的后台数据处理系统,应该选择 Windows 服务而非控制台应用;一个需要丰富交互体验的面向终端用户的工具,应该选择 GUI 桌面应用而非控制台应用。分类体系为这一决策提供了结构化的框架。

安全边界的界定:不同类型的应用具有不同的安全边界和攻击面。UWP 应用运行在 AppContainer 沙箱中,其文件系统访问和注册表写入受到严格限制;而以管理员权限运行的 Win32 桌面应用则拥有对整个系统的控制权。理解分类体系意味着理解每种应用类型的安全模型,从而在设计和审查阶段做出正确的权限决策。

性能预期的管理:原生 C++ 应用与 .NET 托管应用在启动速度、内存占用和运行时性能上存在数量级差异。Electron 应用动辄占用数百 MB 内存,而等效的 Win32 原生应用可能仅需几 MB。分类体系帮助开发者和架构师在项目初期建立合理的性能预期,并在性能瓶颈出现时定位根因——是运行时开销、还是架构选择导致的固有代价。

部署策略的规划:MSI 安装包、ClickOnce、MSIX 打包、便携可执行文件——每种部署方式都有其适用场景和限制。MSIX 提供了干净的安装/卸载体验和自动更新能力,但要求应用通过容器化运行;便携应用无需安装但无法注册系统级服务。分类体系将部署方式与应用类型关联,帮助制定正确的分发策略。

调试与诊断的定向:当应用程序出现问题时,诊断路径取决于应用类型。.NET 应用的内存泄漏需要通过 CLR Profiler 或 dotMemory 分析 GC 堆;原生应用的崩溃需要通过 minidump 和 WinDbg 分析调用栈;Windows 服务的问题可能涉及 SCM 交互和会话隔离。不理解应用类型就无法选择正确的诊断工具链。

1.2 单一维度的局限性

传统的应用程序分类往往只关注单一维度——最常见的做法是按"用户界面类型"将应用分为"控制台应用"和"GUI 应用"。这种单一维度分类虽然在直觉上易于理解,但在工程实践中存在严重的局限性。

考虑以下场景:一个用 C# 编写的、以 Windows 服务形式部署的、运行在 64 位系统上的、需要管理员权限的、通过网络与远程数据库通信的数据同步服务。如果仅按界面类型分类,它被归类为"服务应用"——这只揭示了它的无界面特征和后台运行模式,却完全忽略了它的运行时依赖(.NET CLR)、位宽(x64)、权限需求(管理员)和网络行为(客户端模式)等同样关键的属性。

单一维度分类的根本问题在于:应用程序的属性是多正交的。一个应用可以同时是"控制台应用"+“原生应用”+“64位”+“后台服务”+“便携部署”+“普通权限”+“网络客户端”。这些维度相互独立,每个维度都对应用的行为特征产生独立影响。要全面描述一个应用程序,需要多维度的交叉描述,而非单一标签。

1.3 多维分类模型的概念

多维分类模型的核心思想是:将应用程序的属性分解为若干个正交的维度,每个维度描述应用的一个独立侧面,应用程序的完整描述是所有维度取值的组合。

在本文档中,我们定义以下 8 个分类维度:

维度编号维度名称分类依据典型取值
D1 用户界面类型 应用的交互方式 控制台 / GUI桌面 / Windows服务 / UWP
D2 运行时依赖 应用的执行引擎 原生 / .NET / Java / 脚本 / 混合
D3 位宽 指针大小和地址空间 x86 / x64 / ARM64
D4 运行模式 应用的生命周期形态 交互式 / 后台服务 / 守护进程 / 一次性
D5 部署方式 应用的分发和安装形式 MSI / ClickOnce / MSIX / 便携 / Store
D6 权限级别 应用的安全特权层级 普通用户 / 管理员 / AppContainer
D7 网络通信模式 应用的网络行为特征 纯本地 / 客户端 / 服务端 / P2P
D8 架构耦合度 应用与系统的耦合程度 独立 / 系统集成 / 平台依赖

这些维度的正交性意味着:改变一个维度的取值通常不会直接决定其他维度的取值。例如,一个 GUI 桌面应用(D1=GUI)可以是原生的(D2=Native)也可以是 .NET 的(D2=.NET),可以是 32 位的(D3=x86)也可以是 64 位的(D3=x64)。当然,某些维度之间存在约束关系——例如 UWP 应用(D1=UWP)必须使用 MSIX/AppX 部署(D5=MSIX),但这属于维度间的约束规则,而非维度本身的非正交性。

1.4 多维分类模型总览图

#mermaid-svg-wNPizelil07A2zIQ{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-wNPizelil07A2zIQ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-wNPizelil07A2zIQ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-wNPizelil07A2zIQ .error-icon{fill:#552222;}#mermaid-svg-wNPizelil07A2zIQ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-wNPizelil07A2zIQ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-wNPizelil07A2zIQ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-wNPizelil07A2zIQ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-wNPizelil07A2zIQ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-wNPizelil07A2zIQ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-wNPizelil07A2zIQ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-wNPizelil07A2zIQ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-wNPizelil07A2zIQ .marker.cross{stroke:#333333;}#mermaid-svg-wNPizelil07A2zIQ svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-wNPizelil07A2zIQ p{margin:0;}#mermaid-svg-wNPizelil07A2zIQ .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-wNPizelil07A2zIQ .cluster-label text{fill:#333;}#mermaid-svg-wNPizelil07A2zIQ .cluster-label span{color:#333;}#mermaid-svg-wNPizelil07A2zIQ .cluster-label span p{background-color:transparent;}#mermaid-svg-wNPizelil07A2zIQ .label text,#mermaid-svg-wNPizelil07A2zIQ span{fill:#333;color:#333;}#mermaid-svg-wNPizelil07A2zIQ .node rect,#mermaid-svg-wNPizelil07A2zIQ .node circle,#mermaid-svg-wNPizelil07A2zIQ .node ellipse,#mermaid-svg-wNPizelil07A2zIQ .node polygon,#mermaid-svg-wNPizelil07A2zIQ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-wNPizelil07A2zIQ .rough-node .label text,#mermaid-svg-wNPizelil07A2zIQ .node .label text,#mermaid-svg-wNPizelil07A2zIQ .image-shape .label,#mermaid-svg-wNPizelil07A2zIQ .icon-shape .label{text-anchor:middle;}#mermaid-svg-wNPizelil07A2zIQ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-wNPizelil07A2zIQ .rough-node .label,#mermaid-svg-wNPizelil07A2zIQ .node .label,#mermaid-svg-wNPizelil07A2zIQ .image-shape .label,#mermaid-svg-wNPizelil07A2zIQ .icon-shape .label{text-align:center;}#mermaid-svg-wNPizelil07A2zIQ .node.clickable{cursor:pointer;}#mermaid-svg-wNPizelil07A2zIQ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-wNPizelil07A2zIQ .arrowheadPath{fill:#333333;}#mermaid-svg-wNPizelil07A2zIQ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-wNPizelil07A2zIQ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-wNPizelil07A2zIQ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wNPizelil07A2zIQ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-wNPizelil07A2zIQ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wNPizelil07A2zIQ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-wNPizelil07A2zIQ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-wNPizelil07A2zIQ .cluster text{fill:#333;}#mermaid-svg-wNPizelil07A2zIQ .cluster span{color:#333;}#mermaid-svg-wNPizelil07A2zIQ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-wNPizelil07A2zIQ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-wNPizelil07A2zIQ rect.text{fill:none;stroke-width:0;}#mermaid-svg-wNPizelil07A2zIQ .icon-shape,#mermaid-svg-wNPizelil07A2zIQ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wNPizelil07A2zIQ .icon-shape p,#mermaid-svg-wNPizelil07A2zIQ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-wNPizelil07A2zIQ .icon-shape .label rect,#mermaid-svg-wNPizelil07A2zIQ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wNPizelil07A2zIQ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-wNPizelil07A2zIQ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-wNPizelil07A2zIQ :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

维度 D8: 架构耦合度

独立应用

系统集成

平台依赖

维度 D7: 网络通信

纯本地

客户端

服务端

P2P

维度 D6: 权限级别

普通用户

管理员

AppContainer

维度 D5: 部署方式

MSI 安装包

ClickOnce

MSIX/AppX

便携应用

Store 应用

维度 D4: 运行模式

交互式

后台服务

守护进程

一次性

维度 D3: 位宽

x86 (32位)

x64 (64位)

ARM64

维度 D2: 运行时依赖

原生应用

.NET 应用

Java 应用

脚本应用

混合应用

维度 D1: 用户界面类型

控制台应用

GUI 桌面应用

Windows 服务

UWP 应用

Windows 应用程序(待分类实体)

上图展示了多维分类模型的完整框架。每一个 Windows 应用程序都可以在这个 8 维空间中找到一个唯一的坐标点。例如:

  • notepad.exe:(D1=GUI桌面, D2=原生, D3=x64, D4=交互式, D5=系统内置, D6=普通用户, D7=纯本地, D8=平台依赖)
  • cmd.exe:(D1=控制台, D2=原生, D3=x64, D4=交互式, D5=系统内置, D6=普通用户, D7=纯本地, D8=平台依赖)
  • Visual Studio Code:(D1=GUI桌面, D2=混合, D3=x64, D4=交互式, D5=MSI, D6=普通用户, D7=客户端, D8=独立应用)
  • Windows Update 服务:(D1=Windows服务, D2=原生, D3=x64, D4=后台服务, D5=系统内置, D6=系统级, D7=客户端, D8=系统集成)
  • Windows 设置应用:(D1=UWP, D2=.NET, D3=x64/ARM64, D4=交互式, D5=Store, D6=AppContainer, D7=纯本地, D8=平台依赖)

下面各章节将逐一深入每个维度的技术细节。


2. 按用户界面类型分类

用户界面类型是应用程序最直观的分类维度。它决定了应用与用户的交互方式、PE 文件中的子系统声明、入口函数签名以及操作系统的加载行为。

2.1 控制台应用(Console Application)

2.1.1 核心特征

控制台应用是最基础的 Windows 应用程序类型。它的核心特征如下:

  • 文本界面:通过标准输入(stdin)、标准输出(stdout)和标准错误(stderr)三个字符流与用户交互,没有图形窗口、按钮或菜单。
  • 入口函数:C/C++ 中为 main() 或 wmain();.NET 中为 static void Main(string[] args) 或 static async Task Main()。
  • PE 子系统:PE 可选头中的 Subsystem 字段值为 IMAGE_SUBSYSTEM_WINDOWS_CUI(值为 3),表示控制台用户界面。
  • 控制台句柄:操作系统在创建控制台应用进程时,自动分配控制台缓冲区(Console Screen Buffer)和输入缓冲区,通过 GetStdHandle() 获取句柄。
  • 同步执行模型:控制台应用通常采用自顶向下的同步执行流程,从 main() 入口开始,按代码顺序执行,到 main() 返回或调用 exit() 时终止。
2.1.2 PE 子系统声明

控制台应用的 PE 头中,可选头(IMAGE_OPTIONAL_HEADER)的 Subsystem 字段被设置为 3:

// PE 头中的子系统声明
typedef struct _IMAGE_OPTIONAL_HEADER {
// … 其他字段 …
WORD Subsystem; // IMAGE_SUBSYSTEM_WINDOWS_CUI = 3
// … 其他字段 …
} IMAGE_OPTIONAL_HEADER;

#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // 控制台应用

当 Windows 加载器(ntdll.dll 中的 LdrInitializeThunk)读取到 Subsystem=3 时,会执行以下操作:

  • 调用 Conhost(Windows 7 及以上)或 csrss.exe(Windows XP/Vista)创建控制台窗口
  • 分配控制台输入缓冲区和屏幕缓冲区
  • 设置进程的标准句柄(stdin=键盘, stdout/stderr=控制台屏幕)
  • 如果是从现有控制台启动(如 cmd.exe 中运行),则附加到父进程的控制台
  • 2.1.3 入口函数与 CRT 启动

    控制台应用的 CRT 启动流程涉及从 PE 入口点到用户 main() 函数的桥接:

    // 编译器生成的真实 PE 入口点(非用户的 main())
    // 对于 MSVC,入口点通常名为 mainCRTStartup 或 wmainCRTStartup

    void mainCRTStartup(void) {
    // 1. 调用 _CRT_INIT 初始化 CRT
    // – 初始化堆管理器(_heap_init)
    // – 初始化多线程支持(_mtinit)
    // – 初始化标准 I/O(_ioinit)
    // – 获取操作系统版本信息
    // – 解析命令行参数(GetCommandLineW -> CommandLineToArgvW)
    // – 获取环境变量块(GetEnvironmentStringsW)

    // 2. 调用 atexit 注册表初始化

    // 3. 调用用户定义的 main 函数
    int ret = main(argc, argv, envp);

    // 4. 执行退出清理
    // – 调用 atexit 注册的清理函数
    // – 调用 CRT 全局析构函数
    // – 调用 ExitProcess(ret)
    }

    2.1.4 控制台应用架构图

    #mermaid-svg-8zyKjtogxsrZo8BN{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8zyKjtogxsrZo8BN .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8zyKjtogxsrZo8BN .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8zyKjtogxsrZo8BN .error-icon{fill:#552222;}#mermaid-svg-8zyKjtogxsrZo8BN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8zyKjtogxsrZo8BN .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8zyKjtogxsrZo8BN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8zyKjtogxsrZo8BN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8zyKjtogxsrZo8BN .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8zyKjtogxsrZo8BN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8zyKjtogxsrZo8BN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8zyKjtogxsrZo8BN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8zyKjtogxsrZo8BN .marker.cross{stroke:#333333;}#mermaid-svg-8zyKjtogxsrZo8BN svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8zyKjtogxsrZo8BN p{margin:0;}#mermaid-svg-8zyKjtogxsrZo8BN .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-8zyKjtogxsrZo8BN .cluster-label text{fill:#333;}#mermaid-svg-8zyKjtogxsrZo8BN .cluster-label span{color:#333;}#mermaid-svg-8zyKjtogxsrZo8BN .cluster-label span p{background-color:transparent;}#mermaid-svg-8zyKjtogxsrZo8BN .label text,#mermaid-svg-8zyKjtogxsrZo8BN span{fill:#333;color:#333;}#mermaid-svg-8zyKjtogxsrZo8BN .node rect,#mermaid-svg-8zyKjtogxsrZo8BN .node circle,#mermaid-svg-8zyKjtogxsrZo8BN .node ellipse,#mermaid-svg-8zyKjtogxsrZo8BN .node polygon,#mermaid-svg-8zyKjtogxsrZo8BN .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8zyKjtogxsrZo8BN .rough-node .label text,#mermaid-svg-8zyKjtogxsrZo8BN .node .label text,#mermaid-svg-8zyKjtogxsrZo8BN .image-shape .label,#mermaid-svg-8zyKjtogxsrZo8BN .icon-shape .label{text-anchor:middle;}#mermaid-svg-8zyKjtogxsrZo8BN .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8zyKjtogxsrZo8BN .rough-node .label,#mermaid-svg-8zyKjtogxsrZo8BN .node .label,#mermaid-svg-8zyKjtogxsrZo8BN .image-shape .label,#mermaid-svg-8zyKjtogxsrZo8BN .icon-shape .label{text-align:center;}#mermaid-svg-8zyKjtogxsrZo8BN .node.clickable{cursor:pointer;}#mermaid-svg-8zyKjtogxsrZo8BN .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8zyKjtogxsrZo8BN .arrowheadPath{fill:#333333;}#mermaid-svg-8zyKjtogxsrZo8BN .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8zyKjtogxsrZo8BN .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8zyKjtogxsrZo8BN .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8zyKjtogxsrZo8BN .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8zyKjtogxsrZo8BN .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8zyKjtogxsrZo8BN .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8zyKjtogxsrZo8BN .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8zyKjtogxsrZo8BN .cluster text{fill:#333;}#mermaid-svg-8zyKjtogxsrZo8BN .cluster span{color:#333;}#mermaid-svg-8zyKjtogxsrZo8BN div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8zyKjtogxsrZo8BN .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8zyKjtogxsrZo8BN rect.text{fill:none;stroke-width:0;}#mermaid-svg-8zyKjtogxsrZo8BN .icon-shape,#mermaid-svg-8zyKjtogxsrZo8BN .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8zyKjtogxsrZo8BN .icon-shape p,#mermaid-svg-8zyKjtogxsrZo8BN .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8zyKjtogxsrZo8BN .icon-shape .label rect,#mermaid-svg-8zyKjtogxsrZo8BN .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8zyKjtogxsrZo8BN .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8zyKjtogxsrZo8BN .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8zyKjtogxsrZo8BN :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    控制台子系统

    进程地址空间

    操作系统加载层

    磁盘

    CreateProcess

    Subsystem=3

    WriteConsoleWriteFile

    ReadConsoleReadFile

    键盘事件

    app.exeSubsystem=CUI(3)

    PE 加载器ntdll.dll!LdrpInitializeProcess

    读取 PE Optional HeaderSubsystem = 3 (CUI)

    控制台管理器condrv.sys + conhost.exe

    CRT 启动代码mainCRTStartup

    用户代码main(argc, argv)

    标准 I/O 层printf/scanf/fwrite

    屏幕缓冲区Console Screen Buffer

    输入缓冲区Console Input Buffer

    控制台窗口conhost.exe 渲染

    2.1.5 典型示例与场景

    控制台应用的典型场景包括:

    场景示例程序说明
    系统命令行工具 cmd.exe, powershell.exe 交互式命令解释器
    网络诊断工具 ping.exe, ipconfig.exe, nslookup.exe 输出文本格式的诊断结果
    文件操作工具 copy.exe, xcopy.exe, robocopy.exe 批量文件操作
    编译器/链接器 cl.exe, link.exe, gcc.exe 输出编译结果和错误信息
    构建工具 msbuild.exe, cmake.exe, make.exe 自动化构建流程
    脚本解释器 python.exe, node.exe 执行脚本文件
    后台批处理 tasklist.exe, schtasks.exe 系统管理自动化
    2.1.6 控制台应用的特殊行为

    控制台应用有一些与其他应用类型不同的特殊行为:

    控制台附加与分离:控制台应用可以通过 AllocConsole() 创建新的控制台窗口,或通过 AttachConsole(pid) 附加到另一个进程的控制台。这在需要将 GUI 应用转换为具有控制台输出的混合模式时有用。

    控制台信号处理:当用户按下 Ctrl+C 或 Ctrl+Break 时,控制台子系统向所有附加到该控制台的进程发送 CTRL_C_EVENT 或 CTRL_BREAK_EVENT 信号。应用通过 SetConsoleCtrlHandler() 注册处理函数:

    // 控制台信号处理示例
    BOOL WINAPI ConsoleHandler(DWORD signal) {
    switch (signal) {
    case CTRL_C_EVENT:
    printf("Ctrl+C pressed, cleaning up…\\n");
    // 执行清理操作
    break;
    case CTRL_CLOSE_EVENT:
    printf("Console window closing…\\n");
    // 保存状态
    break;
    case CTRL_LOGOFF_EVENT:
    printf("User logoff…\\n");
    break;
    case CTRL_SHUTDOWN_EVENT:
    printf("System shutdown…\\n");
    break;
    }
    return TRUE;
    }

    int main() {
    SetConsoleCtrlHandler(ConsoleHandler, TRUE);
    // … 主逻辑 …
    return 0;
    }

    控制台输出重定向:控制台应用的标准输出可以被重定向到管道或文件。当 stdout 不是控制台句柄时,printf 的行为会发生变化——控制台输出使用 WriteConsoleW 进行 UTF-16LE 编码输出,而重定向到文件时则使用 WriteFile 按字节输出。这导致中文输出在重定向时可能出现编码问题。

    2.2 GUI 桌面应用(GUI Desktop Application)

    2.2.1 核心特征

    GUI 桌面应用是 Windows 平台上最常见的应用类型,其核心特征如下:

    • 图形窗口界面:通过窗口(Window)、控件(Control)、菜单(Menu)、对话框(Dialog)等图形元素与用户交互。
    • 入口函数:C/C++ Win32 API 中为 WinMain() 或 wWinMain();.NET WinForms/WPF 中为 static void Main() 并标记 [STAThread]。
    • PE 子系统:IMAGE_SUBSYSTEM_WINDOWS_GUI(值为 2),表示图形用户界面。
    • 消息驱动架构:GUI 应用的核心运行机制是消息循环(Message Loop),通过 GetMessage() / TranslateMessage() / DispatchMessage() 处理用户输入和系统通知。
    • GDI/DirectComposition 渲染:传统 Win32 应用使用 GDI/GDI+ 绘制界面;现代 WPF/WinUI 应用使用 DirectX + DirectComposition 进行硬件加速渲染。
    2.2.2 PE 子系统声明

    GUI 应用的 PE 头中,Subsystem 字段被设置为 2:

    #define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // GUI 应用

    当加载器读取到 Subsystem=2 时,不会创建控制台窗口。如果该应用需要控制台输出(如调试日志),必须显式调用 AllocConsole()。

    2.2.3 入口函数与消息循环

    Win32 GUI 应用的入口函数 WinMain 签名如下:

    int WINAPI WinMain(
    HINSTANCE hInstance, // 当前实例句柄
    HINSTANCE hPrevInstance, // 前一个实例句柄(Win32 中始终为 NULL)
    LPSTR lpCmdLine, // 命令行参数(ANSI 字符串)
    int nCmdShow // 窗口初始显示状态
    );

    // Unicode 版本
    int wWinMain(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPWSTR lpCmdLine, // 命令行参数(Unicode 字符串)
    int nCmdShow
    );

    Win32 GUI 应用的标准消息循环结构:

    // Win32 GUI 应用的核心消息循环
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow) {
    // 1. 注册窗口类
    WNDCLASSEX wc = {0};
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.lpfnWndProc = WndProc; // 窗口过程函数指针
    wc.hInstance = hInstance;
    wc.lpszClassName = "MyWindowClass";
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    RegisterClassEx(&wc);

    // 2. 创建窗口
    HWND hwnd = CreateWindowEx(
    0, "MyWindowClass", "My Application",
    WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,
    NULL, NULL, hInstance, NULL);

    // 3. 显示窗口
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // 4. 消息循环 —— GUI 应用的核心引擎
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0) > 0) {
    TranslateMessage(&msg); // 将虚拟键消息转换为字符消息
    DispatchMessage(&msg); // 分发消息到窗口过程
    }

    return (int)msg.wParam;
    }

    // 窗口过程函数 —— 处理所有发送到窗口的消息
    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
    case WM_CREATE:
    // 窗口创建时的初始化
    break;
    case WM_PAINT: {
    // 绘制窗口内容
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hwnd, &ps);
    TextOut(hdc, 10, 10, "Hello, Windows!", 15);
    EndPaint(hwnd, &ps);
    break;
    }
    case WM_DESTROY:
    PostQuitMessage(0); // 向消息队列发送 WM_QUIT
    break;
    default:
    return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
    }

    2.2.4 消息循环机制详解

    消息循环是 GUI 桌面应用的核心运行机制。理解消息循环对于理解 Windows GUI 应用的行为至关重要:

    #mermaid-svg-GnrSWW677KU3OjGV{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-GnrSWW677KU3OjGV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-GnrSWW677KU3OjGV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-GnrSWW677KU3OjGV .error-icon{fill:#552222;}#mermaid-svg-GnrSWW677KU3OjGV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-GnrSWW677KU3OjGV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-GnrSWW677KU3OjGV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-GnrSWW677KU3OjGV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-GnrSWW677KU3OjGV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-GnrSWW677KU3OjGV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-GnrSWW677KU3OjGV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-GnrSWW677KU3OjGV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-GnrSWW677KU3OjGV .marker.cross{stroke:#333333;}#mermaid-svg-GnrSWW677KU3OjGV svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-GnrSWW677KU3OjGV p{margin:0;}#mermaid-svg-GnrSWW677KU3OjGV .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-GnrSWW677KU3OjGV .cluster-label text{fill:#333;}#mermaid-svg-GnrSWW677KU3OjGV .cluster-label span{color:#333;}#mermaid-svg-GnrSWW677KU3OjGV .cluster-label span p{background-color:transparent;}#mermaid-svg-GnrSWW677KU3OjGV .label text,#mermaid-svg-GnrSWW677KU3OjGV span{fill:#333;color:#333;}#mermaid-svg-GnrSWW677KU3OjGV .node rect,#mermaid-svg-GnrSWW677KU3OjGV .node circle,#mermaid-svg-GnrSWW677KU3OjGV .node ellipse,#mermaid-svg-GnrSWW677KU3OjGV .node polygon,#mermaid-svg-GnrSWW677KU3OjGV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-GnrSWW677KU3OjGV .rough-node .label text,#mermaid-svg-GnrSWW677KU3OjGV .node .label text,#mermaid-svg-GnrSWW677KU3OjGV .image-shape .label,#mermaid-svg-GnrSWW677KU3OjGV .icon-shape .label{text-anchor:middle;}#mermaid-svg-GnrSWW677KU3OjGV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-GnrSWW677KU3OjGV .rough-node .label,#mermaid-svg-GnrSWW677KU3OjGV .node .label,#mermaid-svg-GnrSWW677KU3OjGV .image-shape .label,#mermaid-svg-GnrSWW677KU3OjGV .icon-shape .label{text-align:center;}#mermaid-svg-GnrSWW677KU3OjGV .node.clickable{cursor:pointer;}#mermaid-svg-GnrSWW677KU3OjGV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-GnrSWW677KU3OjGV .arrowheadPath{fill:#333333;}#mermaid-svg-GnrSWW677KU3OjGV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-GnrSWW677KU3OjGV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-GnrSWW677KU3OjGV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GnrSWW677KU3OjGV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-GnrSWW677KU3OjGV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GnrSWW677KU3OjGV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-GnrSWW677KU3OjGV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-GnrSWW677KU3OjGV .cluster text{fill:#333;}#mermaid-svg-GnrSWW677KU3OjGV .cluster span{color:#333;}#mermaid-svg-GnrSWW677KU3OjGV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-GnrSWW677KU3OjGV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-GnrSWW677KU3OjGV rect.text{fill:none;stroke-width:0;}#mermaid-svg-GnrSWW677KU3OjGV .icon-shape,#mermaid-svg-GnrSWW677KU3OjGV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GnrSWW677KU3OjGV .icon-shape p,#mermaid-svg-GnrSWW677KU3OjGV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-GnrSWW677KU3OjGV .icon-shape .label rect,#mermaid-svg-GnrSWW677KU3OjGV .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GnrSWW677KU3OjGV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-GnrSWW677KU3OjGV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-GnrSWW677KU3OjGV :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    窗口处理

    消息循环

    消息队列

    消息来源

    OS 转换

    OS 投递

    PostMessage

    取出一条消息

    根据 HWND

    未处理的消息

    PostQuitMessage

    收到 WM_QUIT

    用户输入键盘/鼠标/触摸

    系统事件计时器/重绘/系统命令

    其他线程/进程PostMessage/SendMessage

    线程消息队列per-thread message queue

    GetMessage()从队列取出消息阻塞等待

    TranslateMessage()键盘消息转换WM_KEYDOWN → WM_CHAR

    DispatchMessage()分发到窗口过程

    WndProc()窗口过程函数

    DefWindowProc()默认处理

    WM_QUIT退出循环

    退出消息循环应用终止

    消息循环的关键细节:

    GetMessage 的阻塞行为:当消息队列为空时,GetMessage() 会使线程进入等待状态,操作系统将该线程从 CPU 调度队列中移除,直到有新消息到达。这意味着空闲的 GUI 应用几乎不消耗 CPU 资源。

    消息的优先级:Windows 消息系统对某些消息有优先级处理。SendMessage() 发送的消息绕过消息队列,直接调用目标窗口的窗口过程函数(称为"同步消息")。而 PostMessage() 投递的消息进入队列,等待 GetMessage() 取出(称为"异步消息")。系统生成的某些高优先级消息(如 WM_PAINT、WM_TIMER)会在队列低优先级位置合成,不会频繁唤醒线程。

    线程亲和性:Windows GUI 具有严格的线程亲和性——窗口的创建线程必须是处理该窗口消息的线程。如果线程 A 创建了一个窗口,线程 B 不能直接调用该窗口的窗口过程,而必须通过 PostMessage 或 SendNotifyMessage 跨线程投递消息。跨线程 SendMessage 会导致发送线程阻塞,直到接收线程在消息循环中处理该消息。

    2.2.5 GUI 技术栈演进

    Windows GUI 开发技术栈经历了多次演进,每一代技术都在前一代的基础上提供了更高层次的抽象:

    技术年代渲染方式编程模型代表应用
    Win32 API 1995 GDI 手动消息循环 + 窗口过程 记事本, 计算器
    MFC 1995 GDI 消息映射宏 + 文档/视图架构 Visual Studio 6.0
    WinForms 2002 GDI+ 事件驱动 + 可视化设计器 早期 .NET 桌面应用
    WPF 2006 DirectX XAML + 数据绑定 + 依赖属性 Visual Studio 2010+
    WinUI 3 2020 DirectX XAML + WinRT 投影 现代 Windows 应用
    Electron 2013 Chromium HTML/CSS/JS + Node.js VS Code, Slack
    Avalonia 2016 Skia/OpenGL XAML + 跨平台 跨平台 .NET 应用
    2.2.6 GUI 应用架构图

    #mermaid-svg-RdKskGtKXWqhSM8x{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-RdKskGtKXWqhSM8x .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-RdKskGtKXWqhSM8x .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-RdKskGtKXWqhSM8x .error-icon{fill:#552222;}#mermaid-svg-RdKskGtKXWqhSM8x .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-RdKskGtKXWqhSM8x .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-RdKskGtKXWqhSM8x .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-RdKskGtKXWqhSM8x .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-RdKskGtKXWqhSM8x .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-RdKskGtKXWqhSM8x .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-RdKskGtKXWqhSM8x .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-RdKskGtKXWqhSM8x .marker{fill:#333333;stroke:#333333;}#mermaid-svg-RdKskGtKXWqhSM8x .marker.cross{stroke:#333333;}#mermaid-svg-RdKskGtKXWqhSM8x svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-RdKskGtKXWqhSM8x p{margin:0;}#mermaid-svg-RdKskGtKXWqhSM8x .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-RdKskGtKXWqhSM8x .cluster-label text{fill:#333;}#mermaid-svg-RdKskGtKXWqhSM8x .cluster-label span{color:#333;}#mermaid-svg-RdKskGtKXWqhSM8x .cluster-label span p{background-color:transparent;}#mermaid-svg-RdKskGtKXWqhSM8x .label text,#mermaid-svg-RdKskGtKXWqhSM8x span{fill:#333;color:#333;}#mermaid-svg-RdKskGtKXWqhSM8x .node rect,#mermaid-svg-RdKskGtKXWqhSM8x .node circle,#mermaid-svg-RdKskGtKXWqhSM8x .node ellipse,#mermaid-svg-RdKskGtKXWqhSM8x .node polygon,#mermaid-svg-RdKskGtKXWqhSM8x .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-RdKskGtKXWqhSM8x .rough-node .label text,#mermaid-svg-RdKskGtKXWqhSM8x .node .label text,#mermaid-svg-RdKskGtKXWqhSM8x .image-shape .label,#mermaid-svg-RdKskGtKXWqhSM8x .icon-shape .label{text-anchor:middle;}#mermaid-svg-RdKskGtKXWqhSM8x .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-RdKskGtKXWqhSM8x .rough-node .label,#mermaid-svg-RdKskGtKXWqhSM8x .node .label,#mermaid-svg-RdKskGtKXWqhSM8x .image-shape .label,#mermaid-svg-RdKskGtKXWqhSM8x .icon-shape .label{text-align:center;}#mermaid-svg-RdKskGtKXWqhSM8x .node.clickable{cursor:pointer;}#mermaid-svg-RdKskGtKXWqhSM8x .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-RdKskGtKXWqhSM8x .arrowheadPath{fill:#333333;}#mermaid-svg-RdKskGtKXWqhSM8x .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-RdKskGtKXWqhSM8x .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-RdKskGtKXWqhSM8x .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-RdKskGtKXWqhSM8x .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-RdKskGtKXWqhSM8x .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-RdKskGtKXWqhSM8x .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-RdKskGtKXWqhSM8x .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-RdKskGtKXWqhSM8x .cluster text{fill:#333;}#mermaid-svg-RdKskGtKXWqhSM8x .cluster span{color:#333;}#mermaid-svg-RdKskGtKXWqhSM8x div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-RdKskGtKXWqhSM8x .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-RdKskGtKXWqhSM8x rect.text{fill:none;stroke-width:0;}#mermaid-svg-RdKskGtKXWqhSM8x .icon-shape,#mermaid-svg-RdKskGtKXWqhSM8x .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-RdKskGtKXWqhSM8x .icon-shape p,#mermaid-svg-RdKskGtKXWqhSM8x .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-RdKskGtKXWqhSM8x .icon-shape .label rect,#mermaid-svg-RdKskGtKXWqhSM8x .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-RdKskGtKXWqhSM8x .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-RdKskGtKXWqhSM8x .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-RdKskGtKXWqhSM8x :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    窗口管理器

    渲染层

    应用框架层

    Windows 消息子系统

    用户交互层

    GetMessage

    GetMessage

    Dispatcher

    Dispatcher

    鼠标输入

    键盘输入

    触摸输入

    拖放操作

    线程消息队列per-thread

    DefWindowProc默认窗口过程

    user32.dll消息分发引擎

    Win32 APIRegisterClass/CreateWindow

    MFCCWnd/CFrameWnd/消息映射

    WPFDispatcherObject/Visual Tree

    WinUI 3XAML/Composition

    GDI/GDI+2D 图形绘制

    DirectComposition合成引擎

    DirectX/Direct2D硬件加速渲染

    桌面窗口管理器dwm.exe

    GPU 合成

    屏幕显示

    2.2.7 GUI 应用的 STA 线程要求

    .NET GUI 应用(WinForms 和 WPF)的入口点必须标记 [STAThread] 属性:

    // WinForms 入口
    [STAThread]
    static void Main() {
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new MainForm());
    }

    // WPF 入口(自动生成,App.xaml)
    // WPF 的 Dispatcher 自动在 STA 线程上运行
    public partial class App : Application {
    // WPF 强制 UI 线程为 STA
    }

    [STAThread] 指示 CLR 将主线程初始化为单线程单元(Single-Threaded Apartment)。STA 是 COM 的线程模型,Windows GUI 的底层(OLE 剪贴板、拖放、Shell 对话框等)依赖 COM STA。如果 UI 线程运行在 MTA(多线程单元)中,这些 COM 组件将无法正确初始化,导致拖放功能失效、文件对话框崩溃等问题。

    2.3 Windows 服务(Windows Service)

    2.3.1 核心特征

    Windows 服务是 Windows 平台上专用于后台运行的应用类型,其核心特征如下:

    • 无用户界面:服务运行在 Session 0 中,与用户会话(Session 1+)隔离,无法显示任何 GUI 元素。
    • 入口函数:C/C++ 中为 ServiceMain();.NET 中通过 ServiceBase 类的 OnStart() / OnStop() 方法。
    • SCM 注册:服务必须在服务控制管理器(Service Control Manager, SCM)中注册,由 services.exe 进程管理。
    • 自动启动:可在系统启动时自动运行,无需用户登录。
    • 身份灵活:可配置为以 LocalSystem、LocalService、NetworkService 或特定域账户身份运行。
    • 长时间运行:设计为 7×24 小时持续运行,需具备异常恢复和自动重启能力。
    2.3.2 服务控制管理器(SCM)

    SCM 是 Windows 服务的基础设施,由 services.exe 进程承载。SCM 负责:

  • 维护已安装服务的注册表数据库(HKLM\\SYSTEM\\CurrentControlSet\\Services\\)
  • 在系统启动或手动触发时启动服务
  • 接收服务状态变更通知并向服务发送控制命令
  • 管理服务的恢复策略和依赖关系
  • 2.3.3 服务注册与服务主函数

    C/C++ Windows 服务的标准结构:

    // 服务名称和显示名称
    #define SERVICE_NAME L"MyDataService"
    #define SERVICE_DISPLAY_NAME L"My Data Synchronization Service"

    // 全局变量
    SERVICE_STATUS g_ServiceStatus = {0};
    SERVICE_STATUS_HANDLE g_StatusHandle = NULL;
    HANDLE g_ServiceStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

    // 服务主函数 —— 服务的真正入口点
    VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv) {
    // 1. 注册服务控制处理函数
    g_StatusHandle = RegisterServiceCtrlHandler(
    SERVICE_NAME, ServiceCtrlHandler);

    // 2. 报告 SERVICE_START_PENDING 状态
    g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
    g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
    g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
    SERVICE_ACCEPT_SHUTDOWN;
    g_ServiceStatus.dwCheckPoint = 1;
    g_ServiceStatus.dwWaitHint = 3000; // 预计 3 秒内完成启动
    SetServiceStatus(g_StatusHandle, &g_ServiceStatus);

    // 3. 执行初始化工作
    // … 初始化资源、连接数据库、打开端口等 …

    // 4. 报告 SERVICE_RUNNING 状态
    g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
    g_ServiceStatus.dwCheckPoint = 0;
    g_ServiceStatus.dwWaitHint = 0;
    SetServiceStatus(g_StatusHandle, &g_ServiceStatus);

    // 5. 等待停止事件
    WaitForSingleObject(g_ServiceStopEvent, INFINITE);

    // 6. 清理并报告 SERVICE_STOPPED
    g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
    SetServiceStatus(g_StatusHandle, &g_ServiceStatus);
    }

    // 服务控制处理函数 —— 响应 SCM 的控制命令
    VOID WINAPI ServiceCtrlHandler(DWORD ctrlCode) {
    switch (ctrlCode) {
    case SERVICE_CONTROL_STOP:
    // 报告正在停止
    g_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
    g_ServiceStatus.dwCheckPoint = 1;
    g_ServiceStatus.dwWaitHint = 5000;
    SetServiceStatus(g_StatusHandle, &g_ServiceStatus);
    // 触发停止事件
    SetEvent(g_ServiceStopEvent);
    break;
    case SERVICE_CONTROL_SHUTDOWN:
    // 系统关机
    SetEvent(g_ServiceStopEvent);
    break;
    case SERVICE_CONTROL_INTERROGATE:
    // SCM 查询当前状态
    SetServiceStatus(g_StatusHandle, &g_ServiceStatus);
    break;
    }
    }

    // 进程主函数 —— 注册服务入口
    int main() {
    SERVICE_TABLE_ENTRY serviceTable[] = {
    {SERVICE_NAME, ServiceMain},
    {NULL, NULL}
    };

    // 启动服务分发器 —— 阻塞直到所有服务停止
    if (!StartServiceCtrlDispatcher(serviceTable)) {
    // 错误处理
    return GetLastError();
    }
    return 0;
    }

    2.3.4 .NET Windows 服务

    在 .NET 中,使用 System.ServiceProcess.ServiceBase 简化服务开发:

    // .NET Framework Windows 服务
    public class MyDataService : ServiceBase {
    private Timer _workTimer;

    public MyDataService() {
    ServiceName = "MyDataService";
    CanStop = true;
    CanPauseAndContinue = false;
    AutoLog = true;
    }

    protected override void OnStart(string[] args) {
    // SCM 调用此方法启动服务
    _workTimer = new Timer(WorkCallback, null, 0, 60000);
    }

    protected override void OnStop() {
    // SCM 调用此方法停止服务
    _workTimer?.Dispose();
    }

    private void WorkCallback(object state) {
    // 执行实际工作
    try {
    SyncDataFromRemote();
    } catch (Exception ex) {
    EventLog.WriteEntry(ServiceName,
    $"Work failed: {ex.Message}",
    EventLogEntryType.Error);
    }
    }

    static void Main() {
    ServiceBase[] services = { new MyDataService() };
    ServiceBase.Run(services);
    }
    }

    在 .NET 6+ 中,推荐使用 BackgroundService + IHost 模式作为 Windows 服务的现代替代方案:

    // .NET 6+ Worker Service 注册为 Windows 服务
    public class DataSyncWorker : BackgroundService {
    protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
    while (!stoppingToken.IsCancellationRequested) {
    await SyncDataAsync();
    await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
    }
    }
    }

    // Program.cs
    var builder = Host.CreateApplicationBuilder(args);
    builder.Services.AddHostedService<DataSyncWorker>();
    builder.Services.AddWindowsService(options => {
    options.ServiceName = "My Data Sync Service";
    });
    var host = builder.Build();
    host.Run();

    2.3.5 服务生命周期

    #mermaid-svg-Eww2H4Tk1oUKEVXw{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Eww2H4Tk1oUKEVXw .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Eww2H4Tk1oUKEVXw .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Eww2H4Tk1oUKEVXw .error-icon{fill:#552222;}#mermaid-svg-Eww2H4Tk1oUKEVXw .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Eww2H4Tk1oUKEVXw .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Eww2H4Tk1oUKEVXw .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Eww2H4Tk1oUKEVXw .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Eww2H4Tk1oUKEVXw .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Eww2H4Tk1oUKEVXw .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Eww2H4Tk1oUKEVXw .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Eww2H4Tk1oUKEVXw .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Eww2H4Tk1oUKEVXw .marker.cross{stroke:#333333;}#mermaid-svg-Eww2H4Tk1oUKEVXw svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Eww2H4Tk1oUKEVXw p{margin:0;}#mermaid-svg-Eww2H4Tk1oUKEVXw defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-Eww2H4Tk1oUKEVXw g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-Eww2H4Tk1oUKEVXw g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-Eww2H4Tk1oUKEVXw g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-Eww2H4Tk1oUKEVXw g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-Eww2H4Tk1oUKEVXw g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-Eww2H4Tk1oUKEVXw .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-Eww2H4Tk1oUKEVXw .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-Eww2H4Tk1oUKEVXw .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-Eww2H4Tk1oUKEVXw .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-Eww2H4Tk1oUKEVXw .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-Eww2H4Tk1oUKEVXw .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-Eww2H4Tk1oUKEVXw .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-Eww2H4Tk1oUKEVXw .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Eww2H4Tk1oUKEVXw .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Eww2H4Tk1oUKEVXw .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Eww2H4Tk1oUKEVXw .edgeLabel .label text{fill:#333;}#mermaid-svg-Eww2H4Tk1oUKEVXw .label div .edgeLabel{color:#333;}#mermaid-svg-Eww2H4Tk1oUKEVXw .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-Eww2H4Tk1oUKEVXw .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-Eww2H4Tk1oUKEVXw .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-Eww2H4Tk1oUKEVXw .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-Eww2H4Tk1oUKEVXw .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-Eww2H4Tk1oUKEVXw .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Eww2H4Tk1oUKEVXw .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Eww2H4Tk1oUKEVXw #statediagram-barbEnd{fill:#333333;}#mermaid-svg-Eww2H4Tk1oUKEVXw .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Eww2H4Tk1oUKEVXw .cluster-label,#mermaid-svg-Eww2H4Tk1oUKEVXw .nodeLabel{color:#131300;}#mermaid-svg-Eww2H4Tk1oUKEVXw .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-Eww2H4Tk1oUKEVXw .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-Eww2H4Tk1oUKEVXw .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-Eww2H4Tk1oUKEVXw .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-Eww2H4Tk1oUKEVXw .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-Eww2H4Tk1oUKEVXw .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-Eww2H4Tk1oUKEVXw .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-Eww2H4Tk1oUKEVXw .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-Eww2H4Tk1oUKEVXw .note-edge{stroke-dasharray:5;}#mermaid-svg-Eww2H4Tk1oUKEVXw .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-Eww2H4Tk1oUKEVXw .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-Eww2H4Tk1oUKEVXw .statediagram-note text{fill:black;}#mermaid-svg-Eww2H4Tk1oUKEVXw .statediagram-note .nodeLabel{color:black;}#mermaid-svg-Eww2H4Tk1oUKEVXw .statediagram .edgeLabel{color:red;}#mermaid-svg-Eww2H4Tk1oUKEVXw #dependencyStart,#mermaid-svg-Eww2H4Tk1oUKEVXw #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-Eww2H4Tk1oUKEVXw .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Eww2H4Tk1oUKEVXw :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    sc create / installutil

    sc start / SCM 自动启动

    ServiceMain 初始化完成报告 SERVICE_RUNNING

    初始化失败报告 SERVICE_STOPPED

    SERVICE_CONTROL_PAUSE

    报告 SERVICE_PAUSED

    SERVICE_CONTROL_CONTINUE

    sc stop / SERVICE_CONTROL_STOP

    报告 SERVICE_STOPPED

    系统关机 / SERVICE_CONTROL_SHUTDOWN

    手动重启 / 恢复策略触发

    sc delete

    已安装

    启动中

    运行中

    启动失败

    暂停中

    已暂停

    停止中

    已停止

    状态: SERVICE_START_PENDING必须设置 dwWaitHint定期更新 dwCheckPoint

    状态: SERVICE_RUNNING可接受: STOP, SHUTDOWN可选: PAUSE, CONTINUE

    状态: SERVICE_STOP_PENDING必须设置 dwWaitHint清理资源后报告 STOPPED

    2.3.6 Session 0 隔离

    从 Windows Vista 开始,所有 Windows 服务运行在 Session 0 中,而用户会话从 Session 1 开始。这一隔离机制称为 Session 0 Isolation,其目的是防止服务中的代码利用用户界面对话框进行"Shatter Attack"。

    Session 0 隔离的关键影响:

    • 服务不能显示 UI:服务调用 MessageBox() 或 CreateWindow() 创建的窗口在 Session 0 中,用户无法看到。系统会弹出一个"交互式服务检测"通知,提示用户切换到 Session 0 查看服务窗口(但这不是正常的使用方式)。
    • 服务不能与用户桌面交互:服务的窗口句柄、剪贴板操作和 Shell 通知对用户会话不可见。
    • 服务与用户进程通信必须使用跨会话 IPC:命名管道、套接字、RPC 等机制可以跨越会话边界,是服务与用户进程通信的标准方式。

    #mermaid-svg-wie4HUjBB0Jv5onU{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-wie4HUjBB0Jv5onU .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-wie4HUjBB0Jv5onU .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-wie4HUjBB0Jv5onU .error-icon{fill:#552222;}#mermaid-svg-wie4HUjBB0Jv5onU .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-wie4HUjBB0Jv5onU .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-wie4HUjBB0Jv5onU .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-wie4HUjBB0Jv5onU .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-wie4HUjBB0Jv5onU .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-wie4HUjBB0Jv5onU .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-wie4HUjBB0Jv5onU .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-wie4HUjBB0Jv5onU .marker{fill:#333333;stroke:#333333;}#mermaid-svg-wie4HUjBB0Jv5onU .marker.cross{stroke:#333333;}#mermaid-svg-wie4HUjBB0Jv5onU svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-wie4HUjBB0Jv5onU p{margin:0;}#mermaid-svg-wie4HUjBB0Jv5onU .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-wie4HUjBB0Jv5onU .cluster-label text{fill:#333;}#mermaid-svg-wie4HUjBB0Jv5onU .cluster-label span{color:#333;}#mermaid-svg-wie4HUjBB0Jv5onU .cluster-label span p{background-color:transparent;}#mermaid-svg-wie4HUjBB0Jv5onU .label text,#mermaid-svg-wie4HUjBB0Jv5onU span{fill:#333;color:#333;}#mermaid-svg-wie4HUjBB0Jv5onU .node rect,#mermaid-svg-wie4HUjBB0Jv5onU .node circle,#mermaid-svg-wie4HUjBB0Jv5onU .node ellipse,#mermaid-svg-wie4HUjBB0Jv5onU .node polygon,#mermaid-svg-wie4HUjBB0Jv5onU .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-wie4HUjBB0Jv5onU .rough-node .label text,#mermaid-svg-wie4HUjBB0Jv5onU .node .label text,#mermaid-svg-wie4HUjBB0Jv5onU .image-shape .label,#mermaid-svg-wie4HUjBB0Jv5onU .icon-shape .label{text-anchor:middle;}#mermaid-svg-wie4HUjBB0Jv5onU .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-wie4HUjBB0Jv5onU .rough-node .label,#mermaid-svg-wie4HUjBB0Jv5onU .node .label,#mermaid-svg-wie4HUjBB0Jv5onU .image-shape .label,#mermaid-svg-wie4HUjBB0Jv5onU .icon-shape .label{text-align:center;}#mermaid-svg-wie4HUjBB0Jv5onU .node.clickable{cursor:pointer;}#mermaid-svg-wie4HUjBB0Jv5onU .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-wie4HUjBB0Jv5onU .arrowheadPath{fill:#333333;}#mermaid-svg-wie4HUjBB0Jv5onU .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-wie4HUjBB0Jv5onU .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-wie4HUjBB0Jv5onU .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wie4HUjBB0Jv5onU .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-wie4HUjBB0Jv5onU .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wie4HUjBB0Jv5onU .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-wie4HUjBB0Jv5onU .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-wie4HUjBB0Jv5onU .cluster text{fill:#333;}#mermaid-svg-wie4HUjBB0Jv5onU .cluster span{color:#333;}#mermaid-svg-wie4HUjBB0Jv5onU div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-wie4HUjBB0Jv5onU .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-wie4HUjBB0Jv5onU rect.text{fill:none;stroke-width:0;}#mermaid-svg-wie4HUjBB0Jv5onU .icon-shape,#mermaid-svg-wie4HUjBB0Jv5onU .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wie4HUjBB0Jv5onU .icon-shape p,#mermaid-svg-wie4HUjBB0Jv5onU .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-wie4HUjBB0Jv5onU .icon-shape .label rect,#mermaid-svg-wie4HUjBB0Jv5onU .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wie4HUjBB0Jv5onU .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-wie4HUjBB0Jv5onU .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-wie4HUjBB0Jv5onU :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    跨会话通信

    Session 2(第二个用户会话)

    Session 1(第一个用户会话)

    Session 0(服务会话)

    无法直接显示 UI

    services.exe服务控制管理器

    MyService.exeWindows 服务

    Spooler.exe打印后台处理

    wuauserv.exeWindows Update

    explorer.exe用户桌面

    MyApp.exe用户应用

    explorer.exe另一个用户桌面

    MyApp.exe另一个用户的应用

    命名管道\\\\\\\\.\\\\pipe\\\\MyService

    TCP Socketlocalhost:port

    RPC 接口

    2.3.7 服务的恢复策略

    SCM 支持配置服务失败时的自动恢复策略:

    恢复操作说明配置方式
    不操作 不执行任何恢复 sc failure svc set actions=none
    重启服务 重新启动服务进程 sc failure svc set actions=restart
    运行程序 执行指定的恢复程序 sc failure svc set command=recovery.exe
    重启计算机 强制重启系统 sc failure svc set actions=reboot

    恢复策略可以针对第一次失败、第二次失败和后续失败分别配置不同的操作,并设置恢复延迟:

    # 配置服务恢复策略的命令行示例
    sc failure "MyDataService" reset= 86400 actions= restart/60000/restart/60000/reboot/120000
    # 含义:失败计数器 24 小时后重置
    # 第一次失败:60 秒后重启服务
    # 第二次失败:60 秒后重启服务
    # 后续失败:120 秒后重启计算机

    2.4 UWP 应用(Universal Windows Platform)

    2.4.1 核心特征

    UWP(通用 Windows 平台)是 Windows 10 引入的现代应用模型,其核心特征如下:

    • 沙箱运行:UWP 应用运行在 AppContainer 轻量级沙箱中,文件系统、注册表和网络访问受到严格限制。
    • AppX/MSIX 打包:应用以 AppX 或 MSIX 包格式分发,包含应用清单(AppxManifest.xml)声明能力(Capabilities)和扩展。
    • WinRT API:使用 Windows 运行时(Windows Runtime)API,这是一组基于 COM 的现代 API,支持多种语言投影(C#, C++/WinRT, JavaScript)。
    • 生命周期管理:系统主动管理应用生命周期,包括挂起(Suspend)、恢复(Resume)和终止(Terminate)。
    • 跨设备:同一应用可运行在 PC、平板、Xbox、HoloLens 等设备上。
    • Store 分发:主要通过 Microsoft Store 分发,支持自动更新。
    2.4.2 UWP 应用生命周期

    UWP 应用的生命周期与传统桌面应用有根本性不同。系统在资源压力或用户切换时主动挂起应用,而非保持其持续运行:

    #mermaid-svg-Zrq3XMU10g71rlii{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Zrq3XMU10g71rlii .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Zrq3XMU10g71rlii .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Zrq3XMU10g71rlii .error-icon{fill:#552222;}#mermaid-svg-Zrq3XMU10g71rlii .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Zrq3XMU10g71rlii .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Zrq3XMU10g71rlii .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Zrq3XMU10g71rlii .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Zrq3XMU10g71rlii .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Zrq3XMU10g71rlii .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Zrq3XMU10g71rlii .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Zrq3XMU10g71rlii .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Zrq3XMU10g71rlii .marker.cross{stroke:#333333;}#mermaid-svg-Zrq3XMU10g71rlii svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Zrq3XMU10g71rlii p{margin:0;}#mermaid-svg-Zrq3XMU10g71rlii defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-Zrq3XMU10g71rlii g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-Zrq3XMU10g71rlii g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-Zrq3XMU10g71rlii g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-Zrq3XMU10g71rlii g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-Zrq3XMU10g71rlii g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-Zrq3XMU10g71rlii .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-Zrq3XMU10g71rlii .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-Zrq3XMU10g71rlii .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-Zrq3XMU10g71rlii .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-Zrq3XMU10g71rlii .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-Zrq3XMU10g71rlii .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-Zrq3XMU10g71rlii .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-Zrq3XMU10g71rlii .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Zrq3XMU10g71rlii .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Zrq3XMU10g71rlii .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Zrq3XMU10g71rlii .edgeLabel .label text{fill:#333;}#mermaid-svg-Zrq3XMU10g71rlii .label div .edgeLabel{color:#333;}#mermaid-svg-Zrq3XMU10g71rlii .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-Zrq3XMU10g71rlii .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-Zrq3XMU10g71rlii .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-Zrq3XMU10g71rlii .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-Zrq3XMU10g71rlii .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-Zrq3XMU10g71rlii .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Zrq3XMU10g71rlii .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Zrq3XMU10g71rlii #statediagram-barbEnd{fill:#333333;}#mermaid-svg-Zrq3XMU10g71rlii .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Zrq3XMU10g71rlii .cluster-label,#mermaid-svg-Zrq3XMU10g71rlii .nodeLabel{color:#131300;}#mermaid-svg-Zrq3XMU10g71rlii .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-Zrq3XMU10g71rlii .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-Zrq3XMU10g71rlii .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-Zrq3XMU10g71rlii .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-Zrq3XMU10g71rlii .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-Zrq3XMU10g71rlii .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-Zrq3XMU10g71rlii .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-Zrq3XMU10g71rlii .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-Zrq3XMU10g71rlii .note-edge{stroke-dasharray:5;}#mermaid-svg-Zrq3XMU10g71rlii .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-Zrq3XMU10g71rlii .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-Zrq3XMU10g71rlii .statediagram-note text{fill:black;}#mermaid-svg-Zrq3XMU10g71rlii .statediagram-note .nodeLabel{color:black;}#mermaid-svg-Zrq3XMU10g71rlii .statediagram .edgeLabel{color:red;}#mermaid-svg-Zrq3XMU10g71rlii #dependencyStart,#mermaid-svg-Zrq3XMU10g71rlii #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-Zrq3XMU10g71rlii .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Zrq3XMU10g71rlii :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    安装/未启动

    用户启动 / 协议激活

    应用初始化完成

    用户最小化 / 切换到其他应用

    用户切回应用

    系统资源不足 / 用户关闭

    系统关机

    用户关闭应用

    资源回收

    后台任务触发 / Toast 激活

    未运行

    启动

    运行中

    挂起

    终止

    状态: Active可访问所有资源CPU 正常调度

    状态: Suspended不消耗 CPU内存保留(可能被压缩)必须保存状态

    状态: Terminated内存释放下次启动需恢复状态

    UWP 应用的生命周期管理通过 Application 类的事件来处理:

    // UWP 应用生命周期处理
    public sealed partial class App : Application {
    public App() {
    InitializeComponent();
    Suspending += OnSuspending;
    Resuming += OnResuming;
    }

    protected override void OnLaunched(LaunchActivatedEventArgs e) {
    // 应用启动/恢复时创建主窗口
    var rootFrame = Window.Current.Content as Frame;
    if (rootFrame == null) {
    rootFrame = new Frame();
    // 检查是否有之前挂起时保存的状态
    if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) {
    // 从本地存储恢复状态
    RestoreState();
    }
    Window.Current.Content = rootFrame;
    }
    if (e.PrelaunchActivated == false) {
    rootFrame.Navigate(typeof(MainPage), e.Arguments);
    Window.Current.Activate();
    }
    }

    private void OnSuspending(object sender, SuspendingEventArgs e) {
    var deferral = e.SuspendingOperation.GetDeferral();
    // 保存应用状态到本地存储
    SaveState();
    deferral.Complete();
    }

    private void OnResuming(object sender, object e) {
    // 应用从挂起状态恢复
    // 刷新数据、恢复网络连接等
    RefreshData();
    }
    }

    2.4.3 AppContainer 沙箱模型

    UWP 应用运行在 AppContainer 执行环境中,这是一个基于 Windows 安全令牌和完整性级别的轻量级沙箱:

    渲染错误: Mermaid 渲染失败: Parse error on line 7: …写" "
    %LOCALAPPDATA%\\… ———————-^ Expecting 'SQE', 'DOUBLECIRCLEEND', 'PE', '-)', 'STADIUMEND', 'SUBROUTINEEND', 'PIPE', 'CYLINDEREND', 'DIAMOND_STOP', 'TAGEND', 'TRAPEND', 'INVTRAPEND', 'UNICODE_TEXT', 'TEXT', 'TAGSTART', got 'STR'

    AppContainer 沙箱的核心安全机制:

  • 低完整性级别:UWP 应用进程运行在低完整性级别(Low Integrity Level),不能写入中完整性或高完整性级别的对象(如系统目录、其他进程的窗口)。
  • 能力令牌:每个 UWP 应用进程的安全令牌中包含 AppContainer SID 和能力 SID。只有当目标资源的安全描述符允许相应的能力 SID 访问时,应用才能访问该资源。
  • 命名空间隔离:UWP 应用创建的命名内核对象(如互斥量、事件)被隔离在应用的命名空间中,其他 UWP 应用无法直接访问。
  • ** broker 进程**:当 UWP 应用需要访问声明能力之外的资源(如用户选择的文件)时,通过 broker 进序(RuntimeBroker.exe)代理访问,确保访问经过用户同意。
  • 2.4.4 WinRT API 架构

    WinRT(Windows Runtime)是 UWP 的 API 基础,它是一组基于现代 COM 的 API,通过语言投影(Language Projection)支持多种编程语言:

    #mermaid-svg-EpX6VapDIGDmcWj5{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-EpX6VapDIGDmcWj5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-EpX6VapDIGDmcWj5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-EpX6VapDIGDmcWj5 .error-icon{fill:#552222;}#mermaid-svg-EpX6VapDIGDmcWj5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-EpX6VapDIGDmcWj5 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-EpX6VapDIGDmcWj5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-EpX6VapDIGDmcWj5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-EpX6VapDIGDmcWj5 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-EpX6VapDIGDmcWj5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-EpX6VapDIGDmcWj5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-EpX6VapDIGDmcWj5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-EpX6VapDIGDmcWj5 .marker.cross{stroke:#333333;}#mermaid-svg-EpX6VapDIGDmcWj5 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-EpX6VapDIGDmcWj5 p{margin:0;}#mermaid-svg-EpX6VapDIGDmcWj5 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-EpX6VapDIGDmcWj5 .cluster-label text{fill:#333;}#mermaid-svg-EpX6VapDIGDmcWj5 .cluster-label span{color:#333;}#mermaid-svg-EpX6VapDIGDmcWj5 .cluster-label span p{background-color:transparent;}#mermaid-svg-EpX6VapDIGDmcWj5 .label text,#mermaid-svg-EpX6VapDIGDmcWj5 span{fill:#333;color:#333;}#mermaid-svg-EpX6VapDIGDmcWj5 .node rect,#mermaid-svg-EpX6VapDIGDmcWj5 .node circle,#mermaid-svg-EpX6VapDIGDmcWj5 .node ellipse,#mermaid-svg-EpX6VapDIGDmcWj5 .node polygon,#mermaid-svg-EpX6VapDIGDmcWj5 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-EpX6VapDIGDmcWj5 .rough-node .label text,#mermaid-svg-EpX6VapDIGDmcWj5 .node .label text,#mermaid-svg-EpX6VapDIGDmcWj5 .image-shape .label,#mermaid-svg-EpX6VapDIGDmcWj5 .icon-shape .label{text-anchor:middle;}#mermaid-svg-EpX6VapDIGDmcWj5 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-EpX6VapDIGDmcWj5 .rough-node .label,#mermaid-svg-EpX6VapDIGDmcWj5 .node .label,#mermaid-svg-EpX6VapDIGDmcWj5 .image-shape .label,#mermaid-svg-EpX6VapDIGDmcWj5 .icon-shape .label{text-align:center;}#mermaid-svg-EpX6VapDIGDmcWj5 .node.clickable{cursor:pointer;}#mermaid-svg-EpX6VapDIGDmcWj5 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-EpX6VapDIGDmcWj5 .arrowheadPath{fill:#333333;}#mermaid-svg-EpX6VapDIGDmcWj5 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-EpX6VapDIGDmcWj5 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-EpX6VapDIGDmcWj5 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-EpX6VapDIGDmcWj5 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-EpX6VapDIGDmcWj5 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-EpX6VapDIGDmcWj5 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-EpX6VapDIGDmcWj5 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-EpX6VapDIGDmcWj5 .cluster text{fill:#333;}#mermaid-svg-EpX6VapDIGDmcWj5 .cluster span{color:#333;}#mermaid-svg-EpX6VapDIGDmcWj5 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-EpX6VapDIGDmcWj5 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-EpX6VapDIGDmcWj5 rect.text{fill:none;stroke-width:0;}#mermaid-svg-EpX6VapDIGDmcWj5 .icon-shape,#mermaid-svg-EpX6VapDIGDmcWj5 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-EpX6VapDIGDmcWj5 .icon-shape p,#mermaid-svg-EpX6VapDIGDmcWj5 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-EpX6VapDIGDmcWj5 .icon-shape .label rect,#mermaid-svg-EpX6VapDIGDmcWj5 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-EpX6VapDIGDmcWj5 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-EpX6VapDIGDmcWj5 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-EpX6VapDIGDmcWj5 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    WinRT 系统实现

    WinRT API 模块

    WinRT 运行时

    语言投影层

    C# 投影WinRT.Interop / CsWinRT

    C++/WinRT头文件投影

    JavaScript 投影WinJS

    Rust 投影windows-rs crate

    WinMD 元数据Windows.winmd

    激活工厂RoGetActivationFactory

    跨语言封送HSTRING / IInspectable

    Windows.UIXAML/控件/输入

    Windows.DataJson/Xml/Text

    Windows.Storage文件/文件夹/流

    Windows.NetworkingSockets/BackgroundTransfer

    Windows.DevicesGPIO/I2C/Bluetooth

    Windows.Media播放/捕获/效果

    Windows.SecurityCryptography/Authentication

    COM 基础IUnknown/IInspectable

    Win32 桥接API 内部调用 Win32

    内核/系统服务syscall

    2.4.5 MSIX 打包格式

    UWP 应用以及现代 Win32 桌面应用(通过桌面桥接 Desktop Bridge)可以使用 MSIX 格式打包。MSIX 包的结构如下:

    MyApp.msix (ZIP 格式)
    ├── AppxManifest.xml # 应用清单(必需)
    ├── AppxBlockMap.xml # 文件块映射(用于增量下载)
    ├── AppxSignature.p7x # 数字签名
    ├── [content_types].xml # MIME 类型映射
    ├── MyApp.exe # 主可执行文件
    ├── MyApp.dll # 应用 DLL
    ├── Assets/ # 图标/启动画面资源
    │ ├── Square150x150Logo.png
    │ ├── Square44x44Logo.png
    │ └── StoreLogo.png
    ├── Resources/ # 本地化资源
    │ ├── en-us/
    │ │ └── Resources.pri
    │ └── zh-cn/
    │ └── Resources.pri
    └── Resources.pri # 资源索引(PRI 文件)

    AppxManifest.xml 的核心结构:

    <?xml version="1.0" encoding="utf-8"?>
    <Package
    xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
    xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
    xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
    xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities">

    <Identity Name="com.contoso.myapp"
    Publisher="CN=Contoso Inc."
    Version="1.0.0.0"
    ProcessorArchitecture="x64"/>

    <mp:PhoneIdentity PhoneProductId="guid-here" PhonePublisherId="guid-here"/>

    <Properties>
    <DisplayName>My App</DisplayName>
    <PublisherDisplayName>Contoso Inc.</PublisherDisplayName>
    <Logo>Assets\\StoreLogo.png</Logo>
    </Properties>

    <Resources>
    <Resource Language="en-us"/>
    <Resource Language="zh-cn"/>
    </Resources>

    <Dependencies>
    <TargetDeviceFamily Name="Windows.Desktop"
    MinVersion="10.0.19041.0"
    MaxVersionTested="10.0.22000.0"/>

    </Dependencies>

    <Applications>
    <Application Id="App"
    Executable="MyApp.exe"
    EntryPoint="Windows.FullTrustApplication">

    <uap:VisualElements
    DisplayName="My App"
    Description="My Application"
    BackgroundColor="transparent"
    Square150x150Logo="Assets\\Square150x150Logo.png"
    Square44x44Logo="Assets\\Square44x44Logo.png">

    <uap:SplashScreen Image="Assets\\SplashScreen.png"/>
    </uap:VisualElements>
    </Application>
    </Applications>

    <Capabilities>
    <uap:Capability Name="internetClient"/>
    <uap:Capability Name="documentsLibrary"/>
    <DeviceCapability Name="microphone"/>
    <DeviceCapability Name="webcam"/>
    </Capabilities>
    </Package>

    2.5 界面类型分类对比

    特性控制台应用GUI 桌面应用Windows 服务UWP 应用
    PE Subsystem CUI (3) GUI (2) CUI (3) CUI (3)
    入口函数 main() WinMain() ServiceMain() App.OnLaunched()
    用户交互 文本流 窗口/控件 无(SCM 控制) XAML 界面
    Session 用户会话 用户会话 Session 0 用户会话
    自动启动 否 否 是 否
    消息循环 无 有 无(自定义) 有(Dispatcher)
    内存占用 低(1-10MB) 中(10-100MB) 低-中(5-50MB) 中-高(50-200MB)
    安全沙箱 无 无 无 AppContainer
    后台运行 需保持窗口 最小化时仍运行 始终后台运行 挂起/终止

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 02-02 Windows 软件体系 - 应用程序分类体系与多维划分模型(上)
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!