personal comments edit

Well, Christmas is over, it’s the New Year, and it’s time once again to look back and see what went on for me in the last 365 days or so.

January 2008

I started January by updating my multi-user iTunes instructions to account for Vista and adding some similar multi-user instructions for Picasa. This setup is still working well for me today, in fact. We signed up for Verizon FiOS to save a little money and get a better Internet connection. Not sure if we’re actually saving that much, but the Internet connection is pretty cool. Now, if only they’d increase their HD on-demand offerings. Finally, I ended the month with Xbox problems, which is not uncommon for me.

February 2008

Lots of interesting developments happened with Typemock Isolator in February, particularly the addition of debugger integration, which is awesome. In the spirit of that, I blogged about how to get Isolator, NCover, and NUnit all playing nicely in MSBuild as well as a template for doing some quick Typemock Isolator testing. I fixed an issue with Sandcastle Help File Builder having multiple versions of the same dependency by creating a plugin.

March 2008

March saw me working a lot with Windows Workflow Foundation. I created a small series of articles called “Two Minute WF” to give a high-level overview of some of the things I found. We went to see the Cirque du Soleil show, “Corteo,’ which is fantastic and you absolutely must see it. We also had to get some birds pulled out of our eaves because they were nesting.

April 2008

We started the month by hitting the Shrine Circus, which I hadn’t been to since I was a kid. I posted a quick start for learning to use Typemock Isolator and played around with an Isolator-based product called “Ivonna” for testing ASP.NET pages. I also spoke at Innotech Oregon about Unit Testing with Typemock, which was a great experience - my first conference speaking gig. I started getting into Twitter enough to care to optimize my Twhirl experience. I figured out how to use the Composite Web Application Block without the whole Web Client Software Factory. Our printer went out, so I started looking at new ones but really didn’t find anything. Finally, we saw Jonathan Coulton in concert (and have tickets to see him again this month).

May 2008

May began with me spending a week in Liberty City. I love a good week of GTA, these being so fun, relaxing, and, frankly, cheap that most other vacations can’t beat it. That said, I used the Xbox until it pretty much killed the DVD drive, so I had to send it in and get my fifth Xbox 360. I was named a Typemock Expert (which is similar to the Microsoft MVP program, but for Typemock) - a real honor. At the end of May, we lost our kitty Jack to epinephrine reversal, which is extremely rare in cats. We still miss him.

June 2008

In June I finally stepped into the now and stopped carrying a separate cell phone and PDA, opting for the BlackBerry Curve. I still really like it, though I still have weird issues sometimes with the desktop synchronization software - something I never had a problem with when I was using a Windows Mobile PDA. I really started feelilng some slowdown issues on my work computer so I did a little research on the performance impact of full-disk encryption. I’m all for security, but I still think we need to have some faster hardware to compensate for the software overhead we’re required to keep. I showed you how to build a dynamic dependency list for an FxCop project using MSBuild. Finally, Dr. Horrible’s Sing-Along Blog was announced, and has turned out to be a web phenomenon. If you haven’t seen it, you owe it to yourself to take the time to go watch. I promise, you won’t be disappointed.

July 2008

In July I figured out how to fix the odd sign-in delay to Xbox Live that I was seeing - reboot the router. This is a trick that I still use… in fact, I had to do it last night. We saw Wall-E, which is my favorite Pixar movie so far. I’ve seen it a couple of times since and have it on Blu-ray. Love it. We did the Independence Day fireworks shoot in Walla Walla, WA, which was, as always, hard work but lots of fun at the same time. Plus, it’s always good to see my friend Greg and the rest of the fireworks gang. Once a year is just not enough. That said, I think we’ll be doing something a little closer to home this year if we can - Washington shows don’t count toward my pyro license renewal, and driving that far is really hard. (I’m not a big “car trip” person.) We got two new kittens, Kai and Stanley, and they have turned out to be real wild men. I moved my CR_SortLines and CR_JoinLines plugins into the DXCore Community Plugins project. I also released CR_Documentor 2.0 which included not only a Sandcastle preview style but also was my first release with CR_Documentor as open source. Since then, I’ve released a few bug fix builds and made the internal rendering engine much stronger, all with help from the community. (I’m always looking for contributors, so come on by and help if you can!) Finally, I turned 32. I don’t feel 32, but, well, I guess that’s just how it is.

