在编写一个书签同步工具的过程中,遇到了一个问题:微软并没有提供访问浏览器书签结构的API。尽管大部分书签信息都以易于阅读的格式存储,但是书签在收藏夹菜单中显示的顺序是以二进制格式存储在注册表中的。互联网上有一些解码了这部分结构的人,也想在这里添加发现。
IE收藏夹存储在'收藏夹'文件夹下的目录结构中。这个文件夹可以通过读取注册表键值:
HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
中的'Favorites'值来找到。或者在.NET中,可以调用:
Environment.GetFolderPath(Environment.SpecialFolder.Favorites)
来检索路径。收藏夹文件夹包含.URL文件,这些文件可能以反映IE收藏夹菜单结构的目录结构排列。
.URL文件(扩展名:.url)是老式的.INI文件,包含书签的目标地址。URL文件的名称(不包括扩展名)是书签在收藏夹菜单中显示的名称。以下是指向CodeProject网站的书签内容:
[DEFAULT]
BASEURL=http://www.codeproject.com/
[InternetShortcut]
URL=http://www.codeproject.com/
IDList=
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,2
如所见,CodeProject的地址在这个URL文件中存储了两次。但是,只有第二个地址(键URL,节InternetShortCut)在访问书签网站时使用。第一个地址(键BASEURL,节DEFAULT)仅在将页面添加为书签时存储页面的原始地址。之后对书签的任何编辑只会修改键URL。
现在来说棘手的部分:IE以完全不同的方式存储URL和文件夹的菜单顺序,即注册表。这个冒险始于注册表键:
HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\MenuOrder\Favorites
这个键包含一个二进制类型(REG_BINARY)值'Order',这是一个包含有序记录的表,指向URL文件或文件夹。对于文件系统中的每个收藏夹子文件夹,也有一个对应的注册表键在
"..\MenuOrder\Favorites"
键下,每个键都包含另一个'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"
(注意{..}表示:重复零次或多次)
当阅读上述信息时,可能只对以下信息感兴趣:
请注意,这些信息是逆向工程的结果。只在XP和Vista上验证了这些结构。还应该意识到Vista和XP之间的结构差异:在Vista上,SubRecord1中的'unknown'字节数组的大小与XP上的不同。
已经将上述信息压缩成一个名为FavoritesNode的类,它允许加载和检查当前用户的互联网收藏夹。FavoritesNode实现了IList<FavoritesNode>,所以它实际上是一棵树。这棵树的每个节点要么是一个'文件夹',要么是一个'url'。
以下示例展示了如何加载收藏夹并打印顶级书签:
C#
...
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);
}
}
附加的zip文件中的项目做了一些稍微有用的事情:它加载收藏夹并将它们写入XBEL格式的XML文件(这应该是微软现在应该使用的书签格式)。一旦书签以XML格式存在,将其转换为网页、导入或导出、合并、排序等就变得容易了。