Typemock Isolator Open Source Licenses

Just got word from the folks over at Typemock - if you have an open source project and you want to use Typemock Isolator, they're going to be coming out with a new (free) license type that allows your open source project to use it. Here's the new licensing structure I've seen:

  • Commercial - $449 (same as today)
  • Personal - $200 (will include one year maintenance)
  • Open Source Project - Free
  • 21-Day Trial - Free

And, of course, discounts for upgrades, etc., on the paid licenses.

This is huge. I've been wanting to add tests to CR_Documentor, but it's almost impossible to do that because of the tight coupling DXCore plugins have with the DXCore engine. For example, I'd love to be able to create a fake language element and unit test the syntax generator... but I don't want to have to write wrapper interfaces and services for everything in DXCore that I interact with. Now I can!

Big side benefit - the folks who are unfamiliar with Isolator can see how open source projects use it and see the benefits. Sweet!

CR_Documentor 2.1.0.0 Released: Fixed the JavaScript Security Warning

I just posted the new version of CR_Documentor, version 2.1.0.0, over at Google Code. This new one hosts a tiny internal web server (instead of manually poking things into the IE DOM) so as long as you can get to localhost, you should be able to see the preview without that nasty warning. I also fixed the focus issue so it shouldn't steal focus when the preview refreshes.

If you upgraded before and are ready for a fix, go get it!

Birthday Weekends - Plural!

Since my birthday falls in the middle of the week this year, we're sort of splitting up the festivities across weekends - some this past weekend, some this weekend.

Friday night I started out by playing some GRAW 2 co-op with my dad and uncle. We normally spend a lot of time struggling through just one of the missions (none of us are super-good and some of the missions really need four or five people), but this time we beat two in one night. My uncle came out with the medal of honor on this one, finishing out the mission after my dad and I had both gotten killed.

Saturday morning I went to the DMV and got my license renewed and actually got out far sooner than I thought I would. In the afternoon we saw The Dark Knight, and it was awesome. Heath Ledger was amazing as the insane Joker and really made him a believeable bad guy, not the cartoonish villain you might envision with the Joker. I hope they make more Batman in this style, and maybe adopt it for future super hero movies. Comic movies don't have to be all cartoonish.

Sunday we went to the driving range with our friends K and Angela to have lunch and hit a bucket of balls. It was a beautiful day out and we had a great time. I'd never hit a golf ball before in my life, so this was a fun intro, even though I didn't do too well. Most of my shots went about 40 or 50 yards, though I had a few that went... a bit shorter than that... and some that darn close to injured people. My furthest went about 140 yards. K put all of us to shame going way past everything we did.

K said we might be sore today, but I'm not doing too bad. My back is a little tight and the inside of my right arm is kind of sore (so I can't really grip things or pick up heavy stuff on the right), but other than that, I'm doing well. I think Jenn is mostly feeling it in the back. Regardless, it was a heck of a fun time and we'll definitely be trying that again.

We stopped by on the way home at Baskin-Robbins, had some ice cream, and finished off the day with a barbecue at our place. Someone was outside cooking something delicious smelling and we couldn't resist - we had to cook our own.

This coming weekend I think we're going to hit the Washington County Fair so we can see the Pirate's Parrot Show and maybe have a funnel cake. Since it's free admission, we may even go Friday night and Saturday. It's a lot of fun and only a few minutes away from home.

Tag Soup

Jeff Atwood posts about the exact thing I thought when I saw the MVC tidal wave coming to overtake web forms. It feels like I'm back in the 90's, doing old-school ASP, because of the tag soup.

Don't get me wrong - I'm all about separation of concerns and such, but every time I look at something like MVC, I see all roads leading to web forms. Maybe different web forms, but web forms nonetheless.

  • Too much tag soup? Package stuff up in helper methods.
  • Oh, wait, the helper methods that generate control structures aren't really flexible enough to allow overridden behaviors or wire things up (like validation). Let's make them instance methods on objects.
  • Hmmm, there's sort of an object lifetime to manage here, and wouldn't it be nice if the packaged widget could be a little smarter about handling view data? Like dynamically populating itself based on data and letting me know if the user changed stuff, because writing that every time is such a pain.
  • Hang on, that's web server controls.

Some folks argue they want that "tighter control over the HTML" that the tag soup provides. I, personally, am much less interested in hacking HTML. Let the framework do it for me. I'm more concerned with the business logic anyway.

I've done my share of classic ASP style development in lots of different server side languages, and it always ends up that to get rid of the tag soup, you head towards web forms.

Closed Generic Types Have Their Own Statics

You really have to be careful when you use generic types. Say you have a generic type Foo<T> like this:

public class Foo<T>
{
  public static string StaticValue = "Unset.";
}

Fine, right? Well, what happens if you do this?

