首页
/ PowerToys SCOOBE 升级引导(What's New 对话框):从设计规格到仓库实现

PowerToys SCOOBE 升级引导(What's New 对话框):从设计规格到仓库实现

2026-09-06 18:15:33作者:鲍丁臣Ursa

导读

PowerToys 在每次升级后都会面对一个老问题:用户如何在升级第一时间获知新特性与修复?本文以仓库内《SCOOBE Dialog 设计规格》(Draft 状态,作者 Deondre Davis)为主线,系统讲解 "Second Chance OOBE"(SCOOBE)升级引导的设计目标、功能需求、页面内容组织、度量体系,并结合 ScoobeWindow.xaml.cs 等当前实现源码,剖析它是如何通过 GitHub Releases API 拉取发布数据、按版本分组并以 Markdown 渲染"发布亮点"的。读完本文,你将掌握该对话框从产品规格到工程落地的完整链路,以及其中每个设计决策在代码中的对应物。

1. 背景与动机:为什么需要 SCOOBE

PowerToys 的版本信息(release notes)此前主要发布在主仓库与 Microsoft Docs 上,二者都位于应用之外。这意味着:用户只有主动去查阅才能知道"这个版本改了什么",或者只能在使用中碰巧发现行为变化。规格文档把这类体验归纳为两个痛点:

  • 信息与产品"隔离",升级上下文被打断;
  • 依赖用户主动性与运气,新特性触达率低。

作为应对,PowerToys 希望在升级后启动一个 SCOOBE(Second Chance Out of Box Experience) 对话框,把"最新版本包含哪些新增与改进"以可浏览的形态直接带到用户面前。它与首次安装的 OOBE(Out of Box Experience)同源:首次安装展示 "Welcome to PowerToys",升级之后则展示 "What's New",前者是"第一次机会",后者是"第二次机会"。

规格出处:SCOOBE Dialog 规格文档 第 1.1/1.2 节。

2. 目标与非目标

目标(Goals)

  • 创建一个引导式(guided)对话框,让用户快速浏览当前版本新增的特性与改进概览。

非目标(Non-Goals)

  • 不做成仓库 release notes 的"逐字复制品"。规格明确要求信息必须易于消化,并且需要尽可能附带新行为的可视化演示——而这类视觉内容往往在仓库 release notes 里无法表达或不必要出现。

这一"非目标"在实现里得到了直接体现:渲染层不是简单把 release notes 文本原样铺开,而是做了一系列结构化加工(见第 7.3 节),例如剥离 "Installer Hashes" 段、提取 Hero 图、将 #PR号 自动转为链接等,保证展示内容"可消费"而非"可归档"。

3. 目标用户与成功度量

3.1 目标用户

既有与新增的 power users 和开发者——即那些希望通过调优 Windows 体验提升生产力的人群。规格特别指出:PowerToys 用户群体对 SCOOBE 这类弹窗普遍有抵触情绪,因此对话框必须在第一时间提供可见价值,以提高用户完整走完引导、发现全部新特性的可能性。

3.2 预期的用户与技术成果指标

规格定义了三个量化目标(属于设计文档层面的预期指标,用于度量该功能的成败):

指标 目标值 含义
高可靠性 崩溃率 < 0.1% SCOOBE 展示与浏览过程稳定
激活率提升 已使用相关工具的用户对新增特性/工具的采用率 ≥ 50% What's New 内容确实驱动了新功能的激活
高留存 升级后 28 天内活跃 PowerToys 用户 ≥ 25% SCOOBE 有助于维持长期活跃

3.3 度量需求(Measure Requirements)

为了回答"SCOOBE 是否有效",规格设计了 6 项埋点度量,覆盖用户行为与设备特征:

No. 度量项 设计用途 优先级
1 升级后首次运行的日期/时间 按接触过 SCOOBE 的用户群体归类使用与留存趋势 P0
2 查看过的 SCOOBE 区块(section) 衡量 SCOOBE 对话框激活情况;SCOOBE 上线后当前版本应达到 100% P0
3 对文档链接的访问 评估用户想深入了解的 PowerToys 模块 P1
4 对设置页面的访问 评估对话框中呈现的设置项是否满足用户需要 P1
5 SCOOBE 窗口活跃期间启动的 PowerToys 功能 追踪用户在浏览内容时的实际功能参与度 P1
6 屏幕尺寸 为内容展示所需的最小/最大窗口尺寸提供依据 P2

其中"窗口打开"这一事件在实现中已有对应物:App.xaml.csOpenScoobe() 会先写入遥测事件再创建窗口,相关事件类位于 ScoobeStartedEvent.cs

public void OpenScoobe()
{
    PowerToysTelemetry.Log.WriteEvent(new ScoobeStartedEvent());
    // ... 创建 ScoobeWindow 实例
}

——引自 App.xaml.cs

4. 功能需求规格

4.1 功能需求总览(Functional Requirements)

SCOOBE 对话框基于已有 OOBE 对话框(最初源自社区的设计草图)扩展而来。规格给出的功能需求如下:

No. 需求 优先级
1 PowerToys 被升级后运行时,SCOOBE 对话框应立即启动 P0
2 SCOOBE 应承载在既有 OOBE 对话框中独立的"What's New"页内(见 mock-up) P0
3 SCOOBE 内容应外置于应用,存放于 PowerToys GitHub 上每个 release 独立的 wiki 页中 P0
4 打开"What's New"页时,内容从上述 wiki 页加载(前提:用户设备联网) P0
6 SCOOBE 展示的是用户已安装/升级到的那一版本所发生的更新 P0
7 若为首次安装,应先展示 OOBE 的"Welcome to PowerToys"页,而非 SCOOBE 的"What's New"页 P0
8 SCOOBE 页面内容结构须遵循下文"页面内容"约束 P0
9 首次查看后,用户仍可随时重新打开 OOBE 窗口并选择"What's New"页再次访问 P1

关于需求 3 的规格注释(重要设计权衡): 内容存放于应用外部,团队便不必被 PowerToys 的发布节奏捆绑,可以在任意时刻更新/修正文案。这对于处理错误表述或信息纠偏尤为关键——若内容随版本打包进本地应用,一旦出错几乎难以在已发布的版本上修正。规格预计内容将以归档形式维护在 PowerToys GitHub Wiki 中。

4.2 页面内容规格(Page Content)

"What's New" 页面的内容组织规则如下:

No. 需求 优先级
1 页面应展示用户已安装的 PowerToys 版本号 P0
2 信息分两个区段:"New Features & Improvements"(新特性与改进)与 "Bug fixes Highlights"(修复亮点) P0
3 新特性与改进区段收录新增/更新的用户功能 P0
4 新特性与改进区段按被更新的实用工具细分(如 Color Picker、FancyZones 等) P1
5 修复亮点区段收录值得注意的已修正问题/错误 P0
6 若有相关可视化素材,应与说明文字一并展示 P1
8 内容超出可视范围时对话框应支持滚动 P0
10 页面底部提供指向 PowerToys releases 页的链接,以查看完整版本列表与发布说明 P1

值得注意:本需求表中的编号 7/9 在规格原文中空缺,属该 Draft 文档的草稿痕迹,不影响对内容约束的理解。

4.3 从"wiki 页存放"到"Releases API 拉取":实现的演进

规格第 4.1 节假设内容存放在 GitHub Wiki 页,而当前仓库的实现改为消费 GitHub Releases APIScoobeWindow.xaml.cs 中通过 HTTP GET 请求 PowerToys 官方仓库的 Releases 端点(per_page=100),把返回 JSON 反序列化为 release 对象列表,再就地加工渲染。每个 release 对象携带正文(release notes 的 Markdown)、版本号、发布日期、预发布标记等字段——TagNameNamePublishedDateReleaseNotesIsPrerelease 均可从源码直接看到被使用。

两者目标一致(内容外置、不随包发布、可随时修订),实现上则把"外置内容"从人维护的 wiki 页换成了"仓库发布物本身",并让应用在本地完成裁剪与再排版。规格文档是 Draft 状态,本文以仓库代码的实际行为为准。

5. 用户价值与适用场景

从产品角度,SCOOBE 面向两类诉求:

  • 升级后发现式引导:升级 PowerToys 后第一次运行即弹出,用户无需离开应用即可了解新东西;
  • 随时回看:错过首次弹窗后,仍可从设置界面等处重新进入 What's New。

规格中的 P0/P1 分级恰好反映这一形态:P0 保证"升级后必达 + 内容正确组织",P1 提供"回访入口 + 低门槛信息分区"。

6. 规格到代码:仓库中的落地实现

规格中的设计在当前仓库已有完整实现。核心组件位于设置 UI 工程:

6.1 入口与启动时机

窗口的启动由命令行参数驱动。App.xaml.cs 中:

  • 解析 ShowScoobeWindow 参数并赋值 ShowScoobe
  • if (!ShowOobe && !ShowScoobe) 区分普通启动(直接进入设置主界面)与需要展示引导窗口的启动;
  • ShowScoobe 为真时调用 OpenScoobe(),先发送 ScoobeStartedEvent 遥测事件,再实例化 ScoobeWindow

这与规格需求 1(升级后立即展示)与需求 7(首次安装展示 Welcome 而非 What's New)对应:首次安装走 OOBE 窗口,升级走 SCOOBE 窗口,二者互斥分流。OOBE 侧的窗口与逐模块视图分别位于 OobeWindow.xamlOOBE/Views 目录(内含每个工具独立的一对 Oobe*.xaml/.cs)。

6.2 窗口结构与取数流程

ScoobeWindow.xaml 是一个基于 WinUIEx.WindowEx 的 WinUI 3 窗口,默认尺寸 1100×700、最小 480×480,使用 MicaBackdrop 背景;ScoobeWindow.xaml.cs 中的加载流程为:

  1. 窗口内 NavigationView_Loaded 触发异步 LoadReleasesAsync()
  2. 显示 LoadingProgressRing,随后调用 FetchReleasesFromGitHubAsync()
  3. 取数使用带系统代理HttpClientDefaultProxyCredentialsWebRequest.GetSystemWebProxy()),请求头设置 User-Agent: PowerToys,向 GitHub Releases API 请求最多 100 条 release;
  4. 通过源生成(source generation)的 JsonSerializer 上下文反序列化 JSON;
  5. 失败时展示 ErrorInfoBar(加载错误 + "重试"按钮),对应规格"需要联网"的前提约束。

6.3 版本分组:NavigationView 左侧导航

CreateReleaseGroups() 实现规格"按版本展示"的诉求:

  • 应显示预发布(用户设置开启 IncludePrereleaseUpdates,或当前自身是 preview 渠道构建),则先把最新的 10 条预发布作为一组放入列表;
  • 稳定的 release 取最近 20 条,按 major.minor(如 0.96)做 GroupBy 聚合成组;
  • 每组对应 ScoobeReleaseGroupViewModel.csVersionTextTagName 去掉前缀 v(如 v0.96.00.96.0),DateText 显示发布日期所在月(如 "December 2025"),预发布组单独标记;
  • 分组结果显示在左侧 NavigationView.MenuItems(日期为主标题、版本为副标题),默认选中第一组。

选中任一版本组后,NavigationFrame.Navigate(typeof(ScoobeReleaseNotesPage), viewModel.Releases) 把该组的所有 release 对象传给内容页——这就是"展示用户升级到的那一版本的更新内容"的数据基础。

6.4 内容页渲染:Markdown 加工流水线

ScoobeReleaseNotesPage.xaml.cs 使用 CommunityToolkit 的 MarkdownTextBlock 渲染,其 ProcessReleaseNotesMarkdown() 对每个 release 正文执行一串正则与文本加工,正好落实规格"不能照搬 release notes、必须易于消费"的非目标:

加工步骤 实现方式 目的
多版本合并 版本间插入 --- 分隔线与空行 一组内可连续浏览多个小版本
预发布标记 追加 Preview 徽章文案 让用户知晓内容对应非稳定版
标题与日期 生成 # {release.Name} + 本地化月份日期 + "View on GitHub" 链接 明确版本与出处
剔除哈希段 正则删除 ## Installer Hashes 及之后内容(分带 ## Highlights 与热修复无 Highlights 两种情形) 展示区不出现安装包哈希等技术噪音
Hero 图提取 正则匹配 alt 文本含 "Hero" 的图片,仅取最后一张置于页首大图位,并从正文移除 兼顾视觉亮点与正文整洁
PR/Issue 链接化 用负向断言 (?<!\[)#(\d+)(?!\]) 将裸 #数字 转为对应 Pull Request 链接 引用可点击、可溯源
主题自愈 由于 MarkdownTextBlock 会把标题/链接画刷锚定在 OS 主题,代码在明暗主题切换时重设 RequestedTheme 并回填标题与链接画刷 保证浅色/深色主题下标题与链接可读

规格 5.1.3 给出的"按工具分组 + 两级列表"文案结构(见第 8 节示例)在真实发布正文中由社区按规范书写,应用侧以 Markdown 原样保留其 ## 分级结构,正文中以 ## New Features & Improvements / ## Bug fixes Highlights 呈现两区段,工具名再作为下级标题细分——与规格 4.2 的内容约束一致。

6.5 回访入口与开关

规格需求 9(可随时重新访问)在 UI 侧有多处入口:

  • 设置主界面 DashboardPage.xaml 提供 "What's new" 按钮;
  • 更新状态控件 UpdateStatusControl.xaml 中的 SeeWhatsNew 按钮(x:Uid="SeeWhatsNew")与 ShellPage.xamlWhatIsNew_NavViewItem 均可再次拉起 What's New 内容;
  • GeneralPage.xaml 提供 "升级后显示 What's new" 复选框(ShowWhatsNewAfterUpdates),允许用户在常规设置中关闭升级后自动弹窗——这与规格中"用户群体对弹窗有抵触"的预期相匹配。

窗口底部还内置"打开设置"入口(Scoobe_OpenSettings 导航项),对应规格"浏览内容后一键进入配置"的体验闭环。

6.6 本地化、测试与既有验证

  • 所有可展示文案均通过 x:Uid 绑定到 en-us/Resources.resw 等语言资源文件(如 ScoobeWindow_TitleOobe_WhatsNew_LoadingErrorScoobe_OpenSettingsScoobeReleaseNotes_PreviewBadgeScoobeReleaseNotes_ViewOnGitHub 等),并经由 ResourceLoaderInstance 读取,天然具备多语言能力;
  • 分组逻辑存在单元测试覆盖:ScoobeReleaseTests.cs
  • 启动遥测事件定义于 ScoobeStartedEvent.cs

7. 内容结构示意(规格示例)

规格 5.1.3 给出了升级内容的结构化示例,展示"What's New"文案应如何组织为"两区段 → 工具 → 要点"的形式。以下为规格原文示例(用于说明文案的书写格式,非当前版本实际内容):

v0.29 → v0.31:

  • New Features & Improvements
    • FancyZones
      • Dark mode for the editor
      • Certain settings(如分区数量、间距设置)现可对单个布局分别设置
    • PowerToys Run
      • 服务管理插件(Start、stop…)
      • 注册表键插件
      • 系统操作插件(Reboot、lock...)
  • Bug fixes Highlights
    • Fixed OneDrive SVG Bug (#9999)
    • SVG 在提供 view box 时按比例缩放 (#9999)

v0.31 → v0.33:

  • New Features & Improvements
    • General
      • 新增"首次加载"体验,以轻量快速的方式了解基础功能
    • FancyZones
      • 新增切换分区激活算法的选项
    • PowerToys Run
      • 插件管理器移入设置,可直接开关、纳入通用搜索、修改 action key
      • 通过抽象 shell 进程调用来改进对其他窗口管理器的支持
      • Folder 插件中 ~ 将解析为用户主目录
  • Bug fixes Highlights
    • 修复 PT Run 在不支持的 OS 版本上注册热键的问题 (#9999)

v0.33 → v0.35:

  • New Features & Improvements
    • Color Picker
      • 可用 Esc 退出取色器编辑
    • FancyZones
      • 自定义布局支持热键与快速交换:在编辑器中分配热键后,可用 Ctrl+Win+Alt+数字 或拖拽窗口时按热键快速套用分区
    • PowerToys Run
      • 可指定启动器窗口的显示位置
      • 新增插件支持打开近期使用的 VS Code 工作区、远程机器(SSH 或 Codespaces)与容器(默认关闭,启用后用 { 查询)
      • Shell 历史现在保存原始命令而非解析后命令(如 %appdata% 不再被保存为绝对路径)
  • Bug fixes Highlights
    • PowerToys 将在 0.35.x 之后要求 Windows 10 v1903 或更高版本 (#9999)
    • 修复任务栏垂直时 FancyZones 的布局算法 (#9999)

这些示例正文体现的两点设计原则延续至今:每个工具一个小节(便于快速定位感兴趣的功能)、每个要点一行(便于滚动扫读)。

8. 界面布局 Mock-up

规格附带的线框稿展示了预期界面布局。下图为规格 5.1.1 的 SCOOBE 对话框布局:顶部含窗口标题栏与"What's New"主导航,左侧为按版本组织的条目,右侧为某版本的新特性/改进说明区域,支持按工具展开阅读:

PowerToys SCOOBE 对话框布局示意(What's New 页,规格 5.1.1)

下图为规格 5.1.2 的 OOBE Welcome 页面——首次安装(非升级)时用户首先看到的是它,而不是 What's New:

PowerToys OOBE Welcome 页布局示意(规格 5.1.2)

两图共同说明了规格需求 2 与需求 7:SCOOBE 内容在形态上沿用 OOBE 的对话框框架,但按启动场景(升级 vs 首次安装)决定默认呈现哪一页。

9. 限制与边界说明

结合规格与实现,使用 SCOOBE 时需注意以下事实性边界:

  • 需要联网:内容实时取自 GitHub Releases API,离线或代理异常时窗口会显示错误条并支持重试(规格同样假设"设备已连接互联网");
  • 非归档副本:规格明确它不是 release notes 的复制品;实现进一步做了剔除哈希、提取 Hero 图、PR 号链接化等精简处理,正文仍以 GitHub 为最终来源;
  • 属于可关闭体验:用户可在常规设置中关闭"升级后显示 What's new",避免打扰;
  • 规格为草稿doc/specs/SCOOBE.md 标注 Spec Status 为 Draft,部分条目编号存在空缺(如 4.1 表缺 5/8、4.2 表缺 7/9),个别设计假设(wiki 页存放内容)与当前实现(Releases API)存在差异——阅读与引用时以仓库代码为准。

10. 延伸阅读

登录后查看全文
热门项目推荐
相关项目推荐