August 2008

I started the month with a little epiphany about thinking in the abstract. I tried upgrading my blog to Subtext 2.0 and failed due to some permissions issues (which I believe have since been rectified… but I’m a little scared to try again since the previous attempt brought my site down for a couple of days). While I was working with it, though, I slimmed down my database, which had grown a lot and was bumping up against my alllocated size limit. Some things happened in my little circles of the tech world - Typemock Isolator announced an open source license and .NET Reflector got transferred to Red Gate. I picked up a Windows Home Server (which I still love) and I completed Grand Theft Auto 4 100%. Finally, I went on a team building field trip with the folks in my group and we had a blast. I have to say, the group I’m in is a fantastic team and I’m really proud to be with them. Great manager who really cares for the group, great team who comes together and really takes care of business. Best of the best.

September 2008

In September, besides my car getting hit, the big happening of note was that I finally solved my media server problem

  • all of my DVDs are now stored on a central server in VIDEO_TS format (so they’re not just the movies - they’re also disk backups) and can be played from a home theater PC in the living room. This was a lot of research and effort, but it turned out really well and has been really super cool to use. I can finally access my movies in the same way I can access every CD I have through my iPod and iTunes. (I have since found little issues that I’ve either solved or am working on solving, like some minor stuff with Vista not sleeping properly and the fact that my TV runs at 1366 x 768 but the HTPC outputs at 1280 x 768.)

October 2008

We started out by having some barkdust blown into our flower beds, something long overdue. We then spent a week in Disneyland and Legoland, which was simply amazing and tiring and fun all at the same time - a great vacation. I put a stick through my original Rock Band drums (and later ordered the Ion Drum Rocker kit, which has been so cool - I posted a comparison of the Ion drums vs. original Rock Band vs. Guitar Hero World Tour and the Ion drums are by far the superior choice). Oh, and we had 237 trick-or-treaters this year, a record. On a technical note, I posted some FxCop rule recommendations based on what works for me.

November 2008

After having participated in 2007 in the “Give One, Get One” program for the XO “One Laptop Per Child” program, I hadn’t done much with my XO laptop so I got the gumption up to get Ubuntu running on it. I showed you how to find tracks missing artwork in iTunes, and I also showed you how to read WCF configuration from an alternate location.

December 2008

Slightly late to the game, I realilzed what it takes to force ASP.NET 3.5 on IIS6. I posted a database maintenance page for Subtext to make trimming down the database size a little easier. (Remember the work I did in August?) I started running into a few problems with companies that think “Release Early, Release Often” also naturally implies that the external customer can take every upgrade that comes along without any cost. I had a little fun with the Amazon Universal Wish List button. I got my first 100% on drums in Rock Band. I talked a bit about storing configuration settings behind a WCF service. The year ended with a severe case of cabin fever after having been snowed in for several days.

Christmas was actually sort of spread out because of the snow (we’re still seeing presents we ordered for people trickling in via mail and UPS) and we weren’t able to get together with people because everyone was trapped, so the whole holiday felt a little weird. We still had a lot of fun and were able to see folks over the course of the following week, and everything was cleared up by New Years, when we went to a fun non-party party at our friends Jason and Tracy’s place.

As for the upcoming year, I suppose I have a few resolutions. I would like to try to blog more. Both more technical and more personal stuff, since I have a mixed audience (though I realize that sort of means “jack of all trades, master of none”). I’d like to get together more often with our friends - Angela and K, Jason and Tracy, Jason and Liz - and see some of the folks I don’t see nearly often enough a bit more often. I’d like to get better on the Rock Band drums, which sounds sort of dumb, but I didn’t go to band in high school so this is sort of my chance to learn to play an instrument, albeit a “fake instrument,” and see if it might be worth investing in getting the real electronic drum brain for my Ion kit. I’d like to take more time to do some of the hobbies I’ve let go - I used to draw, I used to do more art projects, I used to read more… it’d be nice to get back to some of that.

