Mad Props!

Omniscience is just a Google-search away.

Login

You're reading Mabsterama, the weblog of Matt Hamilton. Enjoy your stay.

More FeedStoreProvider Goodness

Finally worked the last annoying bug out of my FeedStoreProvider for Windows PowerShell yesterday. If you're interested, I was passing an integer as the first parameter to WriteItemObject() from within my GetChildNames override, and it was causing grief. Always pass strings from there, people!

Anyway, here's my latest trick. Want some stats about your feed subscriptions?

 cd feed: gci -recurse | where {$_ -is [Microsoft.Feeds.Interop.IFeed]} | Measure-Object ItemCount -sum -av -min -ma 

So we're getting all the child items on my "feed:" drive recursively, filtering the list so that we're only talking about feeds and not folders or feed-items, then getting some statistics from the list. The result on my home box:

 Count : 87 Average : 93.551724137931 Sum : 8139 Maximum : 200 Minimum : 2 Property : ItemCount 

So, I'm subscribed to 87 feeds here, with a total of 8139 items. On average, each feed has about 93 items.

Incidentally, I've added a custom parameter to "get-childitem" called "-unread", so you can, if you desire, list out only unread stuff in your subscriptions. That is, folders that contain feeds with unread items, feeds with unread items, and unread feed items. Very handy!

A Common Feed Store PowerShell Provider

After my success yesterday in accessing the Common Feed Store from PowerShell, I started to wonder just how difficult it would be to write a provider for PowerShell so that I could access my feeds as if they were folders and files. You see, in PowerShell, you're not limited to hard drives and files when you use "dir", "cd" etc - you can change into the Windows Registry, or into the certificate store ... all sorts of places.

So I did some reading on MSDN about creating your own PowerShell providers.

A few hours later, and I can now do this:

 cd feed: dir -recurse | where {$_.Modified -gt [DateTime]::Now.AddMinutes(-90)} | ft Title 

... which yields this output:

Title ----- Opening & Saving Word, PowerPoint and Excel 2... Niche Player No More; Apple in the running f... Where's the Cowboy Talk Now? Open Source Music Software & The AGNULA Proje... Zelda:Twilight Princess for GameCube NOT to b... Old buddies reunite in hopes of taking tech w... Fifteen Exercises for Learning a new Programm... LOST - Further Instructions Recap
Engadget's relaunch giveaways: Slingbox PRO w...

In other words, I can list out from the command-line all the items in my feeds that have been updated in the last 90 minutes!

I'll keep working on this provider to give it more functionality. For example, right now you can't use wildcards when you type "dir", and there is no default formatting for feeds, so you need to pipe everything through to format-table to get a nice output. Still, not bad for a few hours' work!!!

TechTalkBlogs Thought Bubble Game

My entry into Mitch's little game. I guess if you don't play the Xbox 360 you might not get it.

TechTalkBlogs Thought-Bubble Game

PowerShell and the RSS Platform

Oh, this is just too much fun. Check this out - a PowerShell script to display the feeds you're subscribed to (in the common RSS store you get with IE7) which have unread items:

 $feeds = (new-object -ComObject Microsoft.FeedsManager); % { $feeds.RootFolder.Subfolders | % {$_.Feeds} | select-object -pr UnreadItemCount, Title; $feeds.RootFolder.Feeds | select-object -pr UnreadItemCount, Title } | where {$_.UnreadItemCount -gt 0} | format-table -au 

I haven't found a "nice" way to combine the output of two commands into one array, but just executing both together inside a scriptblock like this appears to work.

What do you think? It's amazing the sort of stuff you can do in PowerShell!

Update! You can combine the results of two commands into a single array! Here's an updated script:

 $feeds = (new-object -ComObject Microsoft.FeedsManager); @( $feeds.RootFolder.Subfolders | % {$_.Feeds} | select-object -pr UnreadItemCount, Title; $feeds.RootFolder.Feeds | select-object -pr UnreadItemCount, Title ) | where {$_.UnreadItemCount -gt 0} | format-table -au 

