65.9K
CodeProject 正在变化。 阅读更多。
Home

Internet Explorer 收藏夹,剖析

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.83/5 (18投票s)

2007 年 12 月 19 日

CPOL

6分钟阅读

viewsIcon

145172

downloadIcon

750

描述用于存储 Internet Explorer 收藏夹的二进制格式,包含 Favorites-to-XBEL 示例项目。


下载 Favorites2XBEL.zip - Visual Studio 2008 解决方案 - 20 KB

下载 Favorites2XBELvs2005.zip - Visual Studio 2005 解决方案 - 20 KB

引言

本文档包含了我收集到的关于 Internet Explorer 如何以及在哪里存储其书签(或微软术语中的“收藏夹”)的信息。

背景

在我编写终极书签同步器的过程中遇到了一个问题:微软没有提供 API 来访问浏览器收藏夹结构。虽然大部分书签信息是以易于阅读的格式提供的,但书签在收藏夹菜单中出现的顺序是以二进制格式存储在注册表中的。在互联网上搜索会发现有几个人已经(部分)解码了这种结构,我想在这里分享我的发现。

如何开始

IE 收藏夹存储在“收藏夹”文件夹下的目录结构中。可以通过读取注册表项 HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders 中的“Favorites”值来找到此文件夹。或者,在 .NET 中,可以调用 Environment.GetFolderPath(Environment.SpecialFolder.Favorites) 来检索路径。收藏夹文件夹包含“.URL”文件,它们可以选择性地以目录结构排列,该结构反映了 IE 收藏夹的菜单结构。

.URL 文件

.URL 文件(扩展名:.url)是传统的 .INI 文件,其中包含收藏夹的目标地址。不带扩展名的 URL 文件名就是书签在收藏夹菜单中显示的名称。以下是一个指向 codeproject 站点的书签内容:
[DEFAULT]
BASEURL=https://codeproject.org.cn/
[InternetShortcut]
URL=https://codeproject.org.cn/
IDList=
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,2

正如你所见,codeproject 地址在此 URL 中存储了两次。但是,只有第二个地址在访问收藏夹站点时才会被使用。第一个(键 BASEURL,节 DEFAULT)仅仅存储了添加收藏夹时页面的原始地址。任何后续对收藏夹的编辑只会修改键 URL,节 InternetShortCut

排序

现在是棘手的部分:IE 以一种完全不同的方式存储 URL 和文件夹的菜单顺序,即注册表。这个冒险从注册表项 HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\MenuOrder\Favorites 开始。此项包含一个二进制类型(REG_BINARY)的值“Order”,它是一种表格,包含指向 URL 文件或文件夹的有序记录。对于文件系统中的每个收藏夹子文件夹,在 "..\MenuOrder\Favorites" 项下也有一个对应的注册表项,每个项都包含另一个“Order”表。以下截图清楚地展示了收藏夹文件系统结构和注册表结构的镜像关系。

favorites filesystem structure

favorites registry structure

Order 表格式

Order 表是二进制格式的表格。其基本结构如下:
MenuOrderTable = MenuOrderTableHeader,  { MenuOrderRecord }
MenuOrderRecord = MenuOrderRecordHeader, SubRecord0, Filler
SubRecord0 = SubRecord0Header, "short folder or url filename and various other information", SubRecord1
SubRecord1 = SubRecord1Header, "long folder or url filename and various other information"
(注意 {..} 表示:重复零次或多次)
确切的二进制格式在以下表格中给出:

MenuOrderTable
字段长度 字段类型 描述
4 UInt32 0x00000008 Header ID,始终为 8
4 UInt32 0x00000002 Header ID,始终为 2
4 UInt32 x 后面载荷的总长度,包括此字段的 4 个字节
4 UInt32 0x00000001 未知,始终为 1
4 UInt32 NumberOfRecords 后面 MenuOrder 记录的数量
NumberOfRecords * n MenuOrderRecord 见下文 'NumberOfRecords' 次 MenuOrderRecord 结构