Anyway, 2008 was pretty good. 2009 looks to be interesting not only on a personal level, but on a global one - Obama’s been elected, the economy’s in the crapper, and we’re generally on the cusp of some major change. It’ll be an interesting time to see how it plays out. It makes me wonder if folks during the 60’s felt this same sort of feeling in the air of things changing and major events happening.

personal comments edit

The snow on the bush shows how deep it is - that bush is flat on top.

From Arctic Blast 2008

I am going out of my fucking mind with this snow. I hate snow.

Seriously. I’ve been stuck at home for like four days now and the snow just keeps getting deeper, indicating that I’m going to be stuck here until time ends, or at least until next weekend when it’s supposed to get warmer and melt off a bit.

Yesterday ended with about 10” of snow and a quarter-inch sheet of ice on top of that, so you had to break through the ice if you wanted to walk around.

I tried to take the garbage out yesterday, but I can’t because the snow has piled up so high I can’t get the gate to the cans open. I’ve repurposed a recycling bin as a temporary garbage holding area until I can get to the cans. No, the irony of using a recycle bin as a garbage can is not lost on me.

The local news stations are calling this “Arctic Blast 2008.” I guess they all get together and decide what to call various weather systems so the reporting is consistent. I guess “Arctic Blast” is as good a name as any.

I’ve been able to work from home, but Jenn’s stuck at home and unable to work, which means I’m in here sitting at the kitchen table, destroying my back in these crappy chairs, trying to do tasks that require a lot of in-person collaboration without actually getting together in person with people, and she’s in the other room playing Lego Batman. I wanna play Lego Batman and not work. There are so many other things I can imagine doing at home that don’t involve work. I have months of comics backed up that I could read. Movies to watch. Games to play. Cats to pet. (OK, I admit I pet the cats while I’m working at home.)

Anyway, working at home is a motivational challenge. I’d much rather be in the office since then I could get my collaborative work done and not be distracted by, say, a kitten jumping out of the Christmas tree like the squirrel in Christmas Vacation.

Speaking of Christmas Vacation, Jenn and I have been watching holiday movies the last few days and I have to say, I think that and A Christmas Story are possibly the best holiday movies ever made. Ever. In fact, here’s my top five list:

  1. Christmas Vacation
  2. A Christmas Story
  3. Die Hard
  4. Elf
  5. Emmet Otter’s Jug-Band Christmas

You’ll notice there aren’t any of the old “classics” on there like Miracle on 34th Street or It’s a Wonderful Life. I’m just not into them. I mean, I’ll watch, but for various reasons, watching Die Hard (the original) is what really says, “It’s Christmas!” to me.

The house is somewhat decorated for Christmas. Our new kittens, Kai and Stan, are pretty destructive little beasts, so we’ve been slowly introducing things to them in an effort to “warm them up” so they don’t just go apeshit and destroy everything. We figured that we couldn’t hang the stockings from the fireplace because the hangers were only really made to support the weight of the sock and a few small gifts, not the weight of a kitten, so we’ve got them hung by the stairs. We had to use nylon rope to hang them because they chewed through the ribbon we started out with and the string we subsequently replaced the ribbon with. We have a fake tree and the bottom row of branches is totally bent down and looks horrible because the kittens “ride” the branches and attack them. (You wouldn’t think they could break off metal branches, but they did break a piece of one off.) Jenn put gifts under the tree and the kitties have been helping by chewing the living crap out of the bows. I’m surprised the packages are still wrapped.

Kai and Stan learn about snow.

From Arctic Blast 2008

We introduced the kittens to snow, which was pretty funny. They’re indoor kittens so they really don’t get to experience some of that stuff first-hand. We filled up a Tupperware bowl full of snow and brought it in. They dig around in it, pull some out onto the floor, shake their paws (it’s cold!), and then smack the snow across the floor. They’ll watch it go, then dig some more out and the process continues. They pretty close to emptied that bowl of snow out onto the floor.

