PowerToys Advanced Paste:AI 粘贴预览机制与稀疏包身份调试实战指南
2026/9/7 20:02:09 网站建设 项目流程

PowerToys Advanced Paste:AI 粘贴预览机制与稀疏包身份调试实战指南

【免费下载链接】PowerToysMicrosoft PowerToys is a collection of utilities that supercharge productivity and customization on Windows项目地址: https://gitcode.com/GitHub_Trending/po/PowerToys

本文基于 PowerToys 官方开发文档 advancedpaste.md,系统讲解 Advanced Paste 模块的两个核心技术点:其"AI 粘贴预览"功能的实现流程(ShowCustomPreview设置如何复用已生成的 AI 响应而不消耗额外调用),以及作为非打包 WinUI 3 应用的PowerToys.AdvancedPaste.exe如何通过共享稀疏 MSIX 包(Microsoft.PowerToys.SparseApp)获得包身份以解锁 Windows AI 受限功能(Phi Silica /LanguageModel)。读完后你将掌握本地调试 Advanced Paste 的完整流程、稀疏包一键注册与验证命令、常见故障的定位方法,以及 Settings UI 通过子进程探测 AI 可用性的机制。

模块概览

Advanced Paste 是 PowerToys 中提供"增强剪贴板粘贴"的模块:在标准粘贴之外,提供带格式化选项与 AI 处理能力的粘贴动作(如修正拼写与语法、自定义 AI 粘贴等)。源码位于 src/modules/AdvancedPaste,核心 C# 项目在 src/modules/AdvancedPaste/AdvancedPaste,模块接口层(负责进程管理与命名管道 IPC)位于 src/modules/AdvancedPaste/AdvancedPasteModuleInterface。

从源码结构看,该模块是一个非打包(unpackaged)、自包含的 WinUI 3 应用PowerToys.AdvancedPaste.exe。要调用 Phi Silica 的Microsoft.Windows.AI.Text.LanguageModelAPI,进程必须具备匹配的包身份——这正是后文稀疏包身份机制要解决的问题。模块入口在 Program.cs,其中还能看到 GPO 策略检查(管理员可通过组策略禁用该工具)、AppInstance.FindOrRegisterForKey单实例保护等启动逻辑。

AI 粘贴预览:ShowCustomPreview与生成结果缓存

官方文档中最关键的实现说明是:"Show preview" 设置(ShowCustomPreview)控制 AI 生成结果是否在粘贴前于预览窗口中展示,且预览功能不额外消耗 AI 调用额度——预览展示的是同一次 API 调用已经生成、并在本地缓存的结果。

文档给出的实现流程为:

  1. 用户发起 "Paste with AI" 动作;
  2. 通过ExecutePasteFormatAsync发起单次AI API 调用;
  3. 结果缓存在GeneratedResponses集合中;
  4. 若预览已启用,缓存结果展示在预览 UI 中;
  5. 用户粘贴缓存结果时不再产生任何额外 API 调用

这一流程在源码中可以得到逐条印证。核心方法ExecutePasteFormatAsync(PasteFormat, PasteActionSource)位于 OptionsViewModel.cs:

  • 第 746 行调用_pasteFormatExecutor.ExecutePasteFormatAsync(...)执行实际的格式转换(对 AI 动作即一次 AI 调用),执行器接口见 IPasteFormatExecutor.cs 与实现 PasteFormatExecutor.cs;
  • 第 753 行是预览判定条件:pasteFormat.Metadata.CanPreview && _userSettings.ShowCustomPreview && !string.IsNullOrEmpty(outputText) && source != PasteActionSource.GlobalKeyboardShortcut——即格式元数据允许预览、用户开启ShowCustomPreview、输出非空、且来源不是全局快捷键时才走预览;"拼写/语法修正"的引导(coaching)模式则会强制预览;
  • 第 763 行GeneratedResponses.Add(outputText)将结果写入ObservableCollection<string> GeneratedResponses(定义于第 583 行),并更新CurrentResponseIndex指向最新一条,随后触发PreviewRequested事件展示预览界面。

也就是说,AI 调用只发生一次,预览与最终粘贴消费的都是同一个dataPackage/ 缓存文本,这与文档中"预览不消耗额外 AI 额度"的结论一致。

设置项

设置说明
ShowCustomPreview启用后,粘贴前在预览窗口中展示 AI 生成的结果。不影响 AI 额度消耗。

ShowCustomPreview作为用户设置字段在 UserSettings.cs 中定义,模块接口层(dllmain.cpp)也引用了该字段进行设置序列化。

调试:运行与附加调试器