MenuOrderRecord
字段长度 字段类型 描述
4 UInt32 x 此记录的总长度,包括后面的填充字节。也包括此字段的 4 个字节
4 Int32 ordernumber 确定此条目显示顺序的数字,如果条目无序则为 -5
variable SubRecord0 见下文 包含菜单顺序条目类型、长度、名称的子记录
6 byte[6] 0 填充字节,全部为零

SubRecord0
字段长度 字段类型 描述
2 UInt16 x 此记录的总长度,包括此字段的 2 个字节
2 UInt16 标志
位 0:1 => 它是文件夹,否则为 0
位 1:1 => 它是 URL,否则为 0
位 2:1 => 短 8.3 文件名以 Unicode 格式存储,0 => 短名称使用 ASCII 存储
4 UInt32 ? 未知
4 UInt32 ? 可能是“上次访问”日期,每次访问此链接时都会更新。未知编码。
2 UInt16 0x20, 0x10 或 0x11 标志
位 0:1 => 长文件名在 SubRecord1 中后跟一个指向资源字符串的字符串
位 4:1 => 它是文件夹,否则为 0
位 5:1 => 它是 URL,否则为 0
可变(偶数) 零终止的 ASCII 或 Unicode 字符串,取决于 Flags 零终止的 8.3 风格文件夹名或 URL 名称。此字段用零填充以包含偶数个字节。
variable SubRecord1 见下文 包含此菜单顺序条目长 Unicode 名称的子记录

SubRecord1
字段长度 字段类型 描述
2 UInt16 x 此记录的总长度,包括此字段的 2 个字节
Vista 上为 36
XP/2003 上为 18
byte[] ? 未知用途
variable 零终止的 Unicode 字符串 variable 文件夹或 URL 的长名称
variable 零终止的 Unicode 字符串 variable 可选字段:检查 SubRecord0 中第二个“flags”字段的位 0 以查看此字段是否存在。
此字符串指向 DLL 中的一个资源字符串,格式如下:@shell32.dll,-12693
2 UInt16 variable SubRecord1 在 SubRecord0 中的位置(字节索引)

如何使用

在阅读以上信息时,你可能只对以下信息感兴趣:

  • 它是文件夹还是 URL
  • 排序号
  • 长文件名

注意事项

请注意,此信息是逆向工程的结果。我仅在 XP 和 Vista 上验证了这些结构。您还应该意识到 Vista 和 XP 之间的结构差异:在 Vista 上,SubRecord1 中的“未知”字节数组的大小与 XP 不同。

代码

我已经将上述信息浓缩到一个名为 FavoritesNode 的类中,该类允许您加载和检查当前用户的 Internet 收藏夹。FavoritesNode 实现 IList<FavoritesNode>,因此它实际上是一种树。该树中的每个节点要么是“文件夹”要么是“URL”。

如何使用

以下示例显示了如何加载收藏夹并打印顶级书签:

    ...
    using CodeProject.IEFavDecon;
    ...
    FavoritesNode node = FavoritesNode.LoadRoot();

    foreach(FavoritesNode child in node)
    {
        if(child.NodeType == FavoritesNodeType.Url)
        {
            Console.WriteLine("Name: {0}, Url: {0}", child.DisplayName, child.Url);
        }
    }

XBEL: XML 书签交换语言

附加 zip 中的项目做了更有用的事情:它加载您的收藏夹并将其写入 XBEL 格式的 XML 文件(这是微软本应早该使用的书签格式)。一旦您的书签采用 XML 格式,就可以轻松地将其转换为网页、导入或导出、合并、排序等。
例如,主程序文件包含一个注释掉的部分,其中显示了如何应用样式表将生成的 XML 书签转换为漂亮的缩进 HTML 文件。

其他资源

以下链接包含了我在研究过程中非常有帮助的有关此主题的零散信息:

历史

  • 2007 年 12 月 19 日:首次发布
  • 2007 年 12 月 22 日:添加了示例代码,更新了文本和资源链接
  • 2007 年 12 月 24 日:添加了解决方案的 vs2005 版本
© . All rights reserved.