The inaptly named Windows RSS Platform is actually part of IE7, not part of Windows, and therefore is available on Windows XP if IE 7 has been installed, as well as on Windows Vista (where IE 7 is included originally). However, having said that, it isn’t just for IE: it includes a complete COM API which is usable from script or the .Net Framework, and the header files are part of the Windows Platform SDK and usable from C/C++.

The RSS Platform is intended to introduce a unified approach to RSS for Windows applications, where all applications use the same RSS feed store, and a service handles downloading the RSS feeds — including enclosures if requested — and normalizes them so applications need not handle parsing all the different feed formats (that is, you only need to parse the Microsoft-normalized RSS 2.0 with extensions).

As a platform for building RSS-based applications, it’s very well done, and well thought out. It’s now ridiculously easy to create an RSS reader, since the platform removes all need to parse XML except in the weirdest situations, and allows all applications to be instantly integrated on the same list of RSS feeds … let me show you ….

I’ll be using the RSS Platform in my SOM Recommender project, so I’ll have some more sample code I can share later on, including use of some of the events (there are events for all the things that could happen to feed folders or feeds themselves, including creations, renaming, deletion, etc). At the very least, you’d want to check out GetWatcher method (see the examples) and the FeedItemCountChanged and FeedDownloadCompleted events.

For now, I have a very simple example: a single function which exercises some of the most interesting methods in the API, but doesn’t use any of the events for detecting the arrival of new feed items nor the asynchronous download feature. This simple example is a console application which will fetch a feed. As you can see, it parses the command line for the url and name parameters.

Once you’ve specified a feed by name and URL, it will be stored in the “RssMe Feeds” folder so you can just refer to it by name in the future. However, there’s one major problem with that: the FeedStore doesn’t have a concept of aliases or shortcuts, and the feed URLs have to be unique, so if you’ve already bookmarked a feed, RssMe would be able to show you the items from it, but not pull it up by name, unless you specify the full path to it. Honestly, this is the most frustrating thing to me (as a developer, and as a user) about the feed store: what I’d like to be able to do is add a feed in multiple folders and have them automatically share the “read” state of the items.

That would allow applications to create a subfolder (as RssMe does) and rely on it as a way of organizing the feeds they use. As it is, if third-party applications want to use only some of the feeds in the feed store, they will have to keep a list of URLs separately since they may not be able to add the feed to their own folder if it’s already in the store elsewhere. Once they’ve done that, they can just retrieve them by URL from the store.

Although the source code is inline below, you can download the Visual Studio 2005 project which can be compiled by just running msbuild (that’s in your Microsoft.Net\Framework folder in C:\Windows … for some reason it’s not on the path, so you’ll probably need to type the whole path. If you’re not familiar with MSBuild, try the /help argument ;) but you can specify that you want to build the “Release” build by just running: MSBuild /p:Configuration=Release assuming you’ve fixed the path problem). Or you can download the compiled example

The command-line for this sample app is basically:

  • RssMe /url:http://huddledmasses.org/feed/atom/ /name:HM.O
  • RssMe /url:http://del.icio.us/rss/ /name:"Delicious Recent"
  • RssMe /name:HM.O


using System;
using System.Text;
using System.Collections.Generic;
using Microsoft.Feeds.Interop;
using System.Text.RegularExpressions;

