关于 Windows 10 开始菜单残留项目的一些分析

Windows 10 很好用,这一点我想并没有多少人会否定。然而作为一个赶工出来的操作系统来说 bug 多一点也是在所难免的。写这篇文主要是因为自己遇到了一个很蛋疼的 bug,就是那个臭名昭彰的从 Windows 10 旧版 build 更新到正式版之后会有废弃应用项目在开始菜单残留的问题。

症状: 开始菜单出现形如 @{winstore_cw5n1h2txyewy.10.0.10152.0 的应用并且无法卸载或删除。

分析 1: 找到开始菜单项目实际存在的位置并删除那个项目。

鉴于 Modern 或者称作 Metro 应用的特殊性质,注册表中一般并不会保存应用程序数据那么直接删除掉残留应用的话开始菜单的残留是否会消失呢?

那么找出 PowerShell 来试着删掉那个毒瘤好了,首先运行

Get-AppxPackage

来列出所有安装的 Modern 应用,然后找到 PackageFullName: 名称
复制冒号后面的应用完整名称然后

Remove-AppxPackage 名称

就可以卸载应用了。

不过很可惜, Windows 默认阻止了用户随意卸载系统应用(如上图)...

怎么说?软的不听的话就只好稍微暴力一点了。Windows 系统的自带 Modern 应用被安装在了 C:\Windows\SystemApps 目录下,转到目录删掉不想要的系统应用就可以了,之间可能涉及到如何修改文件权限的内容这里就省略掉。删完重启,看一下结果吧。

结果: 应用被删掉了,开始菜单的残留还在。

结论 1: 开始菜单的 Modern 应用列表并不会因为直接删掉应用而重建。

分析 2: 虽然 Modern 应用不大会在注册表中写入太多项目但开始菜单会不会存在注册表的相关键值中呢?

所以接下来就使用我们的利器 Registry Workshop,来全方位搜索一下注册表。我使用了关键字 10152 进行搜索,然而最后的结果果然比较令人失望,没有匹配的结果。

结论 2: 开始菜单的项目并不保存在系统注册表中。

分析 3: 开始菜单列表存在于某个文件中。

剩下的可能性大概比较靠谱的就剩下这一个了吧。开始菜单列表并不是动态构建的,所以很有可能存储在某个文件之中。但问题又来了,Windows 系统有着数十万的文件,究竟哪一个才是我们要找的?盲目寻找如大海捞针一般漫无目的费时又费力。必须要有一个着眼点才行,从系统进程或系统服务开始会不会靠谱一点?那么用 Windows 10 测试版那么久我已经知道 Windows Shell Experience Host 是控制开始菜单、Cortana、任务栏其他应用譬如电量、音量、通知、时钟等等的核心程序(最为明显的就是当开始菜单处于关闭状态,此时的 WSEH 也是同时处于挂起状态的),那么和 WSEH 相关的其他应用或服务就更具可疑点。

所以接下来我们打开享有 Windows 瑞士军刀美名的微软自家工具 Microsoft Sysinternals Suite 并分析位于 C:\Windows\SystemApps 下面的 ShellExperienceHost.exe 文件。

结论 3: 经过分析找到了比较可疑的服务,就是那个名为 Tile Data model server 的服务。然而这个服务停止后便会立即重启,不过多次手动结束服务之后就不会重启了,相应的开始菜单就无法打开,看起来至少路子对了。

分析 4: 接下来就是寻找和 Tile Data model server 相关的文件,开始菜单项极有可能存储于那里。

本来以为会埋藏的比较深,结果很意外的是用 Windows 自带的搜索搜索了 TileData 很容易就找到了!可疑文件夹排除到了一个,就是 C:\Users\用户名\AppData\Local\TileDataLayer\Database,目录下面只有几个文件

只不过复制的时候会提示文件被占用的只有一个,就是那个 vedatamodel.edb 文件。启动到命令提示符的安全模式之后就可以对那个文件进行操作了,进一步印证了自己的想法。

结论 4: 基本可以确定开始菜单项目存放于 C:\Users\用户名\AppData\Local\TileDataLayer\Database\vedatamodel.edb 文件中。

分析 5: 那么简单一点解决,如果删除掉 vedatamodel.edb 的话 Windows 会不会自动重建开始菜单列表呢?

这个简单,重启到命令提示符的安全模式然后运行(记得备份):
del C:\Users\用户名\AppData\Local\TileDataLayer\Database\vedatamodel.edb
重启就好了。

结果: 重启之后登录转圈转了 1 分多钟... 进入系统任务栏假死,然后开始菜单一片空白(真的是包括关机在内什么都没有)。
开启任务管理器假死。随后再次重启了系统,发现进入了一个重建的账号,吓得我赶紧回到原来自己的用户文件夹看数据是不是都在... 后来再次重启发现进入系统了,开始菜单可以用了,残留消除了。但是相应的,自己安装的 Modern 应用快捷方式全部不见,一些桌面应用诸如 Chrome 的快捷方式也没有了。后来发现 C:\Users 下面多了个 TEMP 文件夹,而里面仅有一个 vedatamodel.edb。可以断定这个重建的文件被复制到了原始账号充当替代品。

结论: Windows 重建开始菜单列表十分不智能,甚至可以说是无脑... 需要找到编辑 EDB 文件的东西手动编辑。

分析 6: EDB 全称是 Extensible Storage Engine (ESE) Database File (EDB),由微软开发,Microsoft Exchange Server 的数据库文件。找到相关的编辑器就可以编辑了。

首先我找到了 ESEDatabaseView 这个查看器。毫不意外的是,我们找到了存储在这个 vedatamodel.edb 中的全部程序的项,这里面不仅包括了 Modern 应用还包括了经典桌面的应用。

非常可惜的是,这个一些网站上所谓的编辑器只能看并不能改,所以根本还是没有什么卵用的。

分析 7: 需要找到能读取和写入 EDB 文件的方法。

非常幸运的,微软也确实提供了 ESE 相关的 assembly,诸君有兴趣的话可以参考下 来自 MSDN 的介绍。使用它便可以对 ESE 的数据库 EDB 文件随心所欲地进行操作了。

写了一个小程序,通过输入想移除列表项目的名称来删掉不需要的开始菜单项目。C# 写的,因为 ESE 的 API 仅仅支持 C# 和 VB。

相关用法有:Api.JetAttachDatabase 获取并装载本地的 ESE 数据库文件。Api.JetOpenDatabase 打开本地 ESE 数据库文件。Api.GetColumnDictionary((JET_SESID) session, (JET_TABLEID) table); 来获取相关的 dictionary。Api.JetDelete 删除对应项。

相关的程序和 source code 会稍后放出。