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 对象的抽象接口。
¶实现逻辑
- 获取 AppsFolder 实例:使用
SHGetKnownFolderItem(&FOLDERID_AppsFolder, ...)。 - 枚举项:通过
BindToHandler获取IEnumShellItems。 - 识别 UWP:通过
PKEY_AppUserModel_ID获取 AUMID。如果 AUMID 包含!,通常认为这是一个可启动的 UWP 应用。 - 解析启动目标:构建
shell:AppsFolder\<CanonicalName>。
¶3. 技术挑战与优化
- 去重逻辑:部分应用既在虚拟容器中,又在物理菜单中。通常以应用名称或执行路径作为 Key 进行
HashSet去重。 - 性能优化:扫描过程应放在异步线程中,避免阻塞 UI。
- 拼音支持:为了更好的搜索体验,需将中文应用名转换为拼音和简拼。
¶4. 总结
一个完整的 Windows 应用扫描器必须是“双引擎”的:
- 物理扫描 捕捉大部分桌面软件。
- 虚拟扫描 补全 UWP 应用和系统工具。