Let’s see, what else has gone on during the snow?

Our Scooba broke. I think the pump in it went bad. It just puts this blue light on, the equivalent of your car’s “Check Engine” light. After jumping through a few support hoops, it turns out Scooba is no more. Lame. Now I need to decide if we want to replace it or not. They have an out-of-warranty replacement program that gets you a new robot for a steep discount and I’ll probably be participating in that. I really like the Scooba and it does a pretty decent job. In the meantime, I guess we’ll mop the old fashioned way.

The movies we’ve been watching have mainly been through my media server, just proving the functionality, which is really cool. Having access to the movies is really nice and super convenient.

Cookies, cookies everywhere!

From Arctic Blast 2008

Jenn’s been making a lot of cookies and baked goods while we’re stuck at home. A lot of cookies. They’re freaking everywhere. Counters, cupboards, fridge…

Needless to say, I’m probably not eating as healthy as I should be. I had a rum ball for breakfast this morning as Jenn was yelling in from the other room, “That’s not a breakfast food!” Hmmm. I guess it is now.

That and egg nog, some of which my cat is being very persistent about trying to get.

Oh, here’s an entirely unrelated story but something I was going to blog anyway. We had a cat pooping on the floor next to the litter box. Not sure why, but it’d always be right next to the box. Pee in the box, poop outside the box. Couldn’t figure out why.

Talked to the vet, and there are two reasons a cat will do something like that: medical or behavioral. Since the poop was solid, it wasn’t medical, so we figured it was behavioral.

Behavioral reasons include the cat not feeling safe in the box, the cat not liking the litter, the box being inconveniently located, and so on. So, to address all of these things, we added a second box in a different corner of the room and made sure there was no top on either box so no one would feel “pinned in” or anything - your choice of location, easily escapable, for your pooping pleasure. We also put a Feliway plug-in there in case the kitties were feeling nervous. (Feliway is a cat pheromone analog that calms cats down. Humans can’t smell it.) None of this stopped the issue. You know what it was?

Box not big enough.

We had two pretty big boxes (the large size at the store) but our new kittens are serious diggers - like little steam shovels. The vet recommended we get a bigger box, just to see. We ended up getting this thing that resembles a gigantic Rubbermaid storage container. Takes 25 pounds of litter to fill. But you know what?

No more poop on the floor.

So there you go.

Anyway, that’s about it going on around here. Cabin fever has set in, and we’re waiting for the snow to go.

Here’s wishing you and yours peace and love for the holidays.

Kai and Xev take a
nap.

GeekSpeak comments edit

A few months ago I was looking for a replacement printer and scanner. I tried out a couple of all-in-one solutions (Canon PIXMA MX850 and HP C7280) and was consistently disappointed in the scan quality so returned both of them and decided to get a separate printer and scanner.

HP Photosmart
D7260For the printer, I ended up getting an HP Photosmart D7260.

The quality on it is amazing, just like the C7280 was, but for $70 cheaper and with a better LCD screen on it. The D7260 can connect directly to your network over ethernet, which is how I have it hooked up, and it lets me sit in the living room with the laptop and print wirelessly over the network - nice. There are slots for several different memory card types right on the front, too, so you can take the card out of your camera, plug it right into the printer, and print directly from there - no need to load the photos on your computer first.

Something else I noticed just the other day that was kind of cool: My PS3 has a “printer settings” section that I never looked at. I went in there, told it to search for printers, and it was able to locate and connect to the D7260 over the network with no issues. I’m not sure what I’ll be printing from my PS3, but the neat factor is definitely there.

I’ve only had two problems with it, both of which are minor:

First, for a while I was having troubles getting the paper to feed and thought the rollers might be messed up. Turns out the paper was sort of bunched up and wouldn’t easily separate. Putting different paper in fixed that.