// A simple test of the IE7 "Windows RSS Platform"
namespace RssFeedDemo
{
class RssMe
{
static int Main(string[] args)
{
  string feedName = null, feedUrl = null;
  string fldrName = "RssMe Feeds";
  int result = 0;

  // Everything comes from the FeedsManager
  FeedsManager mgr = new FeedsManagerClass();
  // And everything is inside the RootFolder
  IFeedFolder root = (IFeedFolder)mgr.RootFolder;
  // Specifically, all the feeds are ...
  IFeed feed = null;

  #region process the command-line arguments
  Regex re = new Regex(
    @"(?:(?:/url:\s*""?(?:<url>https?://\S+)""?\s*)|" +
    @"(?:/name:\s*""?(?:<name>\S+)""?\s*))+");
  Match mx = re.Match(string.Join(" ", args));
  if (mx.Success)
  {
    if (mx.Groups["url"].Success)
    {
      feedUrl = mx.Groups["url"].Value;
      // Access feeds by URL ...
      feed = (IFeed)mgr.GetFeedByUrl(feedUrl);
    }
    if (mx.Groups["name"].Success)
    {
      feedName = mx.Groups["name"].Value;
      // if they specified only the name
      if (!mx.Groups["url"].Success)
      { // we assume they already stored it previously
        if (mgr.ExistsFeed(fldrName + "\\" + feedName))
        {
          feed =(IFeed)mgr.GetFeed(fldrName+"\\"+feedName);
        }
        else if (mgr.ExistsFeed(feedName))
        {
          feed =(IFeed)mgr.GetFeed(feedName);
        }
      }
    }
  }
  else
  {
    Console.Write(
@"You should specify the url and/or name of the feed:
    rssme /name:delicious /url:http://del.icio.us/rss/
Once you've defined a name and url, you can just use:
    rssme /name:delicious

Please specify a name for this feed:
> "
);
    feedName = Console.ReadLine();
    if (feedName.Length == 0) return 1;
    // Try getting the feed by it's expected path...
    if (mgr.ExistsFeed(fldrName + "\\" + feedName))
    {
      feed = (IFeed)mgr.GetFeed(fldrName + "\\" + feedName);
    }
    else
    {
      Console.Write(
@"Please specify an http Url for this feed:
> "
);
      feedUrl = Console.ReadLine();
    }
  }
  #endregion process the command-line arguments

  // if the feed doesn't already exist ...
  if (null == feed)
  {
    // Test for the existence of sub folders
    IFeedFolder somrFeeds = null;
    if (root.ExistsSubfolder(fldrName))
    {
      somrFeeds =
         (IFeedFolder)root.GetSubfolder(fldrName);
    }
    else
    {
      // and you can create folders very easily too
      somrFeeds =
         (IFeedFolder)root.CreateSubfolder(fldrName);
    }
    // Here's the catch:
    // Each URL can only be in the storage once!
    // So, try getting the feed by it's URL
    feed = (IFeed)mgr.GetFeedByUrl(feedUrl);
    // if we found the feed by URL, but not by name
    // we won't be able to (re)create it in here ...
    if (null != feed)
    {
      Console.WriteLine(
@"Couldn't save this feed with that name because it "
+ @"already exists in another location.");
      result = 2;
    }
    else
    {
      // Create a new feed specifiying a name and url
      feed = (IFeed)somrFeeds.CreateFeed(feedName, feedUrl);
      feed.MaxItemCount = 0; // store all the items
      // If you wanted to download enclosures...
      // feed.DownloadEnclosuresAutomatically = true;
      // Override the default synchronization schedule
      feed.Interval = 60; // specify interval in minutes
      feed.SyncSetting = FEEDS_SYNC_SETTING.FSS_INTERVAL;
      // Manually download it for starters
      feed.Download();
    }
  }
  // You can check how many items or unread items
  int itemCount = feed.ItemCount;
  int readCount = itemCount - feed.UnreadItemCount;

  // You can use .Items in a foreach loop
  IFeedsEnum items = (IFeedsEnum)feed.Items;
  // But it would force starting from the oldest
  for (int index = readCount; index < itemCount; ++index)
  {
    IFeedItem item = (IFeedItem)items.Item(index);
    // Access the item.Xml if you need to, or use the
    // title, link, description, comments, etc...
    Console.WriteLine(item.Title);
    Console.WriteLine(item.Link);
    Console.WriteLine("=================================");
  }
  // Once we've processed them, mark them as read.
  feed.MarkAllItemsRead();
  // Some extra information
  Console.WriteLine(string.Format("{0} unread out of {1} "
    + "total items in RSS Platform storage."
    +"\nPress ENTER to continue.\n",
    itemCount - readCount, itemCount));
  Console.ReadLine();
  return result;
}
}
}
 

Comments are closed.