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

一个简单的 Windows RSS 存储查看器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.52/5 (10投票s)

2006年2月5日

11分钟阅读

viewsIcon

87413

downloadIcon

744

一个简单的 Windows RSS 存储查看器,基于 IE7 RSS 平台。

Sample Image - rssstoreviewer5.gif

引言

免责声明:本文及源代码未经微软认可。请自行承担使用风险。您可以自由重用此代码。

微软最近(截至2006年2月5日)发布了其新版 Internet Explorer 的预览版,其中集成了 RSS 功能。这包括一个 RSS 存储机制,以及一个有文档记录的COM 接口。

虽然 Internet Explorer 7 是此 RSS 存储的默认客户端,但我认为深入了解其 API,了解 RSS 存储的工作原理以及如何创建自己的非 API 客户端会很有趣。您可以下载的示例是实验的结果,它是 C# .NET 代码。

即使没有安装 Internet Explorer 7,您也可以运行此示例。我在 zip 文件中提供了一个“以防万一”的文件夹,其中包含我的 RSS 存储的快照。只需将该文件夹的内容复制到您硬盘上的 RSS 存储位置(见下文)。

RSS 存储内部解析

RSS 存储在安装 Internet Explorer 7 预览版在 XP SP2 机器上安装。无需进行任何配置。RSS 存储有一个同步引擎(相当于 Unix 的守护进程),我将在本文稍后讨论。

RSS 存储是一组 OLE 文档(一项已有二十年历史、非跨平台的技术),并且是按账户安装的。如果您的 Windows 账户名是 <user>,则 RSS 存储位于 C:\Document and settings\<user>\Local Settings\Application Data\Microsoft\Feeds\FeedsStore.feedsdb-ms

RSS 存储

.feedsdb-ms 文件扩展名所暗示的不同,可以使用标准的 OLE 文档查看器打开它,例如 Visual Studio 自带的(Tools / DocFile Viewer)。如果您没有安装 Visual Studio,可以在此处下载一个替代的 OLE 客户端。

打开 FeedsStore.feedsdb-ms,一个普通的 OLE 文档

OLE 文档包含多个流。第一个存储通用设置,而所有以 @ 开头的流是实际的订阅源。在上图的屏幕截图中,我订阅了两个源。流名称本身无关紧要。

打开这些流,会发现一个简单的 XML 架构,它规定了源的呈现方式以及如何同步。一些最有趣的属性包括:

  • <FeedDataCache Path="...">:存储相应源的名称和路径。
  • <uiInterval>:客户端刷新间隔。
  • <fDownloaded>:是否已下载附加的附件。
  • <Counts>:当前存储的项目数量。

这是从流 @KWKUcVBJEWabDBVUIBbfDFeLHbWD 中抓取的源描述符的屏幕截图。

源描述符

<Path> 元素至关重要:它包含源在 IE7 收藏夹侧边栏中显示的名称,以及描述源文件实际所在文件夹的完全限定路径。请注意,文件夹用于构建 IE7 收藏夹侧边栏树形视图,并且也是硬盘上实际的物理子文件夹。

要访问源,需要获取 RSS 存储路径,在编码后加上 <Path> 的内容,然后在其后加上 ~.feed-ms。生成的文件是另一个 OLE 文档,也可以打开。这是在 OLE 客户端中打开的 Scobleizer - Microsoft Geek Blogger~.feed-ms 的屏幕截图。

存储的源项目

有多个流,其中最值得注意的是:

  • 名称为数字(0, 1, ..., n - 1)的流就是源项目的快照。
  • 一个名为“Rss”的流。它存储 RSS/Atom 源的标题。这对于获取编码字符集等元数据非常有用。
  • 一个名为“Item data”的流。此流包含每个源项目的设置列表,最重要的是它们是否被“标记为已读”。
  • 一个名称被损坏的流。它存储互联网上的实际源 URL。

一个良好的源客户端应该读取所有流并适当地合并元数据。按顺序,您应该读取损坏名称的流以获取实际 URL,然后读取 RSS 流以获取用于呈现源项目的关键标题信息,然后读取“Item data”流,其中列出了所有源项目及其设置。最后,当然是所有存储源项目的实际流。

我提供的示例目前采取了捷径,直接抓取所有流,并按读取顺序存储源项目。

最后,我们需要看看源项目流的样子。这是流 0 的快照。