Console.WriteLine("Foo<string>: {0}", Foo<string>.StaticValue);
Console.WriteLine("Foo<int>: {0}", Foo<int>.StaticValue);
Foo<string>.StaticValue = "String value.";
Foo<int>.StaticValue = "Integer value.";
Console.WriteLine("Foo<string>: {0}", Foo<string>.StaticValue);
Console.WriteLine("Foo<int>: {0}", Foo<int>.StaticValue);

I bet you can guess what the output is.

Foo<string>: Unset.
Foo<int>: Unset.
Foo<string>: String value.
Foo<int>: Integer value.

That's right - each closed generic type (a generic that has a type parameter provided) has its own set of static values.

Think about how that can bite you - if you have multiple parameters on your generic type, like MyType<T, U, V>, and you have three different types that are used in each of T, U, and V, you end up with 27 sets of static values (it's combinatoric). Possibly not what you're thinking at the time you write the code.

I really can't find any documentation on this. There's a nice CodeProject article about it that shows why this can really work against you if you're trying to make a strongly-typed generic singleton factory, but beyond that, MSDN really only yields up an FxCop rule that's fairly unrelated.

Be careful with your generics and static values!

Simplest Embedded Web Server Ever with HttpListener

While working on solving a CR_Documentor known issue, I realized I needed to have some sort of embedded web server running so I could serve up dynamically generated content. I didn't need a full ASP.NET stack, just something I could pipe a string to and have it serve that up so a hosted IE control would be getting content from a "live server" rather than from a file on disk or from in-memory DOM manipulation... because both of those latter methods cause security warnings to pop up.

I looked at creating a dependency on the ASP.NET development server, WebDev.WebServer.exe, or the assembly that contains the guts of that, WebDev.WebHost.dll, but both of those only get installed in certain configurations of Visual Studio (I think it's when you install the Visual Web Developer portion) and I couldn't really assume everyone had that. Paulo Morgado then pointed me to HttpListener, and let me tell you, that's a pretty sweet solution.

Here's a very simple web server implementation that uses HttpListener. You provide it a content string (the "Content" property) and that's what the response content is. It doesn't read files from the filesystem, it doesn't do auth, it doesn't do ASP.NET... it's just the simplest of simple servers, which is exactly what I need for CR_Documentor.

using System;
using System.Diagnostics;
using System.Net;
using System.Text;
using System.Threading;

namespace HttpListenerExample
{
  public class WebServer : IDisposable
  {
    private const string Prefix = "http://*:11235/";
    private bool _disposed = false;
    private HttpListener _listener;
    private IAsyncResult _cycleResult = null;

    public string Content { get; set; }

    public bool AcceptingRequests { get; private set; }

    public WebServer()
    {
      if (!HttpListener.IsSupported)
      {
        throw new NotSupportedException("Your platform does not support HttpListener.");
      }
      this.Content = "Content has not yet been set.";
      this._listener = new HttpListener();
      this._listener.Prefixes.Add(Prefix);
      this.AcceptingRequests = false;
    }

    public void Start()
    {
      if (this.AcceptingRequests)
      {
        return;
      }
      this._listener.Start();
      ThreadStart cycle = new ThreadStart(this.AsyncListenThreadStart);
      this._cycleResult = cycle.BeginInvoke(null, null);
      this.AcceptingRequests = true;
      Debug.WriteLine("Listener now accepting requests.");
    }

    public void Stop()
    {
      if (!this.AcceptingRequests)
      {
        return;
      }
      this.AcceptingRequests = false;
      this._listener.Stop();
      Debug.WriteLine("Listener no longer accepting requests.");
    }

    private void AsyncListenThreadStart()
    {
      while (this.AcceptingRequests)
      {
        try
        {
          HttpListenerContext context = this._listener.GetContext();
          HttpListenerRequest request = context.Request;
          HttpListenerResponse response = context.Response;
          Debug.WriteLine(String.Format("[{0}] Received request.", DateTime.Now.Ticks));
          string responseContent = String.Format("<html><head><title>Listener: {0}</title></head><body><p>{1}</p></body></html>", DateTime.Now.Ticks, this.Content);
          byte[] buffer = Encoding.UTF8.GetBytes(responseContent);
          response.ContentLength64 = buffer.Length;
          response.OutputStream.Write(buffer, 0, buffer.Length);
          response.OutputStream.Close();
          Debug.WriteLine(String.Format("[{0}] Sent response.", DateTime.Now.Ticks));
        }
        catch (HttpListenerException err)
        {
          Debug.WriteLine(String.Format("ERROR: {0}", err.Message));
          break;
        }
      }
    }

    public void Dispose()
    {
      this.Dispose(true);
      GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
      if (this._disposed)
      {
        return;
      }
      if (disposing)
      {
        Debug.WriteLine("Disposing of listener managed resources.");
        this.Stop();
        this._listener = null;
      }
      this._disposed = true;
    }

    ~WebServer()
    {
      this.Dispose(false);
    }
  }
}

With this simple wrapper, you can new-up a web server instance, start it listening for requests, set the Content property with the content you want, and hit http://localhost:11235/ to get the content in your browser. Dispose the instance and you're done. Here's what it looks like in a simple console program host:

using System;

namespace HttpListenerExample
{
  class Program
  {
    static void Main(string[] args)
    {
      using (WebServer listener = new WebServer())
      {
        listener.Start();
        Console.WriteLine("Listener accepting requests: {0}", listener.AcceptingRequests);
        Console.WriteLine("Setting content.");
        listener.Content = "Content set by console app.";
        Console.WriteLine("Press any key to exit.");
        Console.ReadLine();
      }
      Console.ReadLine();
    }
  }
}

I'm going to be using this approach in CR_Documentor to serve up the content preview and maybe augment it a bit later so I can also serve images from embedded resources and such, making the preview that much richer and more accurate.

CR_Documentor Known Issue: JavaScript Security Warning

There's a known issue with the latest CR_Documentor - sometimes, on an unpredictable basis, it'll start issuing that "active content" JavaScript security warning. It does that because we're updating the document by poking data into the DOM directly. Usually setting your IE security settings to "allow active content to run in files on My Computer" fixes it, but not always.

Unfortunately, it's not really something I can replicate easily, but I know the fix is to, well, stop doing that dynamic poking thing and just serve it up like a regular web server. I have a couple of options:

  1. Create a custom in-proc web server from scratch. I'd have the most control over it and the least dependencies, but it's the most amount of work, too.
  2. Add a dependency to the ASP.NET development server and use that. Basically, just fire up the ASP.NET development server and serve from a temporary filesystem location.

Is it safe to assume most folks have the ASP.NET development server installed with Visual Studio? I could detect if it was installed and issue an error when the user displays the window to tell them they need to have it installed. I'm thinking writing web servers, however tiny, is not my "core competency" so I'd rather use something off the shelf than try to roll everything myself.

UPDATE: Turns out rolling your own is easy with HttpListener. I'm going to try that first.

UPDATE 2: This is currently being worked on and should be fixed in the next version. You can follow the issue progress on the CR_Documentor site.

UPDATE 3: It's fixed! Go get it!

Laser Hair Removal: Treatment 12

Saturday was my 12th treatment on my face, and the last in my second set of six (they sell treatments in blocks of six).

A lot has changed since the first treatment, so since I re-upped for a third set of six, I thought it would be time for a retrospective.

  • It still hurts, but it's nothing like the first time I went. I get MeDioStar on my entire face now, and it's not nearly as bad because the hair is so much thinner. Reading back on that first entry, I totally remember how much apprehension I felt before going back for the second treatment. I don't feel that anymore. (There really is no way you can prepare someone for it, so I think a lot of my reaction was that my pain-related expectations were vastly different than reality. Whattaya gonna do?)
  • I still really like all of the people at the clinic. Everyone from the folks at the front desk to the technicians and the sales people are super nice. They all remember my name, they all make me feel totally welcome, and they're super easy to get along with. I'm glad I chose them.
  • I thought I'd be a closer to done than I am, but then, I was supposed to have done 12 MeDioStar treatments by now and I haven't. I spent a lot of time doing just Dermo Flash to thin things out. It was the right thing to do, but it's taking a while.
  • I really like the results so far. My hair grows differently on my face - I pretty much have to shave against the grain to get a good shave - but I've also not destroyed any sheets, pillowcases, or shirts for quite some time.
  • The spots that are being stubborn are my chin, upper lip, a spot on my right cheek, and a spot on my neck. The rest has done really well. Even the stubborn spots are starting to give way, it's just taking a while.

So I did my thing, got my second set of six, and I'm crusin' along. I should probably take some before and after pix in a couple of weeks to see how well this next set of treatments goes.

CR_Documentor 2.0.0.0 Released: Now With Sandcastle Preview and Open Source Goodness

I know it's bad news to release things on Friday right before the day is out, but I can't hold it in any longer:

I am pleased to announce that after a far-too-long silence, CR_Documentor 2.0.0.0 has been released and is now available for download.

Three major things to report in this release:

  1. All reported bugs have been fixed. If you mailed me or left a comment about a bug, it should be resolved in this release. While there are some known issues, things should render right and it should behave itself reasonably.
  2. Sandcastle "Prototype" preview style is available. You can choose between the classic NDoc preview style or the new Sandcastle "Prototype" style.
  3. The plugin is now open source. I've created a new home for the plugin on Google Code and have released it under the Apache 2.0 license. I'd love to get some help and contributions on it, but even if you're just curious about how it works under the hood, feel free to grab the code.

All the info - FAQ, known issues, etc. - is all on the new CR_Documentor site at Google Code, as is the download. Head on over and check it out!

CR_JoinLines and CR_SortLines Join DXCore Community Plugins

My CR_JoinLines and CR_SortLines plugins for DXCore have been joined up with the DXCore Community Plugins project headed by Rory Becker. Complete source, installation/usage info, etc., has all been put up over there and any further dev on them will be done there.

Hopefully this more public release area will be helpful to folks who not only want to find and use the plugins, but also who want to learn how to write plugins.