Second, this thing is loud. I’m not talking like “Xbox 360 cooling fan” loud, either. This is like “one wood chipper being fed through another wood chipper” kind of loud. Whenever you print, it wakes up and goes through some initialization gyrations, which sound like metal grinding metal. The print happens, which is not too loud, and then when it’s done it goes through something that sounds just like the initialization actions. If you can ignore the noise, this thing is pretty cool.

media, tv comments edit

We were talking today about Sesame Street and the Muppets and some of the stuff that we got traumatized with as children watching TV in the US and I remembered the dancing slinkies - one of my favorite Muppet skits next to classic Mahna Mahna.

wcf, gists, csharp, dotnet comments edit

One of the challenges I’m facing in the project I’m working on is that we want to store configuration values for the system in a central location that can be accessed via a service… but that’s not how most .NET developers are used to working with configuration. Most folks are used to ConfigurationManager or WebConfigurationManager, something like this:

NameValueCollection config = (NameValueCollection)WebConfigurationManager.GetSection("mySection");
this.SomeObject.Value = config["key"];

That’s great if everything is stored in your app.config or web.config, but if you’ve got everything behind a service, it’s trickier. You’ve got to get a proxy to your service, get the approriate values, handle exceptions… it’s a lot messier, and if you’re trying to get a bunch of devs up to speed using that, it’s going to take a bit. Wouldn’t it be nice if they could just use the stuff they’re used to?

There are a couple of ways that can happen.

First, you can use a ProtectedConfigurationProvider implementation. You might be used to seeing these in the form of things like the RsaProtectedConfigurationProvider that you’d use to store settings encrypted in your configuration files. The cool thing is, the ConfigurationManager doesn’t really care what’s stored in the <EncryptedData> element in your config. For example, when you use the RsaProtectedConfigurationProvider, you’ll see something like this in your config file:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <mySection configProtectionProvider="RsaProtectedConfigurationProvider">
    <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
      xmlns="http://www.w3.org/2001/04/xmlenc#">
      <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
          <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
          <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
            <KeyName>Rsa Key</KeyName>
          </KeyInfo>
          <CipherData>
            <CipherValue>(encrypted data here)</CipherValue>
          </CipherData>
        </EncryptedKey>
      </KeyInfo>
      <CipherData>
        <CipherValue>(encrypted data here)</CipherValue>
      </CipherData>
    </EncryptedData>
  </mySection>
</configuration>

But everything inside <EncryptedData/> is entirely up to the configuration provider. Since you can define your own providers, what if you did something like this:

<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="mySection"
      type="System.Configuration.AppSettingsSection, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
  </configSections>
  <configProtectedData>
    <providers>
      <add name="ServiceConfigurationProvider"
        type="Framework.ServiceConfigurationProvider, Framework"
        endpointName="WSHttpBinding_IConfigurationService"/>
    </providers>
  </configProtectedData>
  <mySection configProtectionProvider="ServiceConfigurationProvider">
    <EncryptedData>
      <values>
        <value key="value1"/>
        <value key="value2"/>
      </values>
    </EncryptedData>
  </mySection>
</configuration>

See what we have there?

  • A custom section that (for simplicity) is just a key/value section like AppSettings.
  • A custom protected config provider that has a special extra configuration property - an endpoint name (that would correspond to something in your <system.serviceModel> configuration).
  • A section that uses the configuration provider you specified… and notice how the contents of the <EncryptedData> are simply keys? These are the values you’d want to retrieve from your configuration service.

So how would you do it? You could implement a provider that looks like this:

using System;
using System.Configuration;
using System.Xml;
using System.Xml.Linq;
using System.Collections.Generic;
using System.Reflection;
using System.ServiceModel;
using System.Text;

namespace Framework
{
  public class ServiceConfigurationProvider : ProtectedConfigurationProvider
  {
    public string ServiceEndpointName { get; set; }