由于 Advanced Paste 由 Runner 在模块启用后于后台拉起,官方文档给出的标准调试步骤是:

  1. 在 Visual Studio 中将Runner项目(src/runner)设为启动项目;
  2. 启动 Runner(F5),拉起 PowerToys 托盘图标并加载所有模块接口;
  3. 打开设置(右键托盘图标 → Settings),确认已启用Advanced Paste模块。启用后模块会立即在后台启动PowerToys.AdvancedPaste.exe
  4. 在 Visual Studio 中选择Debug → Attach to ProcessCtrl+Alt+P),附加到PowerToys.AdvancedPaste.exe,调试器类型选择Managed (.NET Core)

替代方案:使用 VS Code 的启动配置"Run AdvancedPaste"(位于 .vscode/launch.json)直接拉起 exe——但文档明确提示:没有 Runner 时,IPC 与全局快捷键均不可用,因为管道服务器与快捷键注册都由模块接口层(Runner 进程内)负责。

稀疏包身份:非打包 WinUI 3 应用的包身份问题

为什么需要稀疏包身份

  • LanguageModelAPI 需要 Limited Access Feature(LAF)解锁,而解锁只有调用进程具备匹配包身份时才会成功
  • Advanced Paste 是非打包、自包含的 WinUI 3 应用。稀疏包在不将其转换为完整 MSIX的前提下授予其身份;
  • csproj 使用<ProjectPriFileName>PowerToys.AdvancedPaste.pri</ProjectPriFileName>(与 ImageResizer 等其他 WinUI3 应用相同的自定义 PRI 命名约定)。这一点可在 AdvancedPaste.csproj 第 24 行确认。该约定要求 WindowsAppSDK Foundation ≥ 2.0.22(对应 WindowsAppSDK 的 PR #6376),该版本修复了 MRT 在稀疏身份下查找自定义命名 PRI 文件的问题,使Application.LoadComponent能解析自定义 PRI 名而不是硬编码resources.pri

一键开发环境搭建

完整的稀疏包文档位于 src/PackageIdentity/readme.md。Advanced Paste 文档给出的一键开发注册命令为:

pwsh src/PackageIdentity/BuildSparsePackage.ps1 -Platform ARM64 -Configuration Debug -DevRegister

-DevRegister的行为(对应脚本 BuildSparsePackage.ps1):

  1. src/PackageIdentity/.user/下生成开发证书(仅首次运行);
  2. 自动将该证书导入CurrentUser\TrustedPeopleCurrentUser\Root,使系统愿意把稀疏身份授予 AP(没有信任关系时,GetPackageFamilyName会返回APPMODEL_ERROR_NO_PACKAGE,LAF 解锁静默失败);
  3. 移除此前的注册;
  4. AppxManifest.xml的临时副本中重写 publisher,使其匹配开发证书主题;
  5. 通过Add-AppxPackage -Register … -ExternalLocation X:\…\<Platform>\<Config>\WinUI3Apps完成注册。

关于-ExternalLocation指向WinUI3Apps子目录的原因,src/PackageIdentity/readme.md 有进一步说明:MSIX 本身只含元数据,将其指向 Win32 可执行文件所在子目录,可以把 MSIX 注册在 Windows 23H2/24H2 上引发的 DACL 变更隔离在WinUI3Apps文件夹内,保持安装根目录干净(预览处理器 DLL 仍从根目录加载)。

BuildSparsePackage.ps1还支持的其他开关:

  • -Clean:清理此前bin/obj输出并卸载已有安装;
  • -ForceCert:重新生成本地开发证书(.pfx/.cer/.pwd/.thumbprint);
  • -NoSign:跳过签名(MSIX 仍能构建,但部署前必须签名);
  • -CIBuild(或$env:CIBuild = 'true'):保留 manifest 中的 publisher 原样、跳过本地证书替换,供 CI 使用。

注册后验证

$pkg = Get-AppxPackage -Name '*SparseApp*' $pkg.PackageFamilyName # Microsoft.PowerToys.SparseApp_<PublisherId> $pkg.PublisherId $pkg.IsDevelopmentMode # True

然后确认 AP 在运行时确实获得了稀疏身份:

& 'ARM64\Debug\WinUI3Apps\PowerToys.AdvancedPaste.exe' --check-phi-silica # Exit 0 = Available, 1 = NotReady, 2 = NotSupported

重新构建 AP、修改 AppxManifest.xml 或切换平台/配置后,需重新运行同一命令以完成重新注册;使用-Unregister可注销身份。此外,打包完成后脚本还会输出src/PackageIdentity/.user/PowerToysSparse.publisher.txt,镜像注册后 Windows 可见的 publisher 字符串,供其他组件在生成自身 manifest 时保持同步。

故障排查表

官方文档给出的排查表(完整继承):

问题原因解决方案
运行时GetPackageFamilyName返回APPMODEL_ERROR_NO_PACKAGE(15700),LAF 解锁返回Unavailable开发证书未被信任(或稀疏包未注册)重新运行BuildSparsePackage.ps1 -DevRegister——会自动把证书导入TrustedPeopleRoot
AP 或 Settings 启动时Microsoft.UI.Xaml.dll崩溃,错误0xC000027B(class-not-registered)AppxManifest.xml<Application>Executable路径无法在已注册的ExternalLocation<Config>\WinUI3Apps\)下解析确认每个Executable相对于WinUI3Apps\(见 issue #47177),且文件存在于构建输出中。
通过快捷键触发时 AP 启动但始终不显示窗口Runner 的管道服务器等待在 AP 冷启动完成 WinAppSDK + DI 宿主引导之前超时AdvancedPasteProcessManager.cpp中 15 秒管道超时已缓解该问题;热启动连接远低于 1 秒。对应源码见 AdvancedPasteProcessManager.cpp
XamlParseException/ 找不到ms-appx:///Microsoft.UI.Xaml/Themes/…WindowsAppSDK Foundation < 2.0.22;MRT 无法在稀疏身份下解析自定义 PRI 名确保Directory.Packages.propsMicrosoft.WindowsAppSDK.Foundation≥ 2.0.22。

Settings UI 如何检查 Phi Silica 可用性

Settings UI 本身没有稀疏包身份,无法直接探测 Phi Silica。它的做法是把 Advanced Paste 作为短命子进程启动:

PowerToys.AdvancedPaste.exe --check-phi-silica

Program.cs 中Program.Main识别该参数并进入CheckPhiSilicaAvailability():先调用PhiSilicaLafHelper.TryUnlock(),再调用LanguageModel.GetReadyState(),向 stdout 输出Available/NotReady/NotSupported之一,并以相应退出码结束(0 = Available,1 = NotReady,2 = NotSupported 或错误)。Settings 端读取 stdout 并等待最多 10 秒。由于每次检查都是全新进程,瞬时的Unavailable结果不会跨检查缓存

LAF 解锁逻辑在 PhiSilicaLafHelper.cs 中:特性 ID 为com.microsoft.windows.ai.languagemodel,只缓存成功的解锁结果——失败(Unavailable、未知状态、异常)往往是瞬时的(例如登录前 AI 特性栈尚未初始化、或稀疏身份尚未完全应用到刚启动的进程),下次调用时重试即可恢复。LastUnlockStatus属性暴露最近一次解锁状态,便于诊断真实的 LAF 结果,而不是下游模型调用那句笼统的 "Access is denied"。

源码中还有一个文档未展开的兄弟参数--prepare-phi-silica(Program.cs):它在不启动 WinUI 应用的情况下触发 Phi Silica 模型准备(下载),通过EnsureReadyAsync()把模型从NotReady推进到Ready,退出码为 0 = ready、1 = 准备失败、2 = 不受支持。注释还说明了一个细节:EnsureReadyAsync这类 WinRT 异步操作若从[STAThread]入口点阻塞等待无法正确编组,因此代码将其放到线程池线程上执行。

延伸资料

  • advancedpaste-phisilica-local-testing.md:Phi Silica 可用性的分层诊断与本地测试/故障排查指南;
  • src/PackageIdentity/readme.md:稀疏包的完整文档,包括构建、签名、注册/注销、CI 指引,以及"其他组件如何消费稀疏身份"的六步流程(在AppxManifest.xml中新增<Application>条目、在 Win32 二进制中嵌入带<msix>元素的 sparse identity manifest、使用shell:AppsFolder\...激活形式启动等);
  • Advanced Paste 的设置界面与 DSC 资源分别见 Settings UI 与 doc/dsc/modules/AdvancedPaste.md 中的说明。

适用前提与限制:上述调试与稀疏包注册流程面向 Windows 本地开发环境(PowerShell + Visual Studio / VS Code),--check-phi-silica的可用性结果取决于系统 AI 特性栈、硬件与授权状态;Phi Silica 相关 API 仅在有 Windows AI 能力的系统上返回Ready,其他系统会以NotReadyNotSupported状态呈现,属预期行为。

【免费下载链接】PowerToysMicrosoft PowerToys is a collection of utilities that supercharge productivity and customization on Windows项目地址: https://gitcode.com/GitHub_Trending/po/PowerToys

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询