And here's the output on my machine right now:

 UnreadItemCount Title --------------- ----- 4 digg 1 Slashdot

IE7 is Out

On Windows XP at least. Read the announcement on the IE Team Blog.

It doesn't seem to be on Microsoft Update yet, but you can download it manually from the IE site.

Haven't seen anything different from RC1 in the final release yet, so it looks like it's mostly bug fixes or performance improvements. Well done to the IE team for shipping!

Command-Line Fun with Windows PowerShell

For the past few days I've been messing around with Windows PowerShell. PowerShell is the next-generation command-line environment for Windows and associated server products (for example, Exchange 2007 will use it as a command-line and scripting interface). It's way beyond anything you've used in a command-line in the past, because instead of passing text from command to command (via a pipeline) you're passing fully-fledged .NET objects.

Let me give you an example!

Let's say you want to know some statistics about lines of code in your source tree. The first thing you need to get is a list of C# files on your drive. No problem:

get-childitem \ -recurse -include *.cs

What are we doing here? Well, first we're using the get-childitem to recursively list every file on our hard drive with an extension of ".cs". The output of get-childitem is not a simple string of text - it's an array of System.IO.FileInfo classes.

So now we need information about the contents of each of those files. How many lines are in each file? Let's pipe our output through to another command:

dir \ -recurse -include *.cs | get-content

The get-content command returns the contents of a file as an array of strings, one for each line. We want to get the length of that array (the number of lines in the file), so let's use that get-content call in a slightly different way:

dir \ -recurse -include *.cs | select-object @{Name="Lines"; Expression={(get-content $_).Length}}

The select-object command selects certain properties from the given object (in this case the FileInfo objects in the array returned by "get-childitem"). We're returning a calculated property called "Lines" which is the number of lines in the file (based on the length of the array returned by get-content).

So now our command is returning an array of Int32 values - the number of lines in every C# file on our hard drive. Last thing we want to do is get some statistics about those numbers:

dir \ -recurse -include *.cs | select-object @{Name="Lines"; Expression={(get-content $_).Length}} | measure-object Lines -av -sum -max -min

And we're done! The measure-object command gives us all the statistics we need. Here's an example of the output from the above string of commands:

Count : 63 Average : 221.587301587302 Sum : 13960 Maximum : 8425 Minimum : 20 Property : Lines

Pretty cool, huh? One line of commands to get a bunch of handy statistics about your lines-of-code.

This is a really simple breakdown of what's possible in PowerShell. Check out the team blog for a more in-depth look at the amazing things this thing is capable of!

Machinima

Y'know the art of making movies using a video game's in-game engine? It's called machinima (or sometimes machinema) - a play on words of both 'machine' and 'cinema'.

I was reading the wikipedia entry this evening and was surprised that they suggest that it is pronounced "ma-shin-e-ma" (that is, with an "sh" for the "ch").

I have always pronounced it "ma-kin-e-ma" - a combination, if you like, of 'machina' (as in the Latin phrase 'deus ex machina') and 'kinema' (an early form of the word 'cinema' which is itself derived from 'kinematics', the science of movement). To me, that pronunciation makes much more sense.

How do you pronounce it? And while we're on the topic, do you have a favourite machinima?

Comicster Screenshots

In case you're interested, I've updated the screenshots on Comicster's site with shots of Comicster's new default skin (and one featuring the Green Goblin skin that you can download from the Skins forum). Check 'em out. Here's a sample to get you started:

Comicster Screenshot

Comicster's New Skin System

For a while now I've been unhappy with the code that allows you to switch "skins" in Comicster. It has grown organically over the past year and a half and has evolved into the C# equivalent on the great Flying Spaghetti Monster. So last night I resolved to rewrite it in such a way that it would be faster, more flexible and easier to maintain.