<ItemData>
 <item>
  <title>Dave worries about Microsoft</title>
  <link>http://scobleizer.wordpress.com/2006/02/03/
        dave-worries-about-microsoft</link>
  <comments>http://scobleizer.wordpress.com/2006/02/03/
            dave-worries-about-microsoft#comments</comments>
  <pubDate>Fri, 03 Feb 2006 14:50:03 GMT</pubDate>
  <author>scobleizer</author>
  <atom:author xmlns:atom="http://www.w3.org/2005/Atom">
   <atom:name>scobleizer</atom:name>
  </atom:author>
  <category>RSS</category>
  <category>Blog Stuff</category>
  <guid isPermaLink="false">http://scobleizer.wordpress.com/
              2006/02/03/dave-worries-about-microsoft</guid>
  <description type="html"><p><a href="http://www.scripting.com/
      2006/02/03.html#itsADifferentWorldToday">Dave Winer is worried</a> 
      that Microsoft is going to throw its weight around 
      when it comes to RSS. I worry about that too. A lot.</p>

      <p>I agree, too, that things have changed. For one, 
      Microsoft is far more transparent than it used to be. 
      If we do something evil you know who to call. I have 
      the head of Internet Explorer team, Dean Hachamovitch 
      on IM and have his cell phone number.</p>

      <p>Also, I am here at the Lift conference. 
      During the last session I stood in the back and watched 
      how people were sharing information. Blogs. IM. Email. 
      All live. People are so connected now. If we do something 
      evil it spreads around the world within an hour. 
      Or even faster.</p>

      <p>Finally, it takes minutes for this connected world 
      to figure out whether something is good or not. 
      If it isn’t you’ll know and know in a violent manner.</p>

      <p>What does this mean? First, if we don’t work with 
      the community we’ll fail. Second, if we don’t have 
      the best products and services, we’ll fail. 
      Third, if we take too long to react to market 
      demands we’ll be left out of the conversation 
      and rendered irrelevant.</p>

      <p>Hint: I am using <a href="http://scripting.wordpress.com/
      2006/02/02/scott-they-need-a-river-2/">Dave Winer’s 
      aggregator</a>. That said, I wish Dave’s aggregator told 
      the RSS platform when I read a post so that other RSS reading 
      apps on the system (I have several) will know that I read 
      an item already.</p>
  </description>
  <atom:summary xmlns:atom="http://www.w3.org/2005/Atom" 
         type="html">Dave Winer is worried that Microsoft 
         is going to throw its weight around when it comes 
         to RSS. I worry about that too. A lot. I agree, too, 
         that things have changed. For one, Microsoft is far 
         more transparent than it used to be. If we do something 
         evil you know who to call. I have [...]</atom:summary>
  <wfw:commentRSS xmlns:wfw="http://wellformedweb.org/CommentAPI/">
        http://scobleizer.wordpress.com/2006/02/03/
        dave-worries-about-microsoft/feed
  </wfw:commentRSS>
 </item>
 <Url>http://scobleizer.wordpress.com/feed</Url>
</ItemData>

请注意,源项目包含在 RSS 存储添加的 <ItemData> 元素中。RSS 架构版本 x.y 和 Atom 架构版本 x.y 源都遵循这些规则。

实际上,除非您对解析所有 XML 元素感兴趣,否则这并没有太大关系。毕竟,RSS 和 Atom 架构足够接近,可以轻松构建客户端。我的示例代码使用 .NET XML 订阅器式解析器来抓取以下元素:

  • <title>:源项目的标题本身。
  • <pubDate>:可选,发布日期。
  • <link>:可选,指向实际在线博文的链接。
  • <description>:源项目正文。

大致就是这些了!

有关路径和名称编码的附加信息。当您尝试访问源文件(例如 Scobleizer - Microsoft Geek Blogger~.feed-ms)时,您需要特别注意用于将路径和名称映射到实际硬盘文件的某些编码(我不知道微软为什么在这里发明了另一层专有编码,而标准的 URL 编码方案本来就可以正常工作)。

  • <Path> 中的任何 .(点)字符都应替换为 ~d
  • <Path> 中的任何 :(冒号)字符都应替换为 ~c
  • <Path> 中的任何 \(反斜杠)字符都应替换为 ~\
  • 我很确定还有其他替换,但像撇号和逗号这样的字符不会被替换。如果您发现此处未记录的组合,请告知我。

构建客户端

该示例是一个 C# 项目,包含以下文件:

  • FeedViewer.cs:作为源存储检索代码的 UI。
  • FeedStore.cs:用于打开主 OLE 文档并将源公开给客户端的代码。
  • Feed.cs:用于表示源本身的类。
  • FeedItem.cs:用于表示源项目本身的类。
  • NativeCalls.cs:用于读取 OLE 文档的 IStorage/IStream 调用。

如果您想重用此代码,您可以采用非 UI 文件并将其用作“RSS 存储 API”。或者,您也可以选择使用官方的 Microsoft RSS 存储 API。

读取 OLE 文档本质上不是 .NET 友好的。OLE 文档使用 COM IStorage/IStream 接口来公开给定文件中的虚构子文件夹和子文件的层次结构。微软使用 OLE 文档作为源存储本身,然后为所有源使用单独的 OLE 文档。所有这些加在一起就是他们所谓的 RSS 存储,但物理上它是一堆文件夹和其中的 OLE 文件。为了读取 OLE 文档,必须使用 OLE32.dll 中实现的 IStorage/IStream 接口,或者通过 Wine 或 OLE API 替换(Java 的 Apache POI,Mac OSX、Linux 等)来规避。IStorage 接口没有在 .NET 框架中公开,因此必须这样做。为了方便起见,www.pinvoke.net 网站已经为我们完成了这项工作。IStream 接口已经公开,其名称为 UCOMIStream。由于我们将执行本机代码,因此必须授予执行此操作的权限,因此在初始化阶段进行了 permission.Demand() 调用。

