My first (non-trivial) Windows Live Writer Plugin

So the Live Writer Plugin model is so cool and easy that I had to write a plugin. (and do it with Edit-and-Continue). The obvious ones were already done (eg, Paste code from VS), so I scratched my head for an idea and I finally got one: a “verse of the day” plugin. This

  1. gets an RSS feed from (in this case
  2. parses an item from the RSS feed containing the verse, using specific knowledge of how the xml at the URL above is laid out. I’m just using XmlDocument here instead of the new fancier Xml libraries.
  3. formats it into an HTML string.
  4. inserts that into the blog.

And for bonus points, overrides the Plugin’s Option Dialog to provide a dialog that shows extra diagnostic information.

Example output is:

1 Samuel 16:7“But the LORD said to Samuel, “Do not consider his appearance or his height, for I have rejected him. The LORD does not look at the things man looks at. Man looks at the outward appearance, but the LORD looks at the heart.”

Brought to you by Copyright (C) NIV. All Rights Reserved.


(end of example output).

Here’s the code snippet. I only tested this for for a few minutes and am not alleging this to be bullet proof:

// Simple Windows Live Writer extension for showing a Verse-of-the-Day.
// This gets the verse via an RSS feed from BibleGateway.
using System;
using WindowsLive.Writer.Api;
using System.Windows.Forms;
using System.IO;
using System.Xml;

namespace VerseOfTheDay
    // Plugin to take all URLs and convert them to all uppercase.
        "Verse Of The Day", 
        Description="Insert a 'Verse of the Day' from BibleGateway",
    [InsertableContentSourceAttribute ("Verse Of the Day", SidebarText="Verse of the day")]
    public class MyExt : ContentSource
        #region Configuration
        // This is the URL for the RSS feed that provides the content.
        static string s_SourceUrl = "";
        static int s_TimeoutSeconds = 5;
        static string s_FormatString = "<table border=1><tr><td><b><a href={0}>{1}</a></b>{2}</td></tr></table>";
        #endregion // Configuration

// LiveWriter calls this when the "Options" button is selected in the plugins menu. // This would let us have a dialog to configure options for this plugin. public override void EditOptions(IWin32Window dialogOwner) { // Show settings. // We could be fancier and allow editing the settings, and persisting them to a file. string caption = "Settings for 'Verse of the Day' PlugIn"; string text = string.Format("RSS feed to get verse from: {0}\r\nTimeout when reading RSS feed:{1} seconds\r\n\r\nHTML Format String (args 0 is a URL to the verse, arg 1 is the title, arg 2 is the verse contents):\r\n{2}", s_SourceUrl, s_TimeoutSeconds, s_FormatString); MessageBox.Show(dialogOwner, text, caption); } XmlDocument GetRssFeed(string url) { // Use LiveWriter Services to make the HTTP request. // - this lowers the security requirements for the plugin, // - cooperates with Internet configurations in LiveWriter. PluginHttpRequest request = new PluginHttpRequest(s_SourceUrl); Stream s = request.GetResponse(s_TimeoutSeconds * 1000); // throws on timeout. if (s == null) throw new InvalidOperationException("Couldn't retrieve data from " + s_SourceUrl); StreamReader sr = new StreamReader(s); string xmlString = sr.ReadToEnd(); // gets the XML. // Parse the XML to get the verse. // The XML is an RSS feed with 1 item, containing the "verse of the day". XmlDocument doc = new XmlDocument(); doc.LoadXml(xmlString); return doc; } // This is invoked by LiveWriter when the user chooses this plug-in from the insert menu. public override DialogResult CreateContent(IWin32Window dialogOwner, ref string content) { // Get from verse via BibleGateway. // The XML is an RSS feed with 1 item, containing the "verse of the day". XmlDocument doc = GetRssFeed(s_SourceUrl); XmlElement item = doc.LastChild["channel"]["item"]; string title = item["title"].InnerText; string verse = item["content:encoded"].InnerText; string link = item["guid"].InnerText; // Format the information and return as an HTML string. content = string.Format(s_FormatString, link, title, verse); // Return success. return DialogResult.OK; } } }


 To build  it, include a reference to WindowsLive.Writer.Api.dll in the WLW installation directory. For example, from the command line, if the above is named class1.cs:

csc /t:library Class1.cs /r:”C:\Program Files\Windows Live Writer\WindowsLive.Writer.Api.dll”


Next up: playing around to get it on Gallery.

Comments (9)

  1. You think this is a new one? :-)

    I had the same idea some time ago, when I first tried writing LiveWriter plugins, but I used the feed from It seems competition is starting :-)

  2. Luciano says:

    an example taken from the bible???

    Why not form something MORE TOPICAL on a TECHNICAL blog???

  3. jmstall says:

    Henning-  I know it’s not a novel idea; I just didn’t see one on the gallery at the time I looked. I expect that there will be lots of others soon, and they’ll all be better than this one. :)

    Luciano – writing a plugin, reading an RSS feed, extracting an item, showing how to compile it, etc meets my technical bar. I believe this will be a useful example to others.

  4. Josh Stodola says:

    Liciano – this is a technical post, you moron.  Do you not see the many lines of code posted?!  Would you find this code in your churches sermon bulletin?  I dont think so! Soooo, what is your problem?  You have a problem with using the Bible in a programming venture?   Pfff…..

    Nice post, and an overall good implementation.  Thanks!

  5. My first Windows Live Writer (WLW) PlugIn is now published on the WLW Gallery of Plugins. You can download

  6. My first Windows Live Writer (WLW) PlugIn is now published on the WLW Gallery of Plugins. You can download

  7. Here&#39;s a WiX install script to build an MSI to install a Windows Live Writer (WLW) plugin dll, by

  8. Windows Live Writer (WLW) is awesome. And writing PlugIns for WLW is easy . Combine the two and you just