    public override XmlNode Decrypt(XmlNode encryptedNode)
    {
      List<string> keysToRetrieve = new List<string>();
      foreach (XmlNode value in encryptedNode.SelectNodes("/EncryptedData/values/value"))
      {
        XmlAttribute keyAttrib = value.Attributes["key"];
        if (keyAttrib != null && !String.IsNullOrEmpty(keyAttrib.Value))
        {
          string key = keyAttrib.Value;
          if (!keysToRetrieve.Contains(key))
          {
            keysToRetrieve.Add(key);
          }
        }
      }

      ChannelFactory<IConfigurationService> factory = new ChannelFactory<IConfigurationService>(this.ServiceEndpointName);
      IConfigurationService service = factory.CreateChannel();
      AppSettingsSection section = new AppSettingsSection();
      foreach (string key in keysToRetrieve)
      {
        section.Settings.Add(key, service.GetValue(key));
      }
      XmlDocument doc = new XmlDocument();
      StringBuilder builder = new StringBuilder();
      using (XmlWriter writer = XmlWriter.Create(builder))
      {
        typeof(AppSettingsSection)
        .GetMethod("SerializeToXmlElement", BindingFlags.Instance | BindingFlags.NonPublic)
        .Invoke(section, new object[] { writer, "root" });
      }
      doc.LoadXml(builder.ToString());
      return doc.DocumentElement;
    }

    public override XmlNode Encrypt(XmlNode node)
    {
      throw new NotImplementedException();
    }

    public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
    {
      this.ServiceEndpointName = config["endpointName"];
      base.Initialize(name, config);
    }
  }
}

Note that, in the above, there’s a lot I’m not doing to keep it simple - I’m not properly closing the service channel, I’m not handling errors in the call, etc. It’s for illustration purposes. I’m also doing some reflection magic to get the AppSettingsSection to serialize to XML so I don’t have to manually do it. Wouldn’t that be nice if it was public?

The point is, you can use the protected configuration provider mechanism to store things elsewhere - service, database, etc. Consuming something like this would look exactly like the previous example. You’d literally never know the difference as a consumer of the settings. The problem with this solution is that once the value is read, it’s cached and never re-read. Which is to say, the service will only ever get called once. If the configuration value changes in whatever data store the service is wrapping, you’ll never get it in your app. Also, if you wanted strong typing, you’d have to implement a custom configuration section that handles strong typing and that’s what your provider would return from the Decrypt method. (Like I said, a simple AppSettingsSection keeps it simple.)

A solution that’s chattier but overcomes this caching issue is to implement a special ConfigurationSection. In that section, you can simply have a method that wraps the service call.

Your configuration file might look like this:

<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="mySection" type="Framework.ServiceConfigurationSection, Framework"/>
  </configSections>
  <mySection endpointName="WSHttpBinding_IConfigurationService"/>
</configuration>

It’s a little shorter, but you can still see there’s a service endpoint name in there that’d correspond to the configuration service you’ll be calling. You can also see that we’re using a custom configuration section rather than one of the standard out-of-the-box ones.

The ConfigurationSection implementation might look like this:

using System;
using System.Configuration;
using System.ServiceModel;

namespace Framework
{
  public class ServiceConfigurationSection : ConfigurationSection
  {
    [ConfigurationProperty("endpointName", IsRequired = true)]
    public string ServiceEndpointName
    {
      get
      {
        return (string)this["endpointName"];
      }
      set
      {
        this["endpointName"] = value;
      }
    }

    public string GetValue(string key)
    {
      ChannelFactory<IConfigurationService> factory =
        new ChannelFactory<IConfigurationService>(this.ServiceEndpointName);
      IConfigurationService service = factory.CreateChannel();
      return service.GetValue(key);
    }
  }
}

Again, there’s a lot I’m not doing in there to keep it simple, but, again, you see the idea - the GetValue method on the section wraps the service call. Consuming this looks very similar to the original example:

ServiceConfigurationSection config = (ServiceConfigurationSection)WebConfigurationManager.GetSection("mySection");
this.SomeObject.Value = config.GetValue("key");

This version retrieves the value every time you ask for it, which gets you around the caching issue. That said, the developer using this mechanism should probably be made aware of what’s going on so he or she doesn’t wonder why performance has gone down the tubes on that page that uses 150 bajillion configuration values.