读取主源存储文件时,会枚举流,然后将实际的解析工作委托给相应的对象。Feed 类是唯一知道如何处理源流(名称以 @ 开头的流)的类。同理,FeedItem 类是唯一知道如何处理源项目流(名称为数字的流)的类。

读取这些 OLE 文档可以填充由 FeedStore 类按索引或名称公开的 FeedFeedItem 对象集合。

在 UI 方面,用于在左侧构建 treeview 的文件夹存储在 Feed 类中。简单的 string 分割允许我们递归地构建树。我们使用等待光标并阻止 treeview Win32 窗口更新以避免任何闪烁。treeview 有一个带有“刷新”选项的上下文菜单,该选项基本上会清除集合并重新执行读取工作。换句话说,当您单击“刷新”时,它正在执行在线刷新,它正在从 RSS 存储中抓取可用内容,而 IE7 同步引擎负责单独更新 RSS 存储。

在 UI 初始化时读取 feedstore。此时,我们可以构建源的树,但尚未读取源。这会在需要时按需发生(仅在需要时),用户单击 treeview 项。然后读取与该源关联的 OLE 文档,读取源项目并将其存储在内存中。

右侧的 listview 使用源项目的标题和发布日期进行填充。它可以排序以适应典型需求。右键单击源项目时,可以打开与该源项目关联的实际在线链接。这在适用时有效。实际上,源项目似乎不需要 <link> 元素,尽管我认为一种回退方案是获取 <guid>,它似乎也是可选的。

单击源项目后,我们会抓取随附的正文(<description>)元素,然后将其包含在简陋的 HTML 标记中,以便 Web 浏览器控件能够理解其 HTML。我们创建一个临时文件名,将内容存储在其中,然后通过发出 Navigate 调用来要求 Web 浏览器控件显示它。所有这些只需几行代码。

从上面的内容可以看出,示例代码只是读取源。它从不编辑、删除或添加新源。但这将是一个很好的补充。欢迎贡献!

使用 API

访问源名称

  FeedStore fs = new FeedStore();

  fs.Refresh();

  foreach(Feed f in fs.Feeds())
  {
    string [] pathsplit = f.Path.Split(new Char [] {'\\'});

    String name = pathsplit[pathsplit.Length - 1];
  }

访问源内容

  Feed f = fs[i];

  f.Open(fs.FeedStorePath);

  String path = f.Path;
  int nbitems = f.Items.Count;

  foreach (FeedItem fi in f.Items)
  {
     ...
  }

访问源项目

  Feed f = fs[i];

  f.Open(fs.FeedStorePath);

  foreach (FeedItem fi in f.Items)
  {
     //fi.Name
     //fi.Date
     //fi.Link
     //fi.Body
  }

为什么要使用 API

目前,此 API 完全是 .NET(与官方 API 使用 tlbimp 互操作基于 COM 的 API 不同),并且在只读取 RSS 存储方面存在明显的缺点。尽管如此,它将反映 RSS 存储的任何更新,这毕竟是通用客户端所期望的。

对其进行改进的地方是能够添加/编辑/删除源。同样,这将通过 IStorage/IStream 机制进行。

RSS 存储同步引擎

默认情况下,RSS 存储中的源使用计划机制自动同步。IE7 工具栏中有一个通用选项,允许您取消选中此选项。尽管出乎意料,即使没有启动 IE7,此功能也能正常工作!

实际上,该引擎是一个名为 msfeeds.dll 的 COM 对象,它被注册为 Windows Explorer 插件和 IE7 插件。SysInternals Process Explorer 显示了它。

RSS 同步引擎在未启动 IE7 的情况下也能工作的原因。

由于 Windows Explorer 始终在桌面运行,这提供了通用的同步机制,以及一个意想不到的传输通道。

为什么是 OLE?

人们只能猜测他们为什么选择 OLE 作为存储基础,特别是当每个源都创建单独的 OLE 文档时。除此之外,由于自动防病毒扫描的副作用,系统的整体性能在同步过程中可能会大大降低。每次触摸文件时,人们都会想知道为什么不使用单个 OLE 文档(毕竟,其中的层次结构可以将所有源和所有源项目存储在同一位置)。或者,既然 ZIP 被认为是解决所有文件格式问题的解决方案(开玩笑),为什么他们不使用 ZIP。它在跨平台(远程同步)方面将如何工作仍有待观察。

历史

  • 2006 年 2 月 5 日 - 文章首次发布

许可证

本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。

作者可能使用的许可证列表可以在此处找到。

© . All rights reserved.