Windows 本地应用全量扫描方案

在构建 Windows 桌面启动器(如 Flow.Launcher)时,如何快速、准确地扫描系统中安装的所有应用是第一步。本文介绍一套结合 物理路径扫描Shell 命名空间扫描 的混合方案。

1. 传统应用:开始菜单物理路径

Windows 的传统应用(Win32)主要通过“开始菜单”的快捷方式(.lnk)进行展示。

扫描路径

  • 用户级%AppData%\Microsoft\Windows\Start Menu\Programs
  • 系统级%ProgramData%\Microsoft\Windows\Start Menu\Programs

实现思路

遍历上述目录及其子目录,筛选 .lnk.exe 文件。

  • 使用 walkdir 递归遍历。
  • 提取文件名作为显示名称。
  • 利用 Shell 接口解析 .lnk 以获取图标和备注。

2. UWP 应用:AppsFolder 虚拟目录

现代应用(UWP)和部分系统项不一定存在物理 .lnk 文件,它们统一注册在 shell:AppsFolder 这个虚拟容器中。

核心概念

  • AUMID (AppUserModelID):UWP 应用的唯一标识符(例如 Microsoft.WindowsStore_8wekyb3d8bbwe!App)。
  • IShellItem:Windows 对所有 Shell 对象的抽象接口。

实现逻辑

  1. 获取 AppsFolder 实例:使用 SHGetKnownFolderItem(&FOLDERID_AppsFolder, ...)
  2. 枚举项:通过 BindToHandler 获取 IEnumShellItems
  3. 识别 UWP:通过 PKEY_AppUserModel_ID 获取 AUMID。如果 AUMID 包含 !,通常认为这是一个可启动的 UWP 应用。
  4. 解析启动目标:构建 shell:AppsFolder\<CanonicalName>

3. 技术挑战与优化

  • 去重逻辑:部分应用既在虚拟容器中,又在物理菜单中。通常以应用名称或执行路径作为 Key 进行 HashSet 去重。
  • 性能优化:扫描过程应放在异步线程中,避免阻塞 UI。
  • 拼音支持:为了更好的搜索体验,需将中文应用名转换为拼音和简拼。

4. 总结

一个完整的 Windows 应用扫描器必须是“双引擎”的:

  1. 物理扫描 捕捉大部分桌面软件。
  2. 虚拟扫描 补全 UWP 应用和系统工具。