A bit of back-story: Comicster consists of a main form with a SplitContainer, containing a TreeView on the left and a WebBrowser on the right. Whenever you select a node in the tree, the details of the item represented by that node are rendered as HTML and displayed in the WebBrowser. The HTML itself is read from text files defined by the user (assuming they've created their own skin) which means the entire right-hand pane is completely customizable.

I opened up the three C# files, containing a total of about 2500 lines of code, and hit Ctrl+A, Delete. Now Comicster had no skin system whatsoever. Of course, nor would it compile. So, I spent a while making sure that the classes (Skin, UISkin and ExportSkin) were defined, and that they implemented the minimum methods and properties to get Comicster compiling and running. So now I had a version of Comicster that ran, but showed a blank screen when you selected an item to view.

The next step was to write a class that I could use over and over again, which could search for custom tags within a string. I ended up creating a new class that I called HtmlContentProvider. It looks something like this:

public class HtmlContentProvider 
{
    /// Occurs when a custom tag is encountered within the template.
    public event EventHandler<CustomTagEventArgs> CustomTag; 

    /// The template used for the HTML body content  
    public string Template 
    { 
        get { /* ... */ } set { /* ... */ } 
    }

    /// Determines whether to use reflection to automatically 
/// default the custom tags
/// to the value of the corresponding properties of the subject. public bool AutoFill { get { /* ... */ } set { /* ... */ } } /// Returns the body template with custom tags replaced
///
with content derived from 'subject'. public string GetContent(object subject) { /* ... */ } }

So what I have now is a class that can find tags like <#name> inside an HTML template, and, given an object to read from, can replace those tags with values from the object. It can even handle attributes, so <#name default="No Name"> works just fine. It uses a fairly complex regular expression, as you may have guessed.

Now that I had a reusable class I was able to flesh out the base Skin class. It contains one of these HtmlContentProviders for each kind of item that Comicster can display, and a bunch of event handlers for the CustomTag events of these providers.

The end result is a much cleaner code base which uses a lot of shared code and virtual methods with overrides in descendant classes. It's about two thirds of the original amount of code, which can only be a good thing.

This is going to make it really easy to add arbitrary attributes to certain custom tags. For example, if I want to allow a skin to specify the way in which it needs a title's list of issues rendered, I might use a special attribute like <#issues render="li"> or <#issues render="table">. That sort of thing.

Domain Objects and/or DataSets

I've been thinking recently about how I might approach the development of a completely new version of Comicster.

Right now, Comicster uses an in-memory typed DataSet to store your collection, and when you save, it streams the DataSet (using WriteXml) to a compressed file on disk. That system works really well, but ideally I'd like to move away from DataSets internally and come up with an object model, making use of .NET 2.0's (and WPF's) object binding.

So I've thought about all the various classes this hypothetical new program might have: Folder, Title, Issue, Character, Creator etc. No problems there. But then I started thinking ... each issue has a cast of characters. Likewise, each "team" (eg X-Men) also has a list of characters. How many times would I want the same character (eg Wolverine) instanced in memory? Ideally only once. That means that I either have to have object references all pointing back to the same instance of Character, or I have to use a field like CharID and look the character up in a global list of characters.

The latter approach, however, is exactly what my typed DataSet does - it stores a bunch of in-memory 'tables', and each 'row' has foreign-key references to other 'rows'.

So I'm kind of back to square one. Unless ...

What if I used a typed DataSet as an internal storage mechanism, but only ever surfaced objects to the UI? Like, have some sort of Collection object with methods that enumerate titles or characters, returning them as instances of my domain objects, but internally it's constructing these objects from the same tables that I've always used?

I wonder if that could work. I wonder if there's any benefit to doing it that way. Certainly the idea of wrapping all of that up into its own satellite assembly and having the UI know nothing about DataSets sounds intriguing.

What do you think? How do you represent your domain objects in memory?