# Friday, June 12, 2009

Never heard of ack? Well, by ack’s admission, it is “better than grep.” That’s up to you to decide, but it does make searching code easier than grep.

As a means of illustration, here is a grep example of a recursive search for StringBuilder across multiple C# files that I used back in my post on “finding stuff quickly.”

The output is pretty nice, but the addition of the find command to limit the searching to only C# files isn’t the easiest to type quickly.

ack makes this a little… well, a lot easier.

image

Nice! Even EASIER to read than the grep matching. And it is easier to type.

Well, of course, I had to add this functionality to Find-String. (Guess what, it runs faster than grep and ack both! At least on Windows…)

image

Now, this makes… the third post I’ve had on a Find-String PowerShell script I think. At some point, you’re going to get tired of this if you haven’t already.

“Is this guy seriously going to post every time he changes the way Find-String works?”

No, no, I guess I shouldn’t.

But for my own benefit, I do want this in source control. And I’d like to make it easier to use and find this. I’ve been using a local SVN repository for my changes to my scripts, but they included all of my scripts. Well, I moved just the Find-String source over to GitHub yesterday. I even started from the initial version of Find-String and committed my change history over from SVN :-)

image

For up to date versions of Find-String, they’ll be out there. The URL is http://github.com/drmohundro/Find-String/tree/master. If you don’t want to install git to check the source out, there is a big download button on the project page. It will package up the current version of Find-String for you which you can then download and use to your heart’s content.

If you improve upon the script, send me pull requests or a patch and I’d be happy to make it better.

 

Warning, upcoming tangent regarding GitHub adding PowerShell syntax support…

My other hope with posting this is that maybe GitHub will add the PowerShell syntax support to GitHub. If you view the source for Find-String on the GitHub website, you won’t see any syntax highlighting.

image

But… they have syntax highlighting for lots of other file types, as is evidenced by the gists I’ve already shared.

image

I already asked for this on the GitHub support site, but it was inexplicably closed with “no more actions from GitHub… are required” and that it is apparently “resolved.” Maybe I shouldn’t worry and the feature just hasn’t gone live yet. In which case, I’m just blabbing on and on for no reason and creating a long tangent to the rest of my post. If not, well, maybe they’ll add support if I complain some more!

posted on Friday, June 12, 2009 7:58:18 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Monday, February 23, 2009

WiX Setup

I’ve been doing some work with MSIs lately, specifically using the WiX toolkit, so I thought I’d share a short primer on using WiX to build your own MSIs, and also to share some links and some tricks to avoid some pitfalls that I ran into.

First off, WiX stands for Windows Installer XML and, from what I understand, is the first Microsoft-supported open source project. Not only that, but it is the way that Microsoft builds their MSIs, too, so it is pretty significant.

To get started, I wouldn’t even bother with the release version of 2.0. The real fun is in version 3.0, which, even though it is in beta, is plenty stable (IMHO) and supports Visual Studio with a project template and intellisense support via schema files. It also makes the building step a lot easier.

image

My First WiX Project

Once you start your project, you’re presented with a WXS file pre-filled with a few initial options that looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Product Id="de9157d6-2fbf-4c16-9d28-77f790788b28" Name="WixProject1" Language="1033" Version="1.0.0.0" Manufacturer="WixProject1" UpgradeCode="f5614cd8-aa70-4bc4-948b-208b34e16a6d">
        <Package InstallerVersion="200" Compressed="yes" />

        <Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />

        <Directory Id="TARGETDIR" Name="SourceDir">
            <Directory Id="ProgramFilesFolder">
                <Directory Id="INSTALLLOCATION" Name="WixProject1">
                    <!-- TODO: Remove the comments around this Component element and the ComponentRef below in order to add resources to this installer. -->
                    <!-- <Component Id="ProductComponent" Guid="95758d74-281c-4eee-84ce-4fda6ad60557"> -->
                        <!-- TODO: Insert files, registry keys, and other resources here. -->
                    <!-- </Component> -->
                </Directory>
            </Directory>
        </Directory>

        <Feature Id="ProductFeature" Title="WixProject1" Level="1">
            <!-- TODO: Remove the comments around this ComponentRef element and the Component above in order to add resources to this installer. -->
            <!-- <ComponentRef Id="ProductComponent" /> -->
        </Feature>
    </Product>
</Wix>

It has most of the things that you’ll be interested in.

The Product element is likely the most important element as it defines the application that your MSI will install. You’ll notice that WiX is built around a lot of Guids. MSIs, or Windows Installer actually, is built around tables. Using the orca tool that ships with the Windows SDK, you can actually see these tables for any MSI. (FYI, you’ll find your Product Id Guid if you look under \\HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ after installation.)

image

You Can Refactor WiX, Too

Before going further with your WiX file, I would strongly recommend refactoring some of the Guids and common strings out into variables like so:

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <?define ProductName = "WixProject1"?>
  <?define ProductCode = "de9157d6-2fbf-4c16-9d28-77f790788b28"?>
  <?define UpgradeCode = "f5614cd8-aa70-4bc4-948b-208b34e16a6d"?>
  <?define ProductVersion = "1.0.0.0"?>
  
  <Product Id="$(var.ProductCode)"
           Name="$(var.ProductName)"
           Language="1033"
           Version="$(var.ProductVersion)"
           Manufacturer="WixProject1"
           UpgradeCode="$(var.UpgradeCode)">

Doing this can help you greatly later when you’re trying to figure out which Guid goes where or what the Guid is actually for. The rest of the process of building your WiX file involves mapping out your dependencies. The project template by default already creates Directory elements pointing to the ProgramFilesFolder constant (see http://msdn.microsoft.com/en-us/library/aa370905(VS.85).aspx#system_folder_properties for the other system folder constants). The Component tag resolves to what I think of as a separate installable component. Components go together to form a Feature (think Complete versus Custom installs) so you’ll refer to your Component (by Id) in the Feature element using a ComponentRef element. The template has this commented out, but it shows how this would work. I’ll defer to the WiX Tutorial for specific examples here.

To build your MSI, you just have to do a Visual Studio build because you followed my instructions and installed beta 3.0, which comes with Visual Studio integration! Behind the scenes, though, all the build does is call out to candle.exe passing in your WXS file which results in a wixobj file. Then it calls out to light.exe passing in the wixobj file which results in an MSI. (WiX is pronounced like “wicks” – that should help you get the candle and light jokes… WiX also includes tools like dark, torch, votive, smoke, melt… :-))

Upgrading!

Up to this point, I didn’t really run into any problems with building my MSI. The online resources were fairly good at getting me started. What I wanted was for my MSI to be able to remove existing versions of my software before installing its version. MSIs support three types of upgrades: small update, minor upgrade, and major upgrades. I’d recommend skipping directly to major upgrade. From what I’ve seen so far, the other two options require additional command line arguments to msiexec to actually perform the removal of a prior install of your product.

To get a major upgrade to work, the most important thing you’ll need is your UpgradeCode. This is an attribute off of your Product element tag. Always store that off, regardless of whether or not you plan on allowing upgrades. As soon as you decide you don’t need to upgrade, you’ll want to upgrade. If you don’t have an UpgradeCode, you can’t upgrade.

You’ll use your UpgradeCode in an Upgrade tag like so:

<Upgrade Id='$(var.UpgradeCode)'>
  <UpgradeVersion Minimum='$(var.ProductVersion)'
                  IncludeMinimum='no'
                  OnlyDetect='yes'
                  Property='NEWPRODUCTFOUND' />
  <UpgradeVersion Minimum='$(var.RTMProductVersion)'
                  IncludeMinimum='yes'
                  Maximum='$(var.ProductVersion)'
                  IncludeMaximum='no'
                  Property='UPGRADEFOUND' />
</Upgrade>

Notice how I’m using my predefined variables. Makes it easier, eh? I’ve also added an additional variable defined as RTMProductVersion. This is the version of my installed application that I am upgrading from. UpgradeVersion tags work like ranges. So, for the UPGRADEFOUND to match, the installed application has to match inclusive RTMProductVersion (inclusive because of IncludeMinimum=’yes’) up to exclusive ProductVersion, which is the new version we’re about to install.

Now, changing the version isn’t enough for a major upgrade to work. You also need to change your ProductCode. This is what I continued to miss and why I was getting so frustrated with WiX. Now that I know what it should do (and what to search for), I’m finding plenty of WiX articles on how to do major upgrades! The reasoning for this is because major upgrades only work between two completely different products (think of Visual Studio 2005 and Visual Studio 2008 as having two different ProductCodes). These two products can run side-by-side, hence the different Guids for their product code. These applications allow side-by-side execution so they’re not specifying the removal of the old software, but they certainly could. MSDN has a good article on everything that you’ll need to check before getting an MSI ready for a major upgrade.

Once you have a new version and a new product code, you’ll need to actually tell the MSI to remove the existing version. To do this, you’ll add a RemoveExistingProducts element to an InstallExecuteSequence. Like this:

<InstallExecuteSequence>
  <Custom Action='PreventDowngrading'
          After='FindRelatedProducts'>NEWPRODUCTFOUND</Custom>
  <RemoveExistingProducts After='InstallFinalize' />
</InstallExecuteSequence>

<InstallUISequence>
  <Custom Action='PreventDowngrading'
          After='FindRelatedProducts'>NEWPRODUCTFOUND</Custom>
</InstallUISequence>

<CustomAction Id='PreventDowngrading'
              Error='Newer version already installed' />

In my example, I’ve told RemoveExistingProducts to run after the ‘InstallFinalize’ action, but this is customizable and can have an impact on the efficiency of your installer.

Once I set my WiX project up like this, it worked like a charm.

There are two resources that are essential for getting up to speed with WiX that I’d like to share. One is the WiX Tutorial. I’m probably using about a 10th of the content posted there. Second is Alex Shevchuk’s “From MSI to WiX” articles, particularly his post on major upgrades, which was invaluable to me.

posted on Monday, February 23, 2009 1:38:15 PM (Central Standard Time, UTC-06:00)  #    Comments [1]
# Wednesday, November 19, 2008

I’ve been doing some WPF work lately. WPF is ridiculously powerful and provides a lot more than WinForms. On the other hand – wow, the learning curve is quite steep. I think I’m improving, though.

So, the scenario. I wanted to be able to let a user click on an item in a ListBox and drag across, selecting multiple items in the process. Basically, I want to emulate the behavior that the Outlook calendar provides.

I ended up coding up the following XAML to get the behavior:

<ListBox
  x:Name="myListBox"
  SelectionMode="Multiple"
  ItemsSource="{Binding Path=SomeIEnumerableOnMyDataContext}"
  >
  <ListBox.Resources>
    <Style
      TargetType="{x:Type ListBoxItem}"
      >
      <EventSetter
        Event="PreviewMouseLeftButtonDown"
        Handler="ListBoxItem_PreviewMouseLeftButtonDown" />
      <EventSetter
        Event="PreviewMouseUp"
        Handler="ListBoxItem_PreviewMouseUp" />
      <EventSetter
        Event="PreviewMouseMove"
        Handler="ListBoxItem_PreviewMouseMove" />
      <EventSetter
        Event="PreviewMouseRightButtonDown"
        Handler="ListBoxItem_PreviewMouseRightButtonDown" /> 
    </Style>
</ListBox>

The problem with this code is that Blend (currently v2 SP1) doesn’t like EventSetters.

image

I wanted to keep the events hooked up so that, while testing, I could keep the behavior but, at the same time, I want to be able to at least try to design in blend. So I took to implementing the above XAML in code.

Sacha Barber has a good article on converting from XAML to code and back that helped a lot but it didn’t get me quite there.

Here is how to programmatically create one of the EventSetters in code:

var style = new Style(typeof (ListBoxItem)); 
 
style.Setters.Add(
    new EventSetter(PreviewMouseLeftButtonDownEvent,
                    new MouseButtonEventHandler(OnPreviewMouseLeftButtonDown)));

It’s pretty straightforward, but actually hooking this style into my ListBox was what got me confused next.

Setting the ListBox’s style to my style instance didn’t work and then I got stuck on how to plug my style into the ListBox’s ResourceDictionary (via the Resources property). The XAML doesn’t specify a Key anywhere, but the Resources’s Add method requires a key. I tried creating my own key and also specifying a null key, but I still didn’t get the behavior I wanted.

StackOverflow’s goal of being the place for one-off questions like this is starting to work because I stumbled across my answer via Google. I didn’t realize that, in the above XAML, when the Style specifies its TargetType, the type is implicitly the Key in the ResourceDictionary.

So the solution is this:

Resources.Add(typeof (ListBoxItem), style);

Easy enough.

posted on Wednesday, November 19, 2008 12:01:01 PM (Central Standard Time, UTC-06:00)  #    Comments [2]
# Tuesday, July 15, 2008

Brian Sullivan tagged me with the latest ongoing meme. I’m really sort of excited because I’ve missed out on all the other memes going around. Jeff Atwood probably wouldn’t even consider me a real geek because of that. (I haven’t updated a Wikipedia page either! Gasp!)

How old were you when you started programming?

I didn’t write my first “Hello World” until I was 18 in COMP 170. I created my first personal website when I was 15 I think, but my primary tools were Netscape Composer and Paint Shop Pro. :-) I think I had figured out by that point some very basic Javascript, but I really had no idea what I was doing.

How did you get started in programming?

I remember when my dad got a new PC with Windows 3.1 on it. Prior to that, I knew how to ‘cd’ between directories and how to run ‘dir’. All of these commands were, of course, to get to the directory where my games were installed. :-) I never really stayed in Windows at the time, because all the games were still DOS-based. I didn’t really have much to do with Windows (except for the Hot Dog theme), until Windows 95 came out. That’s when I started becoming more of a computer enthusiast. I remember troubleshooting Dial Up Networking so that our 14.4 modem would connect up. I also remember buying my first piece of hardware, the 3dfx Voodoo card.

As I mentioned, I started doing some basic web pages when I was in high school. This was the time of animated GIFs and tiled backgrounds, if you’re interested. This was also back when 56K modems first came out and there wasn’t yet a clear standard on how 56K modems would talk (you could either go with US Robotics or the cheap brands) and I worked as tech support at a local ISP. It wasn’t hard to do tech support because I had been troubleshooting my own Dial Up Networking problems for a few years already.

Coming from a tech support role, I didn’t really have any programming knowledge. I knew how to build a computer and I even knew about msconfig, but programming??? Nah… not really. Just WYSIWYG HTML.

When I graduated high school, I either wanted to be a musician or work with computers. Seeing as how I didn’t really want to teach high school band, I decided to go to school to learn about computers. I didn’t really know what Computer Science meant, but hey, my grades were pretty good so why not? So, I chose a major of Computer Science and the rest is history.

What was your first language?

Unlike the rest of the programming populace, my first language was actually not BASIC, but C++. I didn’t actually write a line of BASIC until my junior year of college! I would say that I currently prefer C# over VB.NET, but it has more to do with terseness than it does with braces. For the same reason, I’m a fan of Ruby as well.

What was the first real program that you wrote?

Are you saying Hello World doesn’t count? C’mon!

I’m going to define “real program” in this case as something that I could show my parents. I couldn’t show them “Hello World” or a command line application to create a binary search tree because they couldn’t relate to it. However, I could show them a GUI maze application that I wrote in Java. It had four players (one of which could be human controllable) and then each player raced to get to the exit. I also wrote a Solitaire program in C++, a networking Tic Tac Toe game in C++, and a Paint program in C++ (using the Windows API).

My first team application, like Brian’s, was created in the capstone course at Harding. We wrote a version of Othello that had to be networked with an AI. I wrote the networking code in C#. It even had threading code, which of course was written completely wrong. I’m still not entirely convinced that I can write threading code correctly today. :-)

What languages have you used since you started programming?

In college, I primarily used C++ and C#, but I also had some exposure to some Assembler, Java, VB.NET, Perl, and even LISP! My work experience includes a (thankfully short) period of COBOL and JCL on an IBM mainframe, but primarily has been in VBScript (both classic ASP as well as scripts), Javascript, PowerShell, C++, C#, and VB.NET.

In my personal projects, I’ve used C#, VB.NET, JavaScript, PowerShell, PHP, Python, and Ruby. I’m sure I’ve missed something in there.

What was your first professional programming gig?

I got hired out of college to work at Data-Tronics, Corp. where I still am to this day. My role has changed significantly now, where I’m trying hard to push out 40 years of IT practices with more modern methodologies (down Waterfall, down!) and technologies (down Mainframe, down!).

If you knew what you know now, would you have started programming?

You bet. I’m a geek to the core.

If there was one thing you learned along the way that you would tell new developers, what would it be?

I’d have to agree completely with Brian – get involved in the community. Do not let programming become just the job you perform. Like JP, get passionate about developing. If you don’t enjoy what you do, there isn’t any point in doing it. Start reading blogs and going to user groups. You’ll be overwhelmed at how much you didn’t know, but remember that no one else knows it all either. We’re all learning together.

What's the most fun you've ever had... programming?

I can’t think of any one specific instance, but I think one of the best feelings is, after having spent literally hours trying to debug some problem and then giving up and going home, waking up the next day and having the light bulb come on with the solution to this problem. I love solving problems with software.

Tag, you’re it!

Colin Neller, come on down!
Randy Walker, you too!

I’ve got other tags if anyone else is interested. I might even give some out!

posted on Tuesday, July 15, 2008 12:36:10 PM (Central Daylight Time, UTC-05:00)  #    Comments [3]
# Thursday, July 10, 2008

I was going through some code today and stumbled across the following:

Mmmmm... that was a good exception

Hilarious.

posted on Thursday, July 10, 2008 10:09:37 AM (Central Daylight Time, UTC-05:00)  #    Comments [6]
# Thursday, April 24, 2008

(Warning - this post is both a rant against the Mutex as well as a guide for its usage. Also, don't blindly copy code, only the bottom code snippet works. :-) )

I'm a big fan of an API that is so easy to use that I don't have to look at the documentation.

I had to look up the documentation for System.Threading.Mutex... multiple times.

Taking a look at Mutex, I see that it implements IDisposable. Great, that means I can wrap it in a using block.

My first try:

bool createdNew;
using (Mutex mtx = new Mutex(false, "MyAwesomeMutex", out createdNew))
{
    MessageBox.Show("Press OK to release the mutex.");
}

Looks good, right? Nope, that is a big negative. Nowhere does this actually acquire the mutex. When you run this application twice, they both show the message box just fine. Maybe I should actually check the createdNew value?

Let's change the code to look like this:

bool createdNew;
using (Mutex mtx = new Mutex(false, "MyAwesomeMutex", out createdNew))
{
    if (!createdNew)
        mtx.WaitOne();
    MessageBox.Show("Press OK to release the mutex.");
}

However, that didn't work, either. It turns out that the createdNew parameter just tells you if you're the one who created the mutex, not if you currently own the mutex. That is what the purpose for the WaitOne method is for. Of course, the documentation just says that it "blocks the current thread until the current WaitHandle receives a signal." Okay. Well, I'm glad that I now know that it also waits for my thread to acquire a lock on the mutex. (note, if you pass in 'true' as the first parameter, you'll request to be the owner, but you'll only be the owner if the createdNew out parameter comes back with true)

Third try. Third time's the charm, right?

bool createdNew;
using (Mutex mtx = new Mutex(false, "MyAwesomeMutex", out createdNew))
{
    mtx.WaitOne();
    MessageBox.Show("Press OK to release the mutex.");
}

Great, now when I run my app twice, the second one is blocking on the WaitOne call. Cool. You can even tell in the below screenshot, because the button's paint event is blocked and is whiting out (like Solitaire does when you win!).

image

Let's click okay and see if the second form gets the mutex, thus displaying the message. That's weird - the form still isn't responding. Let's close the first form.

image

Ouch! That was unexpected. What? Abandoned mutex? This sounds like I never even released the mutex. Hmmm... ReleaseMutex? Shouldn't that be called from the Dispose (end of the Using block)? Might as well try it.

bool createdNew;
using (Mutex mtx = new Mutex(false, "MyAwesomeMutex", out createdNew))
{
    try
    {
        mtx.WaitOne();

        MessageBox.Show("Click OK to release the mutex.");
    }
    finally
    {
        mtx.ReleaseMutex();
    }
}

Finally! Now, it works like I'm wanting. I'm keeping the using block in place, because that disposes the WaitHandle that Mutex uses (Mutex in face inherits from WaitHandle).

Anyway, I'm hoping there is a reason for the API to be designed in this way, but man, it doesn't seem very intuitive to me.

While learning this, I unfortunately tried putting the Mutex in some of my code without trying it small scale first. After struggling for quite a while, I went to the small application and discovered everything that I've posted here. I hope this helps you with the Mutex when you have to deal with it.

posted on Thursday, April 24, 2008 3:48:19 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Tuesday, February 05, 2008

I've found myself wishing that I could pass in more than two arguments to Path.Combine. That is, something like this:

Path.Combine(rootPath, someCalculatedPath, someKnownFileName);

As it is, Path.Combine only accepts two arguments, so I end up with calls that look like this:

Path.Combine(Path.Combine(rootPath, comeCalculatedPath), someKnownFileName);

It seems like a hassle to me. Here is a simple wrapper function (with accompanying test) that will accomplish this:

public static class FileUtils
{
    public static string CombinePaths(params string[] paths)
    {
        if (paths.Length == 0) return string.Empty; 

        return Path.Combine(paths.First(), CombinePaths(paths.Skip(1).ToArray()));
    }
} 

[TestFixture]
public class FileUtilsTests
{
    [Test]
    public void Should_combine_paths_correctly()
    {
        string expected = @"c:\some\path\to\file.txt"; 

        Assert.AreEqual(expected, FileUtils.CombinePaths("c:\\some", "path\\to", "file.txt"));
    }
}
posted on Tuesday, February 05, 2008 7:29:02 AM (Central Standard Time, UTC-06:00)  #    Comments [2]
# Wednesday, January 30, 2008

In my post looking forward to 2008, I mentioned that I wanted to take more time this year to learn new technologies, particularly outside of the Microsoft communities. With all of the push in .NET towards dynamic languages right now, why not look to some of the dynamic languages that have been out there being used for years?

I know what you're thinking - looks like David here decided to learn Ruby. I mean, that's what everyone is using, right? Ruby and Ruby on Rails? Nahhh, I'm actually learning Python! Probably the key factor for me was the Python Challenge. I follow MoW's Powershell blog and he's started up a series on working through the Python Challenge using Powershell. I had heard about the challenge before, but hadn't really looked into it much, but this was enough to prompt me to get over there and try it out. (I am planning on still learning Ruby, though - I'll just go through the challenges with Ruby later)

I resisted the urge to try to find an IDE for Python and just code it up in a text editor. It has forced me to get more familiar with the syntax as a result. The Python site has a great tutorial for starters as well as some good documentation on the available modules. The hardest part for me is to not write the code like I write C# or VB. For one of the challenges, you have to take a given string, a given mapping, and then translate the string to get the instructions to move to the next challenge. I wrote a basic loop over the characters in the string, converted them to their ordinal values, performed the translation, and then converted them back to characters. It worked, but it wasn't the best way to do it in Python. Python provides this great function called string.maketrans. Also, the map function is amazing. It is sort of like the List<T>.ForEach method except that it reads a lot better (though lambda expressions in C# make it a little better). I'm starting to understand the power behind the whole map/reduce idea that Google is so big on. List comprehensions are really cool, too.

Anyway, so far, I'm to the 5th challenge (with some help from Google, the Python tutorials, and the challenge forums at times) and it is pretty cool. One of the most enlightening things about going through the challenge is that, as you complete one, you can go look at submitted solutions on the wiki. It is a great way to evaluate if you solved the challenge the "right" way or not. It is a great learning experience. One way I'm trying to apply this knowledge is that I'm running the challenges in both CPython (Python that runs on C, the standard I think) and IronPython.

Another thing I've done to try to see how other development communities work is that I've installed Ubuntu 8.04 (the alpha) on my laptop. I'm now dual booting Vista x64 and Ubuntu and it is pretty nice. I have two favorite things about Ubuntu so far - the ridiculous customization that you can do with it (compiz is amazing) and the package manager. Seriously, the fact that you don't have to pull up a browser to download apps and install them is a massive plus over Windows. In fact, you can just run a simple apt-get command if you want. Don't worry, though, I'm not planning on switching from Vista anytime, soon. Ubuntu is great and I'll be keeping it on the laptop, but I still like Vista, too. Right, right, blasphemy, I know. They're both great operating systems as far as I'm concerned. One takes an entire DVD and seems like a resource hog (not as bad anymore) and the other fits on a CD and requires editing conf files, downloading "restricted" drivers, and sitting at the command line to get video and wireless working :-) Seriously, neither are perfect. It has been nice seeing both sides of the fence, though.

posted on Wednesday, January 30, 2008 8:11:42 AM (Central Standard Time, UTC-06:00)  #    Comments [1]
# Thursday, December 06, 2007

In case you've been under a rock recently, Visual Studio 2008 was released recently which supports a lot of functional capabilities like lambda expressions. I've been playing around with the lambda syntax in both C# and VB.NET recently and the addition to the languages is great. I did run into one thing that is still frustrating me in VB.NET, though.

Check out the below C# snippet:

TryTimes(() =>
{
   Console.WriteLine("hi there.");
   throw new Exception("haha");
   Console.WriteLine("hi there after   .");
}, 5);

This is the prototype for the usage of a function that could try an operation a certain number of times and then fail if the operation didn't succeed after N number of tries. Obviously, the above code sample will fail every time, but the idea could work alright for file I/O if you're unsure if anyone else might have locks on the file.

The above is impossible to do in VB.NET, though, because VB.NET does not support multi-line lambda expressions. The C# supports them by wrapping the expressions in curly braces, essentially making the lambda expression a block. I wanted to emulate the same thing with VB.NET, but after some fruitless web searches, I came across this MSDN forum posting on VB.NET and lambdas which then pointed to Paul Vick's post on the VB 2008 features that are still in.

I've been wanting the equivalent of anonymous delegates in VB for a long time and I thought, with lambda expressions, I might finally get them. We are a lot closer, but they still don't provide quite the benefit that they could have had we gotten multi-line lambda support. I guess those annoying line continuation characters in VB mess this all up. I think if I could change anything about VB, it would be to make those optional.

On the positive side, though, the intellisense support for VB.NET has increased substantially. For that, I am thankful.

posted on Thursday, December 06, 2007 9:56:03 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Wednesday, November 14, 2007

I'm close to finishing up some work on one of my first true TDD projects and it has gone great for the most part. It did take a long time to get started though. The hardest part for me was fighting the urge to just open the designer and start dropping controls. Visual Studio really does guide developers towards a designer-centric approach which, after having done this for a few years, is very hard to resist. What I ended up doing was thinking about the problems that this application was going to solve and starting there. Make your tests define the problem area and move outward. The idea is that, if you can't write your tests that show what your code will do, are you even ready to write the code yet?

I was able to get my first few tests out quickly, but then I hit a block where I struggled with the structure I wanted to follow. This turned out to be good because, instead of coding something up that was substandard, I was able to fight through this struggle and come out with a better solution in the end. In doing this, I discovered a great benefit that TDD provides - you can continue coding even if you don't know all of the answers to all of the problems that your application will solve. For example, I'm still not sure what file format I'll be using in my application (or even if I'll use the file system). It really doesn't matter, though, because I was able to set up an interface and mock that dependency out in my tests and continue with the rest of my application. Had I started with the designer, I likely would have sat around until I had hashed out the file format requirements.

Once I got past my initial hang ups, I was able to fly through the rest of the code. What is even better is that I feel a huge amount of confidence in this code - code that still has no UI around it. I haven't felt this good about code quality in, well, ever.

If you're wanting to start with TDD, I'd like to recommend a few resources. First, read more code. If you aren't using it yet, go get TortoiseSVN and pull down some open source code. The Rhino.Commons repository is an excellent source of code (as well as great utilities). I can also recommend Jeremy Miller's StoryTeller code. I don't do anything with FIT tests, but the code is still a great example of WinForms code driven by tests.

Another great resource is screencasts. Watching someone write their tests first helps immensely. Evan Hoff has a great screencast on TDD. It also shows some of the power of ReSharper.

One final thought for this post is something that Bob Martin spoke about in this Channel 9 interview on programming discipline. Bob pointed out that few disciplines are as fragile as programming is. For example, if even one bit is off in your application, it has the potential to crash. One example of a profession that is also fragile is accounting. If one digit is off in the wrong spreadsheet, the CEO of a corporation can get thrown in jail. The way that the accounting profession has solved this is by entering their numbers twice - with credits and debits. If something gets entered wrong, it won't balance. When the sheets balance, there is confidence in the reported numbers. In the same way, TDD and unit tests provide the balance and confidence that applications are doing what they were intended to do.

Technorati tags: ,
posted on Wednesday, November 14, 2007 12:56:48 PM (Central Standard Time, UTC-06:00)  #    Comments [2]
# Wednesday, October 31, 2007

It is Halloween after all. It would be a great day to start learning Boo.

Sorry. I couldn't help myself.

posted on Wednesday, October 31, 2007 1:46:36 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Thursday, October 18, 2007

I was reading through my feeds this morning and came across this gem of a paragraph:

Manual testing is immoral. Not only is it high stress, tedious, and error prone; it’s just wrong to turn humans into machines. If you can write a script for a test procedure, then you can write a program to execute that procedure. That program will be cheaper, faster, and more accurate than a human, and will free the human to do what humans to best: create!

The paragraph is actually an aside to the rest of the post, too! Go read the entire TDD post in context at the ObjectMentor blogs.

posted on Thursday, October 18, 2007 8:15:18 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Friday, September 28, 2007

One of the banes of my existence (okay, not that bad but fun to say) is supporting Windows 2000 at work. Yes, there are still Win2K machines out there - not many, but enough to make a difference. One problem is that .NET 3.0/3.5 isn't supported on Win2K, so we're limited in what we can do, at least on the client-side. Another problem is just strange issues with the framework. 99% of the stuff we write works great, but there are a few things that don't.

Here is one that caused mass confusion recently.

Check out the code for this incredibly simple console application that I wrote:

Module Module1
 
    Sub Main()
 
        Console.WriteLine(">>Environment.CommandLine = {0}", Environment.CommandLine)
        Console.WriteLine(">>Environment.GetCommandLineArgs()(0) = {0}", Environment.GetCommandLineArgs()(0))
 
        Dim commandLineFileName As String = System.IO.Path.GetFileName(Environment.GetCommandLineArgs()(0))
        Console.WriteLine(">>commandLineFileName = {0}", commandLineFileName)
 
        Console.WriteLine(">>ProcessName = {0}", Process.GetCurrentProcess.ProcessName)
 
        Console.WriteLine("Press enter to continue....")
        Console.ReadLine()
 
    End Sub
 
End Module

What would you expect the output to be?

Here's what it does on Windows XP:

>>Environment.CommandLine = ConsoleApplication1.exe
>>Environment.GetCommandLineArgs()(0) = ConsoleApplication1.exe
>>commandLineFileName = ConsoleApplication1.exe
>>ProcessName = ConsoleApplication1
Press enter to continue.... 

On Windows 2000, it does the same thing. Super.

Let's change the name of the executable to ThisIsALongNameForAnExe.exe and run it again.

>>Environment.CommandLine = ThisIsALongNameForAnExe.exe
>>Environment.GetCommandLineArgs()(0) = ThisIsALongNameForAnExe.exe
>>commandLineFileName = ThisIsALongNameForAnExe.exe
>>ProcessName = ThisIsALongNameForAnExe
Press enter to continue.... 

Once again, Windows 2000 behaves the same way. Great.

Let's try one more thing. Let's change the name of the executable to This.Is.A.Long.Name.For.An.Exe.exe and run it one last time.

Windows XP looks like this:

>>Environment.CommandLine = This.Is.A.Long.Name.For.An.Exe.exe
>>Environment.GetCommandLineArgs()(0) = This.Is.A.Long.Name.For.An.Exe.exe
>>commandLineFileName = This.Is.A.Long.Name.For.An.Exe.exe
>>ProcessName = This.Is.A.Long.Name.For.An.Exe
Press enter to continue.... 

However, Windows 2000 looks like this:

>>Environment.CommandLine = This.Is.A.Long.Name.For.An.Exe.exe
>>Environment.GetCommandLineArgs()(0) = This.Is.A.Long.Name.For.An.Exe.exe
>>commandLineFileName = This.Is.A.Long.Name.For.An.Exe.exe
>>ProcessName = This.Is.A.Long
Press enter to continue.... 

Can you tell the difference? System.Diagnostics.Process.ProcessName is truncated when running on Win2K. The only thing I can tell is that the periods in the process name throw it off. Granted, hopefully you don't have anything secure relying on the name of your process (cough, rename, cough), but it still came across as very unexpected.

Note - the results can be different depending on how you actually execute the program. The command line and command line arguments are literally what was typed when the program is executed.

posted on Friday, September 28, 2007 2:21:13 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Wednesday, September 26, 2007

Yesterday, I had a somewhat strange experience. I was helping someone with a problem they were having and, almost as a side note, this individual thought he would share some code with me that he was particularly proud of. He even prefaced the story with the "not to brag or anything" phrase. He had written some custom code to help text boxes grow or shrink depending on how the user resized the window. If you know anything about WinForms, you'll know that some simple anchoring techniques and good use of the SplitContainer will solve this problem for you - please, please, please don't go writing custom mathematical equations when the framework can take care of it for you.

At the time, I was pretty annoyed with it, because this individual was bragging about something that I considered "the wrong way to do it." In retrospect, this probably was the wrong response. Why? Because he was proud of some of the code he had written. He actually cared about it enough to not just treat it as something to toss off on to someone else when he moved to the next project.

The projects that have turned out best that I've worked on the ones where I was really proud of the code. That doesn't mean I did it the right way. I'm thinking of one example where I wrote this crazy elaborate dynamic menu system in JavaScript. It even worked in both Firefox and Internet Explorer. It had a full blown object model and made use of closures and more - it was great. Here's a complete example of usage of the menu:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
   <head>
      <title>clsNavBar</title>
      <script language="JavaScript" src="clsMenu.js"></script>
      <link href="styles.css" rel="stylesheet" type="text/css">
   </head>
 
   <body>
      <script language="JavaScript">
        var nav = new clsMenu();
        nav.setContainer(document.body);
        nav.setXMLUrl("NavBar.xml");
        //nav.setHorizontal(false)
        nav.buildMenu();
      </script>
   </body>
</html>

It had one problem. Maintenance. Maintenance on the system will be nigh impossible for the next guy. From the very beginning, I should have used CSS for the entire menu structure. When and if someone ever decides to change the way the menus look, well... good luck. However, it was still a good experience. I learned more about the inner workings of JavaScript from working with that than I did from any blog post or book I've ever looked at. I would have never learned what exactly 'this' references in JavaScript without that example (see this post on JavaScript gotchas and refer to the section on 'this').

In all of this, I have learned to be very careful of the code I'm proud of. Inevitably, if you're growing as a developer by "sucking less every year," you're not going to be too proud of your code in a year or two anyway.

Do you have any code you're particularly proud of? If it turned out to be the "wrong way to do it" but you learned a lot from the experience, you get bonus points.

posted on Wednesday, September 26, 2007 8:17:19 AM (Central Daylight Time, UTC-05:00)  #    Comments [2]
# Thursday, August 30, 2007

I was messing around with some unit tests this week and I came across an unexpected benefit while working on code that worked with a COM object. When you add a reference to a COM library in .NET, you'll get an interface as well an implementation of that interface that forwards the calls to the COM objects.

Because an interface is created for the COM objects as well as the implementation, you can mock the COM dependency with Rhino Mocks or some other mocking framework. Just code against the interface instead of the concrete implementation and inject the concrete implementation via dependency injection for the normal scenario.

Let's say you wanted to unit test some code that had a dependency on the Windows Media Player COM object. Here's how you could do it.*

image

// Code to be tested
public class SomeClass
{
   private WMPLib.WindowsMediaPlayer _player;

   public SomeCode(WMPLib.WindowsMediaPlayer player)
   {
      _player = player;
   }

   public void DoSomething()
   {
      _player.enabled = false;
   }
}

// Unit test
[TestFixture()]
public class SomeCodeTest
{
   [Test()]
   public void PlayerEnabledShouldBeSetCorrectly()
   {
      MockRepository mocks = new MockRepository();

      // Mock the WMP interface... note that even 
// though it doesn't start with an 'I', // it is still an interface... WMPLib.WindowsMediaPlayer player = mocks.CreateMock(); // Inject the mocked WMP object SomeClass sc = new SomeClass(player); using (mocks.Record()) {
// Expect player.enabled to be set to false player.enabled = false; } using (mocks.Playback()) { sc.DoSomething(); } } }

I tried this code out and the test runs fine. Note the comment where the mock object is actually being created. For some reason, the interface to the COM object isn't named with an 'I'. It still is an interface, though. And you can create the COM object by saying 'new WMPLib.WindowsMediaPlayer' though I think that is some COM interop magic going on there (I'm guessing the CoClass attribute on the interface has something to do with this magic).

* I'm not actually mocking Windows Media Player in any of my code and I have no idea how well it will work. I do know that I can mock some of our own COM objects without any problems, though.

posted on Thursday, August 30, 2007 4:36:44 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Tuesday, August 21, 2007

I found myself writing the following code this evening:

public T GetItem<T>(string name)
{
    string result = node.SelectSingleNode(name).InnerText.Trim();
 
    return (T)GetConverter(typeof(T)).ConvertFromString(result);
}
 
private TypeConverter GetConverter(Type objectType)
{
    if (objectType.Equals(typeof(int)))
        return new Int32Converter();
    else if (objectType.Equals(typeof(bool)))
        return new BooleanConverter();
    else if (objectType.Equals(typeof(string)))
        return new StringConverter();
    else
        throw new ArgumentException("Does not support casting to " + objectType.Name);
}

Don't ever write code like this. Read the documentation which explicitly says that "you should never create an instance of a BooleanConverter". If you follow their advice, your code will become much cleaner. Like so:

public T GetItem<T>(string name)
{
    string result = node.SelectSingleNode(name).InnerText.Trim();
    return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(result);
}
posted on Tuesday, August 21, 2007 9:39:58 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]

I was looking through programming.reddit.com today and discovered that IronLisp now has a website on Codeplex. I haven't coded in LISP since college, but it was certainly an interesting experience.

This got me thinking - how many Iron* projects are there now? This is what I've come up with:

1) IronPython - the original Iron project?

2) IronRuby

3) IronLisp

4) IronXSLT - (thanks Michael!)

5) ...

Hmmm... as I was thinking about this blog post, I seemed to think there were a lot more out there. I know there are a lot of other languages that support the CLR, but I guess the Iron designation seems to be fitting with the languages that are build on top of the DLR. I'm a little curious if the Smalltalk/DLR implementation (Vista Smalltalk) will make the name change to IronSmalltalk or not.

So where did the Iron naming scheme come from anyway? Why not Nython1 or NRuby2? :-)

1 - The Java implementation is Jython.

2 - The Java implementation is JRuby.

posted on Tuesday, August 21, 2007 7:47:02 PM (Central Daylight Time, UTC-05:00)  #    Comments [3]
# Tuesday, August 07, 2007

I work with the WebBrowser control that was introduced in .NET 2.0 (as well as the ActiveX browser it is based on) a lot at work. As a result, I've come to learn a lot about some of the various intricacies that Internet Explorer has as well as the browser control in general.

Because we're not running some of our web pages in Internet Explorer but in a custom web browser, unit testing frameworks like Watir and Watin won't work for us. They make use of the Internet Explorer COM application. Unless we want to fork one of those frameworks as well as provide an automation interface into our custom browser, I don't see either of those frameworks working for us.

However, Selenium will work fine!

Selenium runs in the browser!

image

That's a picture of a little WinForms application I put together that is hosting the WebBrowser control. As you can see, all but one of shipped Selenium tests passed (the only one that failed had to do with opening an XHTML page).

Looks pretty good to me!

posted on Tuesday, August 07, 2007 1:51:25 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Thursday, August 02, 2007

(note - if you're reading this in a feed reader like Google Reader, sorry - the code snippets look awful... if anyone has any suggestions on good ways to get code to look good in the webpage and feed readers, I'd appreciate it)

Given this:

    delegate void WorkDelegate();
    interface ISomeInterface
    {
        void Execute();
    }

 

What is the difference between this class

    class TestCaseOne
    {
        ISomeInterface something = Activator.GetObject(typeof(ISomeInterface), "http://some.url.com/") as ISomeInterface;

        public TestCaseOne()
        {
            BackgroundWorker wkr = new BackgroundWorker();
            wkr.DoWork += new DoWorkEventHandler(wkr_DoWork);
            wkr.RunWorkerAsync();
        }

        void wkr_DoWork(object sender, DoWorkEventArgs e)
        {
            something.Execute();
        }
    }

and this class?

    class TestCaseTwo
    {
        ISomeInterface something = Activator.GetObject(typeof(ISomeInterface), "http://some.url.com/") as ISomeInterface;

        public TestCaseTwo()
        {
            WorkDelegate dlg = new WorkDelegate(something.Execute);
            dlg.BeginInvoke(MyCallback, new object[] { dlg });
        }

        private void MyCallback(IAsyncResult iar)
        {
            object[] asyncState = iar.AsyncState as object[];
            WorkDelegate dlg = asyncState[0] as WorkDelegate;

            dlg.EndInvoke(iar);
        }
    }

 

Both classes have a field named something that is a reference to an HTTP remoting proxy that has been published at http://some.url.com. Let's assume that the the HTTP Remoting configuration has already been set up. Both call the Execute method defined on the interface, but one is using a BackgroundWorker for threading and the other is using the BeginInvoke/EndInvoke means of threading. Big deal, right?

There isn't a huge difference just looking at the code -- except that with TestCaseOne, the remoting call will result in a blocked thread whereas TestCaseTwo will not. In TestCaseOne, the background thread will block on the something.Execute() call and wait for it to return. In TestCaseTwo, the WorkDelegate BeginInvokes on the transparent remoting proxy. There isn't any code to block on. Instead, the framework will let you know when your remoting call returns.

Why does this matter? When you have a blocked thread, you basically have wasted CPU cycles where it is blocking instead of working. This likely won't matter much if you're not working with a lot of threads, but it can cause performance problems if you're working with a lot of threads.

On the other hand, when TestCaseTwo calls back to let you know the remoting call has completed, it will not call back on the calling thread. BackgroundWorker is smart enough to invoke back to the UI thread if needed. Both have their pluses and minuses. The BackgroundWorker component does make the code a little more easy to read and it handles invoking back to the UI thread. However, if you're working with a lot of threads, you might try using the delegate approach instead, so as to avoid any blocked threads.

posted on Thursday, August 02, 2007 10:40:25 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Friday, July 13, 2007

Visual Basic annoys me because of the way arrays are initialized.

What's the semantic difference between the two lines of code below?

C#

int[] test = new int[10];

VB.NET

Dim test(10) As Integer

Here's a hint - one array has ten items and one does not. The VB.NET array has eleven elements. When you declare an array in VB.NET, you're specifying the upper bounds of the array instead of the length. This drives me insane. We regularly go between C# and VB.NET and I am constantly bit by this one.

I was talking with a guy at work today and we discussed how we'd like to have another option setting (in addition to Option Strict and Option Explicit) available for VB.NET:

Option OperateLikeAllOtherLanguages = True

This setting would allow VB.NET to initialize arrays like all other languages.

NOTE: This post is satire. I still like to program in VB.NET and C#. I do not want to get into which language is better. Both languages have their virtues. Learn them both. Then go learn Ruby.

posted on Friday, July 13, 2007 2:02:19 PM (Central Daylight Time, UTC-05:00)  #    Comments [1]
# Thursday, July 05, 2007

In the few years that I've worked as a software developer, I've read and seen many examples of testing software. As a result, my own thinking regarding testing has changed drastically over the past year or two. It seems that there is a continuum behind the thinking that goes behind testing. I originally titled this post "the Evolution of Testing Thought Processes" but evolution doesn't describe this as well for me, because I find myself moving between the different processes depending on the circumstances.

This post has a few goals:

  1. I want to gain a better understanding of where I stand regarding testing code.
  2. I want to share some of these ideas with others, particularly my coworkers, who might not have encountered ideas like unit testing.
  3. I want to get your input on this and see if anyone else struggles with these issues, too.

 

Here are the different thought processes that I've seen regarding testing:

No Testing (i.e. did it compile?)

This one's easy to categorize, right? Basically, no testing happened whatsoever. If it compiles, you're set. If you're working in a dynamic or interpreted language, then good luck. Hopefully, you've never seen this one before, but I wouldn't be surprised if you have.

I have a horror story to share regarding this. A few years ago, my team was on track to install a fairly substantial update to a daily scheduled application. The update unfortunately required some changes to the script that kicked off the whole process. Because my team didn't own this script, we had to get someone else to do it. What we didn't know is that a certainly individual who will remain nameless decided to convert this script from REXX to VBScript. This would have been a good change at the time, had we prepared for it. Needless to say, this wasn't even the worst part.

This individual never even attempted to run this script.

You heard me - this individual converted a script from one language to another one and never tested the script at all. How could I possibly know this when I didn't even know the script was being converted? Because when the script was scheduled to run the next day, it blew up. It blew up because of invalid syntax. It blew up because there was VBScript code at the top... and REXX script at the bottom. I spent the better part of two days attempting to fix that problem.

The lesson here is to at least run your application once before installing. I don't care if you're the best developer in the world. You can still make mistakes.

Don't do this.

 

Manual Testing (i.e. F5 testing)

Manual testing is when developers run their application and attempt to test all of the functionality themselves. If they don't spot any problems, then the application is ready for production.

I used this technique the most while in college. If my professor could break our application with invalid input, then our grade would drop. For each problem the professor found, the grade would continue to drop. The majority of the applications that I wrote during this time were command line applications, so most of the user interaction was pretty easy to verify. I missed a few edge cases sometimes, but I was able to test the basic functionality because the application itself was so simple.

I consider having someone else test your application an example of this as well. My experience is that usability problems are discovered here instead of bugs. The problem is that most developers have their own projects to work on, so testing your application isn't exactly at the top of their list of things to do. In other words, their testing will likely be even less rigorous than your testing.

 

Manual Unit Testing

This is a small variation on manual testing the whole application. At this point, you are testing smaller units rather than an entire application, which is a good thing. To do this, you typically have either a command line interface, a small form or a small web page that uses the small unit from your application. Your UI likely performs a few actions on your library and you then examine the results for problems. Sometimes, you'll enter a few input details to test different scenarios. Ideally, you'll test as much of the functionality that the library provides as possible.

The most common place I see this is when someone has written a shared component or created some external assembly that will potentially be used by someone else. It doesn't have a UI of its own, so to test it, you have to create something else to run it.

On the testing continuum, this is the first case where application testing is broken up into pieces. Developers can test parts of the application separate from the rest. As a result, there is less to distract developers.

 

Unit Testing

The problem with manually testing units of an application is that verification of the results is still dependent upon the developer. Everyone makes mistakes so it is only a matter of time before someone misses a problem. Unit Testing takes the last approach and expands upon it by letting the computer decide whether or not your library is working correctly.

With a manual test application, you simply look at the results that your test UI provides. Why not put those results (expectations) into code? The test can then be much more precise about its results. For example, it is much easier to determine if a returned numeric type is an integer or decimal value from code than you can from a UI. In .NET, you can just check the type. Better yet, you know immediately from code whether or not that is a "0" or an "O".

These tests provide value during development time, but particularly during maintenance time. Imagine that a user of your system decides that they want to change something. Crazy, right? Have you ever made a change to an existing system and then broken existing functionality elsewhere in the application? This is why regression testing is necessary. Unit testing makes regression testing even easier because the list of tests you have stays with the application. As you find new bugs, you can write tests for those so that they never show up again.

Tool support for unit testing is awesome, too. With tools like MbUnit, NUnit, TestDriven.NET and others, it is easier than ever to write and use unit tests. The tools get better with each release, too. One of the things that is nice about the unit testing libraries available is that they all have test runners that generate reports. This allows you to automate the testing and tie it into your build process or test your code nightly or whatever. That is one of the ideas behind Continuous Integration. Every check-in of an item into source control results in a build script running which can also run tests. Not only do you find out if you broke the build, you also find out if your tests now fail.

One of the problems that people have with unit tests is that they feel like they spend twice as long on code because they're writing tests in addition to the code that will run on a user's machine. Doesn't that increase development time? In my experience, it adds to the time (though not twice as long) of the first iteration of software development, but it can significantly cut down on latter iterations. Have you ever maintained legacy code? I hate working with legacy code because half the time I end up breaking existing functionality. With unit tests, when I later have to come in to change a program, I can feel confident knowing that I'm not breaking existing functionality.

 

Test Driven Development

How about writing your unit tests first? That will blow your mind the first time you think about it. The idea behind Test-Driven Development isn't so much that you're writing a test first as you are designing the contract for your class from the outside. Proponents of test driven development very often state that this development methodology helps drive their design more than providing a good test framework. The test framework is an added benefit to good and extensible design.

This is the hardest of the thought processes behind testing to really grasp, at least for me, because it requires a change in the way you think about developing software. Some don't see the benefits from it and others wouldn't program without it. I certainly can see the value in it, but I haven't had enough real world experience actually doing it to be effective with it yet.

 

So, did I miss anything? Where are you on the testing continuum? I find that I move back and forth between Manual Unit Testing and Test Driven Development. I'd like to move more towards TDD, because it is certainly beneficial and I find that code designed with testability in mind is much easier to modify later.

One thing to remember is that all of these ideas play a part in testing an application... except for the not testing idea. At some point, you'll need to actually run your application to try it out. If you employ unit tests, they'll simply provide more confidence in the application and provide future insurance when the code changes - and it will change.

For more information, check out this software testing article on Wikipedia.

posted on Thursday, July 05, 2007 2:12:09 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Tuesday, June 19, 2007

I just completed the Classic Mistakes survey from Construx. Thanks to Jeff Atwood for pointing this one out.

The survey itself didn't seem particularly helpful, but the questions it poses do help in enumerating many of the problems I've experienced by actually putting them into words.

It also is beneficial to me because some of these mistakes stem from the developers instead of the management. I've been guilty of developer gold-plating and the silver-bullet syndrome many times, which is likely a result of being a beta junkie. We're in the process of moving to .NET 2.0 (no, not even .NET 3.0 or 3.5 yet) and I'm already jumping to move to Visual Studio 2008 (formerly Orcas). I mean, surely WPF, Linq, and WCF would solve all of our problems wouldn't they? Or, if we suddenly went 100% with Test Driven Development, all of our problems would disappear! Wouldn't they?

Sam Gentile's comments on writing maintainable code are very relevant to silver-bullet syndrome. He points out that the XP methodology revolves around 12 practices and not TDD by itself. TDD isn't a silver bullet but instead is a tool to help document and protect your codebase. You also have to work at refactoring your code and keep it clean and simple.

I haven't ever worked in an XP/Agile environment before, but I do like the goals that it strives for. I'm really pushing my team to learn more about architecture, design, and unit testing because I really do see the value. We really have to just start using these tools. Otherwise, we'll keep talking about them and never actually do anything.

Thank goodness for all these tech blogs. I've learned more from reading these in the past couple of years than I have from just about anything else. It's almost like I'm being mentored by all of the more experienced developers.

posted on Tuesday, June 19, 2007 9:52:51 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Thursday, April 12, 2007

Scott Hanselman recently posted about a bug that can occur when using Firefox as your default browser. The root problem deals with Outlook trying to start up Firefox using DDE instead of just a simple command line argument. At work, we ran into a very similar situation, because we were wanting to open up URLs in the default browser from our application. Normally, this would be easy because all you would have to do is Process.Start the URL without providing an application and ShellExecute would handle the rest for you. Needless to say, this wasn't going to work for us because we had overridden the default open action for URL shortcuts with our own action (it's a long story that I won't go into in this post).

Our solution started with pulling out the default browser from the registry (we still kept the original open action command, see HKEY_CLASSES_ROOT\HTTP\shell\open\command). Once we have the value, we thought we would be able to Process.Start the command line from the registry passing in the specified URL. We tested it out in Firefox and everything worked great. Even better, Firefox would reuse windows based on the user-defined settings.

Not so with Internet Explorer. Internet Explorer would open the URL for us, sure, but it would not respect the user-defined settings on the reuse of windows. This was confusing to us, because Outlook was smart enough to get Internet Explorer to reuse windows. The question was how it was happening... and that's where DDE came in.

When Outlook opens a URL shortcut, it connects to the DDE IExplore server on the WWW_OpenURLNewWindow topic. If he is able to connect, then Internet Explorer is already running. He then sends an XTYP_EXECUTE transaction passing along the URL. If everything works correctly, then Internet Explorer will open the new window and bring it to front for you. If no Internet Explorer instances are running, Outlook will start a new instance.

In case you were wondering, this was all verified using DDESpy (which you can find in the Visual C++ 6.0 Tools installation... if you still have it). It was also tested against Internet Explorer 7 and Outlook 2007 which means this information is still current.

And yet, Raymond Chen has encouraged us to stop using DDE, because "DDE has been dead as a shell interface for over ten years." Oh how I wish that the Internet Explorer team knew that. If they had, we wouldn't have had to code up DDE to get similar behavior in our application. And let me tell you, DDE is not fun to code against. There are very few resources covering DDE on the Internet (probably because DDE died before the Internet became really widespread... or not).

posted on Thursday, April 12, 2007 8:54:14 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Thursday, March 29, 2007

If you're not already subscribed to Jeremy Miller's blog, do so now. I'll wait for you to come back.

Okay, now that you've done that, read his latest post on sunk costs and architectural decisions. I'll keep waiting.

Done? Good.

As I was reading his post, I found myself nodding my head in agreement over and over again because I've been dealing with the exact same issues at work for the past few months. Sunk costs are something that every business deals with. A sunk cost is when you've already spent money on something and you later wish that you hadn't spent that money. The Wikipedia example that Jeremy cites of going to see a bad movie is the classic example of sunk costs.

One of the biggest problems with sunk costs isn't the actual cost involved but the fact that as soon as you admit you're dealing with a sunk cost, you're also admitting that a bad decision was made somewhere. This can lead to hurt feelings, hurt pride, etc. Jeremy points out that there can be political implications of this as well. Management will not be happy to find out that this awesome tool that was supposed to bring world peace, cure cancer, and solve the energy crisis actually is too slow for the masses to effectively use. They're likely going to question more than just the tool afterwards.

However, I submit that these same sunk costs can provide an incredible benefit to developers. One of the quickest and most efficient ways to learn is to make mistakes. If you get burned badly enough, you're not going to touch the hot stove again, because you now know that it is hot. If you're the one who is responsible for the bug that cost your company thousands or millions of dollars, will you make that same mistake again? Of course not!

Learn from your mistakes! I've been fortunate to be a part of a similar process and the results so far have been very positive. Our team has really come together and pushed out some really good code that our users are very happy with. Prior to starting the rework, we had all been dreading continuing to deal with the prior version of the product, because we knew we would be spending our time hunting down obscure bugs and hearing complaints from users. The question we continually heard from users was, "why is this better than before?" We hated the question because we didn't like the system either! Now, we can tell them with confidence that our work is without a doubt better and that we're behind it 100%.

From the management side, I submit that managers who give their teams a chance to fix mistakes and start over can gain a great deal of respect from their team. Our manager had ties to the prior system, but he also knew there were problems with it. The system had gone through three different groups before we had ever been given responsibility over it! No one even knew the system anymore! Not only did we come together as a team more, we also became more familiar with the code and were able to really take ownership of it. A positive response to problems or mistakes reflects a real maturity in leadership.

You can treat sunk costs as a straight loss and accept defeat. The better alternative is to treat them as a training expense. The benefits from training are not tangible, but most companies still spend money on their employees because they can become more efficient. Similarly, when we respond to sunk costs positively, they can provide the same kind of intangible benefits as training. Mistakes were made, but mistakes are an opportunity for growth. We all write bad code. Just be sure you learn from it and become a better developer!

UPDATE: Some clarification on sunk costs - a reader pointed out that a sunk cost isn't necessarily a bad decision or mistake, just an unrecoverable past expenditure. I'm no economist, but it seems that the term typically carries negative connotations.

posted on Thursday, March 29, 2007 8:39:07 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Tuesday, March 27, 2007

Lately, I've been working on performance enhancements to one of the projects at work. Our users had all mentioned that the application's startup time was pretty slow and wanted to know if we could do anything to speed it up. Of course, when all of your users have been using green screen applications, even native C applications will likely seem slow to them... but anyway. We started digging in and found a few places where we could optimize our code but our form still took a while to load.

While testing, I happened to have Process Explorer up and noticed that our process was kicking off csc.exe, which is the C# compiler.

This is one of those instances where some (if not all) of you will know what I was seeing here. You see, we were using XML serialization in our project. When you do XML serialization, some code-gen happens to make the serialization magic work. If you have FileMon or ProcMon up, you'll actually see a temporary C# file being written out and compiled. I might have remembered this (Scott Hanselman has a lot of posts on the XmlSerializer) if I had thought about the temp file aspect, but I was wondering more about the C# compiler.

Anyway, the best way to avoid this precompilation step is to do the precompilation yourself using sgen. Basically, if you give it an assembly named Foo.dll, you'll get back an assembly named Foo.XmlSerializers.dll.

My only question regarding sgen is why standard compilation doesn't do this for you automatically. I'm sure there is some reason why, but I haven't thought of it yet. Regardless, I went ahead and added it to our build script and we've seen increased performance.

As a side-note, Red Gate's ANTS Profiler is an awesome profiler tool to help you find bottlenecks in your code. It will put big red lines next to the code that takes a long time to run.

posted on Tuesday, March 27, 2007 7:55:46 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Friday, March 02, 2007

Your programmer personality type is:
DHSC

You're a Doer.
You are very quick at getting tasks done. You believe the outcome is the most important part of a task and the faster you can reach that outcome the better. After all, time is money.
You like coding at a High level.
The world is made up of objects and components, you should create your programs in the same way.
You work best in a Solo situation.
The best way to program is by yourself. There's no communication problems, you know every part of the code allowing you to write the best programs possible.
You are a Conservative programmer.
The less code you write, the less chance there is of it containing a bug. You write short and to the point code that gets the job done efficiently.

Find out your score at http://www.doolwind.com/index.php?page=11.

posted on Friday, March 02, 2007 7:36:27 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Monday, February 12, 2007

Lately, I've been doing some work with the WebBrowser control (new in the 2.0 framework). It really does offer a lot of benefits over directly using the underlying ActiveX web browser control. And when the new functionality doesn't cover a need you may have, you can always get at the ActiveX control (though you'll need plenty of COM interface definitions - hello pinvoke.net!).

The typical usage scenario with the WebBrowser control is that, if you want more than just a basic control, you're going to inherit from it. I was wanting to be able to provide a custom context menu instead of using the default IE one. Here comes MSDN documentation to the rescue! According to the documentation on the protected CreateWebBrowserSiteBase method, the method can be overridden to provide a custom WebBrowser.WebBrowserSite object. Here's the quote from the documentation:

To use this feature, implement classes that inherit from the WebBrowser and WebBrowser.WebBrowserSite classes. The unmanaged WebBrowser ActiveX control uses the protected CreateWebBrowserSiteBase method to retrieve extensibility interfaces implemented by the WebBrowser.WebBrowserSite class. Override the CreateWebBrowserSiteBase method to return an instance of your own class that inherits from the WebBrowser.WebBrowserSite class. The WebBrowser.WebBrowserSite class provides default implementations of the OLE IDocHostUIHandler. You can provide your own implementation of this interface or implement any other WebBrowser ActiveX control interface in order to customize the behavior of the control.

Super!

Because the WebBrowserSite class is protected and internal to the WebBrowser, your implementation must be internal to your inherited WebBrowser class to have access to it. Like so:

public class CustomWebBrowser : WebBrowser
{
	private class CustomBrowserSite : WebBrowserSite
	{
		// Your implementation
	}
}

So, I happily pulled up the interface definition for IDocHostUIHandler, coded it up and made my custom WebBrowserSite implement it. To verify that it was working, I just stuck a message box to tell me hello in the ShowContextMenu method. When I ran my test, I right clicked and saw a context menu... the default context menu! Huh?!?

I was positive I must have missed something, because the documentation is CLEAR on the fact that this scenario is possible.

And yet... and yet... WHAT IS THIS?!?

More searching and I find that there is a bug reported for this exact scenario on Microsoft Connect! And what's more, it has been closed because it has been postponed!!!

This wouldn't really irk me so much except that the documentation specifically says that it can be done. Here is a snippet of the reasoning behind closing the bug:

... The bug you entered has been reproduced, but our evaluation determined that it does not meet the criteria to be addressed in this release. The main reason for this is that in this release, our webBrowser control is tightly tied to the IDocHostUIHandler not leaving much room for such customization. ...

Why, oh why wasn't this tested? The documentation says THAT THIS CAN BE DONE! Don't post documentation that says that you can do this and then tell us that you can't because your implementation won't allow it!

Luckily, there are 2 workarounds listed that let you hook your own IDocHostUIHandler implementation in (it involves implementing ICustomDoc and calling the SetUIHandler method, see this CodeProject article for more details). Tightly tied my butt... the workaround gets the same results just fine.

posted on Monday, February 12, 2007 1:01:36 PM (Central Standard Time, UTC-06:00)  #    Comments [1]
# Monday, December 11, 2006

I'll tell you what it looks like.

It looks like -1.#IND.

That's what it looks like. At least if the code is using the Double.NaN constant. I sure didn't know that before I saw it and, I can tell you, it sure freaked me out when I saw that in the immediate window in Visual Studio. I was working on speeding up another dev's code here and apparently they were using NaN to signify the difference between 0 and "not yet initialized." It works pretty well for them in that case, but as I said, if you're not expecting that, it very well may throw you off.

And PowerShell is smart enough to just say NaN instead of this -1.#IND stuff.

Along the same lines, -1.#INF is apparently how Infinity is represented.

(IND would be indefinite whereas INF is infinite... makes sense I guess.)

posted on Monday, December 11, 2006 2:34:15 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Sunday, September 24, 2006

Last month (almost two months ago!), I posted on how to programmatically get the caption for an image in C#. I haven't posted much more on the subject lately, because I've been busy with other things like playing with Vista RC1 and different unit testing frameworks. I also have learned a lot more about the different methods for storing metadata in images. My previous method ONLY works for images where the metadata is in the EXIF format. There are a variety of different metadata formats available and I discovered that not all of my digital pictures use EXIF. In other words, my previous post DOES NOT WORK for those images. I also discovered that there is no reason to use my previous method, because Omar Shahine has already done all of the hard work here.

If you're interested in EXIF metadata, use his PhotoLibrary. It is a very well designed library for setting and retrieving EXIF metadata on images. I really wish I had known about it a couple of months ago, but at least I learned some stuff on my own. That's always nice. The problem is, once again, that it only works with EXIF metadata. Basically, I wanted a solution that gave me the same results that Windows Explorer file properties provides. I wanted the caption regardless of the metadata format.

The solution? Windows Presentation Foundation!!! WPF provides a completely new way to look at images. There is a great overview in the MSDN documentation here.

The short of it is that you can write code like this, though:

ImageSource src = this.image1.Source;

BitmapMetadata bm = ((BitmapMetadata)this.image1.Source.Metadata);

MessageBox.Show(bm.Title);

Neat, eh? What's even better is that it works for every image I've tested with it so far. The only other code in my small example is some XAML to get an image loaded and the code to get a click event handler so I could see the results of my test.

Nice!

I guess my new Gallery Manager application will target the .NET 3.0 Framework!

Note - for uncommon metadata attributes, there is a GetQuery property that BitmapMetadata provides. I haven't looked into much, but it looks like it covers many of the various metadata formats available. You just have to know the query syntax... which I currently don't. If anyone knows of any good resources on this, please let me know!

posted on Sunday, September 24, 2006 10:12:45 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Monday, August 21, 2006

(After yesterday's post on getting metadata from images in .NET, I've decided to continue to post some of the information I find regarding working with images in .NET.)

As I mentioned yesterday, I'm working on an application to export a folder of images over to a webpage or something (I haven't decided on the output format, whether to a database, XML, or what). I've been learning quite a bit about .NET image support (primarily from GDI+) and it really provides a lot right out of the box. Today's post is on resizing an image without losing too much quality in the process.

The first resource I found was System.Drawing.Image.GetThumbmailImage. My first thought was, "Surely it isn't this easy!" I was right - it wasn't that easy. Check out this quote from the remarks section of the documentation:

The GetThumbnailImage method works well when the requested thumbnail image has a size of about 120 x 120 pixels. If you request a large thumbnail image (for example, 300 x 300) from an Image that has an embedded thumbnail, there could be a noticeable loss of quality in the thumbnail image.

My first test was resizing an image that was originally 2580 x 1932 down to 640 x 483. It looked quite nasty after trying to call GetThumbnailImage. Back to Google I went, but thankfully I soon hit paydirt. I found the "Resizing a Photographic image width GDI+ for .NET" article by Joel Neubeck on CodeProject. The meat of the functions he provides are that they give examples on how to carry the resolution of the original image over and also how to use bicubic interpolation. With his code, my 640 x 483 picture still looks great - just as good as Picasa does for its export code!

I will say that I am still using the GetThumbnailImage method for what it was primarily designed for: thumbnails. As the documentation says, it works fine up to about 120 x 120. I'm personally using a max width/height of 90 for my thumbnails right now. Here's an example of a call to GetThumbnailImage just so we'll get some code in this post:

private static void CreateThumbnail(Image img, string path, Size imageSize)
{
    // Only call this to create thumbnails smaller than 120 x 120! Otherwise, check out 
    // http://www.codeproject.com/csharp/imageresize.asp.
    
Image thumbnail = img.GetThumbnailImage(
        imageSize.Width,
        imageSize.Height,
        (
delegate { return false; }),
        
IntPtr.Zero);
    thumbnail.Save(path);
}

As you can see, I'm using an anonymous delegate for the 3rd parameter, which presumably only exists for backwards compability, because it isn't called. It makes more sense to me to do it this way than to add a function that won't even be called.

posted on Monday, August 21, 2006 10:12:41 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Sunday, August 20, 2006

So, this is a little off-topic compared to some of the other posts I have done lately, but it was something new to me and I thought I'd share it for information... and as a means of helping me remember it later!

At home, I have been using both Microsoft Digital Image Library 2006 and Picasa to manage my digital pictures because I like features in both. Microsoft's product provides some nice editing features and tagging while I've been using Picasa's export as a webpage in an XML format for mine and my wife's blog. One of the hassles between the two, though, is that they store captions for images differently. I was having to manually copy and paste captions between both programs, which is huge time waster. Because I wanted to continue using Digital Image Library, I decided to write a program to export the gallery. (I know there are programs out there that can do this for me... I've got the programmers' disease!)

To write this program correctly, I wanted to still be able to pull out information like the captions I had set for each picture. I ended up digging around a little bit researching the different implementations for storing metadata in the files and it would appear that Microsoft's implementation seems more standard than that of Picasa. In fact, some digging in one of my pictures using a hex editor shows the proprietary <picasastamp> enclosing a <caption> tag. At least that means it will be easier to pull the caption out.

Probably one of the best places to start for researching this is the MSDN how to: Read Image Metadata. It details the PropertyItem that you can get off of the System.Drawing.Image class. There is actually a collection of PropertyItem objects from the PropertyItems collection. Basically, you can loop through the collection and inspect each item's Id property until you find the one you are looking for. That's the easy part. The hard part is figuring out which Id you're interested in because they don't have user-friendly names like "Caption" or "Title" - they're in hex. Thanks to this sort of random post, I was able to find out that the captions I was looking for were 0x9c9b.

So, without further ado, here's a very simple GetCaption method that will return the caption/title based on an Image passed to you:

public static string GetCaption(Image img)
{
    if (img == null) 
        throw new ArgumentNullException("img");

    Encoding enc = Encoding.UTF8;

    foreach (PropertyItem prop in img.PropertyItems)
    {
        if (prop.Id == 0x9c9b)
        {
            return enc.GetString(prop.Value).Replace("\0", "").Trim();
        }
    }

    return string.Empty;
}

Let me know what you think!

If you're interested in more about the PropertyItem class, check out these pages - they've got some nice information on them as well.

- http://www.codeproject.com/cs/media/photoproperties.asp
- http://www.pixvillage.com/blogs/devblog/archive/2005/03/27/176.aspx

posted on Sunday, August 20, 2006 9:21:59 PM (Central Daylight Time, UTC-05:00)  #    Comments [2]
# Friday, August 18, 2006
This post is just as much for me as it is to share...

I was attempting to create a automatically resizing GroupBox control that would let users drop controls on it and it would grow as the controls dropped. I also wanted to offer a FlowLayoutPanel-like ability so that it would slide controls that were lower up if higher controls were hidden. Doesn't sound too bad and we would use it enough that it made sense to encapsulate it in a custom control. I started looking into inheriting from GroupBox and adding a FlowLayoutPanel to it's control collection. Then I hooked into the ControlAdded event for the GroupBox so that I could move the control from the GroupBox to the FlowLayoutPanel. I'm just walking you through the steps in my thinking process here... this apparently isn't how it should be done, because though it worked if controls were added at run-time, it gave me a weird designer error that said "'child' is not a child control of this parent" (like these guys did).

What research I came up with looked like I would have to create my own custom designer to support code like this, that would also include code serialization into InitializeComponent. Yay. A little more research brought me this link, though. It details how to drop controls onto a UserControl at design time. It is a slightly different approach, but it provided what I needed. Basically, the solution also involves using a ControlDesigner, but the code seems much less involved than if I were handling code serialization.

Here's a code snippet to give you an idea of what I did:
<Designer(GetType(AutoResizeGroupBoxDesigner))> _
Public Class AutoResizeGroupBox
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
Public ReadOnly Property FlowPanel() As FlowLayoutPanel
Get
' Where _flowPanel has already been added to the designer
Return _flowPanel
End Get
End Property

' code snipped...

End Class

Public Class AutoResizeGroupBoxDesigner
Inherits ControlDesigner
Public Overrides Sub Initialize(ByVal component As System.ComponentModel.IComponent)
MyBase.Initialize(component)
Dim autoGroupBox As AutoResizeGroupBox = DirectCast(component, AutoResizeGroupBox)
EnableDesignMode(autoGroupBox.FlowPanel, "FlowPanel")
End Sub
End Class
posted on Friday, August 18, 2006 7:58:52 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Thursday, July 20, 2006
Like many other users of Visual Studio 2005, I've occasionally received the WSoD (White Screen of Death) while using the designer. And like a typical user, I blamed it on Visual Studio. That's what users do, right? They blame the program, because the user is always right. The same behavior that frustrates me to no end when users enter invalid data into MY program and then blame MY program (of course, if my UI were better, it wouldn't be as difficult to use, but that is another story). Anyway, my frustrations with VS2005 crashing and the WSoD's were in fact a problem with the user - me.

In one of my forms, I had some background threading work that was started when the form loaded. Like a good programmer, I had wrapped this threading work in a check against Me.DesignMode to ensure that it wouldn't try to do this work while in the designer. What I didn't know at the time is that the DesignMode property isn't set until AFTER the constructor fires. I checked around with some guys at work and I discovered that I wasn't the first one to discover this. They had already put a check against Application.ExecutablePath to see if it was devenv.exe. If it is, then we're in DesignMode. Simple as that!

So, all of my VS crashes and weird WSoD's have now been tracked back to my OWN code. HOWEVER, I would like to say that it would have been nice if Visual Studio had given me a better message to inform me that my designer code was trying to run background threads or something - in much the same way that my own code should work better and give my users better messages.

Ah, the joys of user interaction.

Note: This fixed the problem suggested after sending error reports that link to this hotfix (http://support.microsoft.com/?kbid=915038). If you're running into this, check and double-check the code in your UI constructors, INCLUDING base class constructors!
posted on Thursday, July 20, 2006 11:22:10 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Friday, June 30, 2006

If anyone out there knew about the BindingList before today, I sure wish one of you would have told me. Now I know, if you had known I was looking for something like the BindingList, you would have told me, but still...

Okay, all joking aside, the BindingList is what I've been trying to find for a long time. With Visual Studio 2005, the option to bind to an object data source is now possible (see screenshot).

The typical usage scenario for me with this data binding option is that I have just used .NET remoting to pull a collection of business objects back from a remote server. After that, I usually want to bind this collection to a datagrid or something like. For the past few months, I had used the new BindingSource object and set its DataSource property to my collection (usually a System.Collections.Generic.List<T> or a System.Collections.ObjectModel.Collection<T>). The problem I had was that any changes to either of those collections later would not fire ListChanged events. I had settled myself to the fact that I would have to reset the binding everytime.

Well, not so!

Dinesh Chandnani posted to his MSDN blog over a year ago about this subject. Too bad I didn't find it until today. In his post, he provides some very simple code examples, one of which details how to get a "DataGridView bound to business objects." *gasp!* Where have I been? This is what his code looks like:            

            DataGridView dgv = new DataGridView();

            BindingSource bs = new BindingSource();

            BindingList<Customer> bList = new BindingList<Customer>();

           

            // Fill bList with Customers

 

            bs.DataSource = bList;

            dgv.DataSource = bs;

 

I wish I known about the System.ComponentModel.BindingList<T> before now. It would've saved me so much time. If you're still trying to bind to a List or Collection like I was, take that guy out and bind to the BindingList instead! It really works the way you would expect it to!
posted on Friday, June 30, 2006 12:31:42 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Tuesday, June 27, 2006
I'm not sure how often people run into situations where the ManualResetEvent is needed, but I have a few times. System.Threading.ManualResetEvent provides an easy way to allow cross-thread communication and to let other threads know when something has completed. Most of the time that I've needed it, I have a property in a class that is loaded in another thread, but I want to prevent access to the property until it is loaded. From what I've seen, this is a great time to use the ManualResetEvent.

It is easiest to explain with some code snippets. Here's how you create the ManualResetEvent.

Private _dataLock As New ManualResetEvent(False)

The constructor takes a boolean that signifies whether the object is signaling or not. A signaling object implies that the action has been completed... we're done with the work. If signaling is false, the work hasn't finished yet.

To wait on the signal, use this code:

_dataLock.WaitOne()

You can also specify a period of time to wait instead of waiting indefinitely.

Once your background work is completed, you can call Set like so:

_dataLock.Set()

This begins signaling, so any calls to wait will stop blocking and will continue execution.

Here's a full code sample that shows how it would work and also gives a short example on the BackgroundWorker.

Imports System.ComponentModel
Imports System.Threading

Module Module1

    
Private _dataLock As New ManualResetEvent(False)

    
Sub Main()

        Thread.CurrentThread.Name =
"[Main]"

        Dim wkr As New BackgroundWorker
        
AddHandler wkr.DoWork, AddressOf wkr_DoWork
        
AddHandler wkr.RunWorkerCompleted, AddressOf wkr_RunWorkerCompleted

        wkr.RunWorkerAsync(
"Get to work!")

        Write(
"Waiting on the lock...")
        _dataLock.WaitOne()
        Write(
"we're back!")


        Console.WriteLine(vbNewLine &
"Press any key to continue...")
        Console.ReadLine()
    
End Sub

    Private Sub wkr_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs)
        Thread.CurrentThread.Name =
"[Work]"

        Write("DoWork just received this value: " & CStr(e.Argument))
        Thread.Sleep(
5000)

        e.Result =
"DoWork finished!"

        Write("DoWork is done so start signaling completion.")
        _dataLock.Set()
    
End Sub

    Private Sub wkr_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs)
        
Dim wkr As BackgroundWorker = DirectCast(sender, BackgroundWorker)
        
RemoveHandler wkr.DoWork, AddressOf wkr_DoWork
        
RemoveHandler wkr.RunWorkerCompleted, AddressOf wkr_RunWorkerCompleted
        wkr.Dispose()
    
End Sub

    Private Sub Write(ByVal s As String)
        Console.WriteLine(
String.Format("Thread: {0}, Message: {1}", Thread.CurrentThread.Name, s))
    
End Sub

End
Module

The output from running looks like this:
Thread: [Main], Message: Waiting on the lock...
Thread: [Work], Message: DoWork just received this value: Get to work!
Thread: [Work], Message: DoWork is done so start signaling completion.
Thread: [Main], Message: we're back!

Press any key to continue...
One thing to remember: do NOT put the call to Set (i.e. _dataLock.Set()) in the thread where you are waiting (i.e. _dataLock.WaitOne())! You'll never get the signal because that thread is already blocking! Because of this, make sure your call to Set always happens in the DoWork event of the BackgroundWorker instead of the RunWorkerCompleted event.
posted on Tuesday, June 27, 2006 12:59:56 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Thursday, June 22, 2006
I can't help myself, PowerShell is great and I keep finding useful things to do with it. Most of what I've been finding is easily accomplished in other ways, but this just goes to show the power available straight from the PowerShell command prompt.

What if you want to know the full path to all of the solutions in a sub-directory?

You could try this:
PS C:\Dev>dir -recurse -include *.sln . | foreach { $_.FullName }
This builds on my post from yesterday.
posted on Thursday, June 22, 2006 3:42:46 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Wednesday, June 21, 2006
dir -recurse -include tempproj.proj | foreach { rm $_ }
Awesome!

Recursively removing files!
posted on Wednesday, June 21, 2006 4:40:16 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Thursday, June 15, 2006

We were working with partial classes recently at work and we came up with a best practice usage for naming them, at lease for our needs, and I thought I would share it with you.

Basically, do it the way Visual Studio does. For example, with GUI components such as forms, VS2005 names the main class Form1.vb, while it names the partial class Form1.designer.vb. So, if you want to make your Shipment class have a partial piece, have a file that is Shipper.vb and Shipper.stuff.vb.

This way, it is clear by the naming that the files are related. Otherwise, I would think there would be a lot of confusion on how the files are related.

Any thoughts on this?

posted on Thursday, June 15, 2006 12:44:28 PM (Central Daylight Time, UTC-05:00)  #    Comments [1]
# Wednesday, June 07, 2006
Most of you probably are already aware of this little development, but there is a freeware IDE for PowerShell development (Scott beat me to the post...). It really is great. One of the most interesting parts about it, at least at first glance, is that it gives a first look at what an IDE might look like if it were to use Office 2007's ribbon. Not only that, but it even has an Mac OS X styled (or ObjectDock if you're so inclined) tool section in the bottom right.

Sweet!
posted on Wednesday, June 07, 2006 7:58:55 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Tuesday, June 06, 2006
As many of you are aware, if you attempt to access your Outlook data using some of the Outlook Interop assemblies, you'll be seeing a security dialog informing you that something is attempting to access your emails and whether or not you will allow this. If you're like me, you've run into this before and attempted to circumvent it.

Well, with the advent of Office 2007, we can all breathe a huge sigh of relief. Why, you ask? Because the fine folks at Microsoft heard our collective annoyances about the security model and fixed it! For the long story, check out this MSDN article. Here's the gist of it:
Outlook 2007 introduces an important change in the way that the Outlook object model guard operates. While the behavior of the object model guard has not changed significantly for Outlook add-ins, Outlook 2007 allows external applications to run without object model guard prompts—provided that the computer on which your code is running has functional antivirus software installed and that all antivirus definitions are current."
I've bolded the important part for you. Now, you'll only get the warning if your antivirus software is out of date. You also have the option to either always show the warnings (yeah, right) or completely disable the warnings. Your choice.

Great news!
posted on Tuesday, June 06, 2006 4:54:50 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Tuesday, May 16, 2006
Anyone checked out CodePlex yet?

Looks like a Microsoft site for sharing open source applications, sort of like SourceForge, except a lot more user friendly! Apparently, it is built on Team Foundation Server, too. I just found the 1.0 release of MSBee (target .NET 1.1 with Visual Studio 2005) on there.

Check it out!
posted on Tuesday, May 16, 2006 7:51:53 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Monday, May 15, 2006
If you've ever wondered why the increment and decrement operators weren't included in VB.NET, here's a post explaining why.

Coming from the C/C++ world, I still miss the increment (++) and decrement (--) operators, but I definitely understand why after reading. Basically, it has to do with the fact that assignments in VB are done at the statement level instead of the expression level. If you're not following, consider how you can have things like (if (x = 5) ...) in C, but you can't in VB because the = sign is used for both assignment and equality, depending on the STATEMENT. There isn't any problems in C, because equality is checked with the == sign.

Interesting.
posted on Monday, May 15, 2006 12:54:45 PM (Central Daylight Time, UTC-05:00)  #    Comments [1]
# Thursday, May 11, 2006

Prompted primarily by Karl Sequin's excellent "Understanding and Using Exceptions" post, I was recently attempting to clean up some of the generic exceptions being throw in some code and I was having trouble deciding which exception to use.

I had a BackgroundWorker that could potentially throw an exception (can't everything?) that was doing some remoting to another process. As additional information, the BackgroundWorker exposes any exceptions that might occur in the Error property off of the RunWorkerCompletedEventArgs. I didn't want to just throw e.Error because, as Karl points out, this modifies the call stack making it look my code was the source of the exception. At the same time, I couldn't just use throw, because the exception had basically already been caught and been given to me to handle.

I ended up pulling up the Object Browser in Visual Studio and filtered the list down by searching on "exception" - a nice trick to see all currently accessible exceptions. I ended up using the System.Runtime.Remoting.RemotingException, because it described exactly what I was looking at. Here's the description for it:

Public Class RemotingException

          Inherits System.SystemException

     Member of: System.Runtime.Remoting

Summary:

The exception that is thrown when something has gone wrong during remoting.

If you exclude the "during remoting" part, it basically describes any exception that can be thrown. It's almost funny in a way, because that's exactly the type of thing I was looking for. I was able to set the InnerException to my e.Error which provided me with all the information I needed.

posted on Thursday, May 11, 2006 9:27:20 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Wednesday, May 03, 2006
Thanks to Scott Hanselman for the heads up.

I've been using Consolas for a few months now and it is easily one of the best programming fonts I've ever used... and I've tried an awful lot of them... (see here and here for others).

Once it is loaded, start pimping your IDE.
posted on Wednesday, May 03, 2006 7:42:19 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Wednesday, April 26, 2006
Never heard of PowerShell you say?

I hadn't either, at least until today. That's because it used to be called Monad. Microsoft released the RC1 of PowerShell today and it is pretty sweet. Basically, it offers scripting and CLI access to the .NET Framework. Instead of using cmd.exe, you'll be using PowerShell.exe. I haven't used it much yet, but it is really cool. Just as a quick example, try this out in PowerShell:

$var = "This is a sweet"

Now, type $var. and then hit tab.

OH WOW! Tab completion for System.String from the command line!

Check it out!
posted on Wednesday, April 26, 2006 12:44:27 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Friday, April 14, 2006

Ever seen this error in Visual Studio 2005?

I've seen it all too often and it is really annoying.

However, I did find a possible fix today. I was working in a project that had multiple assembly references. One of the references was using a 1.1 assembly, so it came along for the ride. By simply removing that reference, I was able to view my form without any problems. If I tried to add the reference back, I would get the designer error again. I reworked the assembly being referenced to not use any 1.1 components and... lo and behold... the designer errors stopped.

Is this just a really random bug or is this a subtle way to push people to migrate to .NET 2.0?

posted on Friday, April 14, 2006 3:09:51 PM (Central Daylight Time, UTC-05:00)  #    Comments [3]
I had some code that I was porting from .NET 1.1 to .NET 2.0 today. The code I had was checking the version of comctl32.dll to see if it was version 6 or greater to determine if the application supported visual styles or not. As I didn't write that code, I'm not sure if that is a valid way to check for visual style support in .NET 1.1.

I DO know that in .NET 2.0, that check doesn't necessarily work correctly; however, there is a new way to check that is much easier and more reliable -- Application.RenderWithVisualStyles. If you call Application.EnableVisualStyles in your Sub Main method, this boolean will be set to true. That's all you need to check!

See MSDN documentation here.
posted on Friday, April 14, 2006 11:50:11 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Friday, March 31, 2006

Recently, I was adding the ability to open files from an application at work. Luckily, I had run into this situation before, so I knew that you could run a Process.Start on the file in question and have Explorer open it for you. What I didn't know was that it would throw a Win32Exception if the file didn't have an associated program to open it. My next step was what any good developer would do: Google it.

Fairly early on in my searching, I came across a post by Ned Batchelder that described the EXACT same scenario I was working on! Ned wanted to open a file with an unknown extension from a managed application just like me. He details his Google search and explains how he discovered information about the API functions, ShellExecute and ShellExecuteEx. Basically, you can call ShellExecuteEx with an "open" verb and Explorer will attempt to open the file. If it fails with an SE_ERR_NOASSOC error, then call ShellExecuteEx again but using an "openas" verb. Doesn't sound too bad, though some code snippets still would've sped the process up for me :-) I did learn it better this way, though.

Anyway, here's where I started. First, I pulled in the definition for the SHELLEXECUTEINFO structure.

Friend Structure SHELLEXECUTEINFO
    
Public cbSize As Integer
    Public fMask As SEE_MASK
    
Public hwnd As IntPtr
    <MarshalAs(UnmanagedType.LPTStr)> _
    
Public lpVerb As String
    <MarshalAs(UnmanagedType.LPTStr)> _
    
Public lpFile As String
    <MarshalAs(UnmanagedType.LPTStr)> _
    
Public lpParameters As String
    <MarshalAs(UnmanagedType.LPTStr)> _
    
Public lpDirectory As String
    Dim nShow As Integer
    Dim hInstApp As SE_ERR
    
Dim lpIDList As IntPtr
    <MarshalAs(UnmanagedType.LPTStr)> _
    
Public lpClass As String
    Public hkeyClass As IntPtr
    
Public dwHotKey As Integer
    Public hIcon As IntPtr
    
Public hProcess As IntPtr
End Structure

Next, I created definitions for the SW, SEE_MASK, and SE_ERR constants.

#Region " SW Constants "
    Friend Enum SW As Integer
        HIDE = 0
        SHOWNORMAL = 1
        NORMAL = 1
        SHOWMINIMIZED = 2
        SHOWMAXIMIZED = 3
        MAXIMIZE = 3
        SHOWNOACTIVATE = 4
        SHOW = 5
        MINIMIZE = 6
        SHOWMINNOACTIVE = 7
        SHOWNA = 8
        RESTORE = 9
        SHOWDEFAULT = 10
        FORCEMINIMIZE = 11
        MAX = 11
    End Enum
#End Region

#Region " SEE_MASK Constants "
    Friend Enum SEE_MASK As Integer
        CLASSNAME = &H1
        CLASSKEY = &H3
        IDLIST = &H4
        INVOKEIDLIST = &HC
        ICON = &H10
        HOTKEY = &H20
        NOCLOSEPROCESS = &H40
        CONNECTNETDRV = &H80
        FLAG_DDEWAIT = &H100
        DOENVSUBST = &H200
        FLAG_NO_UI = &H400
        UNICODE = &H4000
        NO_CONSOLE = &H8000
        ASYNCOK = &H100000
        HMONITOR = &H200000
        NOZONECHECKS = &H800000
        NOQUERYCLASSSTORE = &H1000000
        WAITFORINPUTIDLE = &H2000000
        FLAG_LOG_USAGE = &H4000000
    End Enum
#End Region

#Region " SE_ERR Constants "
    Friend Enum SE_ERR As Integer
        SE_ERR_FNF = 2              ' file not found
        SE_ERR_PNF = 3              ' path not found
        SE_ERR_ACCESSDENIED = 5     ' access denied
        SE_ERR_OOM = 8              ' out of memory
        SE_ERR_DLLNOTFOUND = 32
        SE_ERR_SHARE = 26
        SE_ERR_ASSOCINCOMPLETE = 27
        SE_ERR_DDETIMEOUT = 28
        SE_ERR_DDEFAIL = 29
        SE_ERR_DDEBUSY = 30
        SE_ERR_NOASSOC = 31
    End Enum
#End Region

Finally, I created my definition for the ShellExecuteEx function.

<DllImport("shell32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Friend Shared Function ShellExecuteEx( _
        
ByRef lpExecInfo As SHELLEXECUTEINFO) As Boolean
End Function

I stuck all of this into a NativeMethods class and tried the code below:

Dim info As New NativeMethods.SHELLEXECUTEINFO
info.cbSize = Marshal.SizeOf(info)
info.lpDirectory = Path.GetDirectoryName(fileToStart)
info.lpFile = Path.GetFileName(fileToStart)
info.nShow = NativeMethods.SW.SHOWDEFAULT
info.lpVerb =
"open"
info.fMask = NativeMethods.SEE_MASK.FLAG_NO_UI Or NativeMethods.SEE_MASK.FLAG_DDEWAIT

If Not NativeMethods.ShellExecuteEx(info) Then
    If info.hInstApp = NativeMethods.SE_ERR.SE_ERR_NOASSOC Then
        Dim sinfo As New NativeMethods.SHELLEXECUTEINFO
        sinfo.cbSize = Marshal.SizeOf(info)
        sinfo.lpVerb =
"openas"
        sinfo.lpDirectory = Path.GetDirectoryName(fileToStart)
        sinfo.lpFile = Path.GetFileName(fileToStart)
        sinfo.nShow = NativeMethods.SW.SHOWDEFAULT
        NativeMethods.ShellExecuteEx(sinfo)
    
End If
End If

UPDATED (9/12/2006): Many thanks to Michael and his comment regarding using the SEE_MASK.FLAG_DDEWAIT. That fixed all of the problems I was running into regarding the above code. (see the usage on info.fMask)

A quick note about the code: Ned mentioned in his post that he got the ERROR_NO_ASSOCATION error instead of SE_ERR_NOASSOC. Well, the ERROR_NO_ASSOCATION is what is returned in the Win32 error (Marshal.LastWin32Error). The SE_ERR_NOASSOC is returned in the hInstApp (see MSDN documentation here).

See any problems with that? I certainly didn't (and still don't). It works like a charm for files with associations... however, it would only work one time for files without any associated program. Afterwards, it wouldn't give me anything... no errors, nada, zilch. After a few tries, an AccessViolationException would get thrown. Why? I have no idea. I tried various things to see if I should be cleaning up memory somewhere but I couldn't find anything. I did find out that if I just called ShellExecuteEx with the "openas" verb the first time, I wouldn't get any problems at all. What in the world???

As a result of the strange behavior, I changed my code slightly to look like this:

Try
    Using p As New Process
        p.StartInfo.FileName = fileToStart
        p.StartInfo.UseShellExecute =
True
        p.Start()
   
End Using
Catch win32Ex As Win32Exception
   
Dim sinfo As New NativeMethods.SHELLEXECUTEINFO
    sinfo.cbSize = Marshal.SizeOf(sinfo)
    sinfo.lpVerb =
"openas"
    sinfo.lpDirectory = Path.GetDirectoryName(fileToStart)
    sinfo.lpFile = Path.GetFileName(fileToStart)
    sinfo.nShow = NativeMethods.SW.SHOWDEFAULT

   
If Not NativeMethods.ShellExecuteEx(sinfo) Then
        Throw New Win32Exception
   
End If
End Try

The above code is working like a charm. I still have no idea why my first example won't work for me. If anyone has any ideas or suggestions, please let me know. I haven't worked with Interop between managed and unmanaged code very much. My experience up to this point has primarily been an entirely managed project or an entirely unmanaged project (and that only in college).

NOTES: Here are some resources I found while researching this:

[http://www.nedbatchelder.com/blog/20050318T070512.html]
[http://www.pinvoke.net/default.aspx/shell32/ShellExecuteEx.html]
[http://www.pinvoke.net/default.aspx/Constants/SW.html]
[http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/structures/shellexecuteinfo.asp]

Also, be sure to look at the ShellAPI.h header file!

posted on Friday, March 31, 2006 9:08:06 AM (Central Daylight Time, UTC-05:00)  #    Comments [2]
# Friday, March 24, 2006
I've been using the System.Collections.Generic namespace an awful lot lately. I really like it, too. I use the List<T> collection all the time. It is so much better than inheriting from the CollectionBase to get a type-safe collection. I won't go into the reasons here, though. This post is about Predicates. If you have a List<T> collection, you'll notice it exposes a Find method that takes a Predicate as an argument. A Predicate is just a delegate that takes an object of type T and returns a boolean. When you call the Find method, it will call your Predicate for each object in its collection until your Predicate returns true. Looks like a nice, clean way to search collections, right?

Well, if you're using C# anyway.

Compare the following VB.NET code and C# code:

VB.NET :

    1 Module Module1

    2     Sub Main()

    3         Dim tests As New List(Of Test)

    4         tests.Add(New Test("test"))

    5         tests.Add(New Test("test2"))

    6         tests.Add(New Test("test3"))

    7 

    8         toSearchFor = "test2"

    9         Console.WriteLine(tests.Find(AddressOf FindTest).ID)

   10     End Sub

   11 

   12     Private toSearchFor As String = ""

   13     Private Function FindTest(ByVal val As Test) As Boolean

   14         Return val.ID = toSearchFor

   15     End Function

   16 

   17     Private Class Test

   18         Public ID As String

   19         Public Sub New(ByVal id As String)

   20             Me.ID = id

   21         End Sub

   22     End Class

   23 End Module


C# :

    1 using System;

    2 using System.Collections.Generic;

    3 using System.Text;

    4 

    5 namespace CSPredicateExample

    6 {

    7     class Program

    8     {

    9         static void Main(string[] args)

   10         {

   11             List<Test> tests = new List<Test>();

   12             tests.Add(new Test("test"));

   13             tests.Add(new Test("test2"));

   14             tests.Add(new Test("test3"));

   15 

   16             string toSearchFor = "test2";

   17             Console.WriteLine(tests.Find(delegate(Test val) { return val.ID == toSearchFor; }).ID);

   18         }

   19 

   20         class Test

   21         {

   22             public string ID;

   23             public Test(string id)

   24             {

   25                 this.ID = id;

   26             }

   27         }

   28     }

   29 }


I've bolded the important part. In case you missed it, it is the toSearchFor variable. The only way for a predicate to find a value is to compare it to another value; however, there is no way to pass this value to the predicate outside of an external variable. In C#, this isn't a problem because of closures. In C#, the wrapping of the toSearchFor variable so that it is accessible to the inner anonymous delegate is the closure. VB.NET does not have this feature (yet!). Because of this limitation in VB.NET, you have to have a class-level variable or global variable to effectively use predicates so that your predicate has something to compare to! It seems to me that the lack of closures effectively cripples the use of predicates in VB.

Because of features like this, I am really looking forward to the next release of VB. Of course, with LINQ, will I even care about predicates then?

I would be very interested to know if anyone has any other suggestions on ways to effectively use the predicate model in VB.

UPDATE: Wow, go Paul Stovell! Instead of complaining like I did, Paul actually did something to get around this limitation in the current version of VB.NET and created an implementation of "Almost-anonymous" methods! His method also shows how to use the Widening overloaded operator in VB.NET, which I haven't seen much of. Cool!
posted on Friday, March 24, 2006 5:58:16 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Wednesday, March 22, 2006
I've blogged about FileHelpers before. I like it a lot.

Since then, Marcos has added even more great features to it including support for .NET 2.0 Generics and a new Wizard application that really increases the speed in developing new records.

Marcos has an article up on CodeProject as well as a FileHelpers website with examples and a support forum.

Seriously, if you're still using String.Substring calls to parse out flat files, give the library a try.
posted on Wednesday, March 22, 2006 2:02:17 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
At work, we're slowly moving from a classic ASP Intranet environment to a smart client environment. It has been very interesting watching (and being a part of) this movement. The typical intranet application is usually a form that consists of grabbing user input and doing something with it. Validating that user input can be a major headache. Typically, good applications would have both client-side (to improve usability and let users know about invalid data early on) and server-side (to ensure that nothing weird happened and to guarantee that the data is valid).

Where am I going with this? Well, I've seen more and more of my coworkers jumping at the chance to use masked textboxes. And you know why? I think it is because masked textboxes offer "free" validation. If you're unfamiliar with masked textboxes, you provide a mask (i.e. (999) 000-0000 for phone numbers) and the textbox will only accept input that matches the mask. It is basically a guarantee that the data from the textbox will be in the format you specify. If you only want 5 numbers, a dash, and 4 numbers (standard U.S. zip code), that's what you'll get. The problem is that it isn't particularly user friendly. There isn't any notification to the user when they type something invalid that it didn't take their input. It just sits there. It also lets them put their cursor in the middle of the mask, so they can start typing anywhere.

I really think that Jeff Atwood hit the nail on the head when he said that we should "we let the user enter the number however they like, and accept lots of formats" (see his post here). I think that the masked textbox idea could work if the mask it displays were gray and showed the user an example of what the input might look like; however, I don't think it should hinder a user's input. As soon as the user focuses, it could clear so they could type freely. Outlook has a similar feature in the search contact box at the top of the window (see image below).



I'd be curious if anyone has any really successful uses of masked textboxes. And I'm talking about cases where you know the user likes the functionality, not where you like it because it saved you a little bit of validation time :-)
posted on Wednesday, March 22, 2006 9:48:12 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
I remember the first time I ran into an ASP.NET error talking about event validation (specifically while playing with CommunityServer). The solution I discovered at the time was to just disable event validation by setting enableEventValidation to false in the web.config file.

Well, thanks to a couple of posts from K. Scott Allen, I now have a much better understanding of event validation and why it is a really good thing. Check out his posts here and here.

Thanks Scott!
posted on Wednesday, March 22, 2006 8:35:30 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Friday, March 17, 2006
First thing - jfo's coding is a great blog. I regularly find her posts very helpful and relevant to what I'm working on.  If you're not already reading her blog, you should check it out.

Second, as she says, tracepoints ARE awesome. I had used a few of the new breakpoint features in VS2005 such as Condition and Hit Count, but I seen the "When Hit..." option yet. All I can say is, you can say goodbye to Debug.WriteLine'ing (aka "the poor man's debugger"*).

* If you're unfamiliar with "the poor man's debugger," it is basically using output statements to determine values and flow of code. If used correctly, it can actually be very useful. It just isn't fun to remove all of that code after you're done debugging (particularly the Response.Write variety in webpages... ouch).
posted on Friday, March 17, 2006 10:09:17 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Wednesday, March 08, 2006

I've blogged about the FlowLayoutPanel in the past. It is a highly useful control in certain circumstances, but it doesn't behave as expected a lot of the time. In trying to better explain how it works, I created a small test program to show what it is doing. Here is what it looks like:

It primarily demonstrates how FlowDirection and WrapContents affect controls in the FlowLayoutPanel, particularly dynamically added controls. If you click one of the dynamically added buttons, it will pull up that buttons PropertyGrid, which will allow you to edit its properties. This is useful to examine the effects of sizing, anchoring, and docking.

Here's the link to the VS2005 solution if you're interested in playing around with it. It's in C#. I wanted to play around with anonymous delegates :-)

posted on Wednesday, March 08, 2006 8:33:27 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Monday, March 06, 2006
This may not be new for everyone, but I just learned it today. In webpages, to set focus to a control after a page has loaded, you handle the body's onload event and then call the focus method off of the control.

In .NET, there is a focus method off of controls, but it doesn't work if the control isn't visible... i.e. in the constructor or in the Load event. To get around this, use the ActiveControl property off of the Form or UserControl, like so:

  105 Me.ActiveControl = Me.txtTo

Not too bad, eh? In this example, Me.txtTo will have focus when the Form or UserControl is displayed. Just make sure it is in the Load event. It didn't seem to work for me in the constructor (even after the InitializeComponent call). Of course, I only tried it once...

(Google'd and found via here)
posted on Monday, March 06, 2006 4:49:13 PM (Central Standard Time, UTC-06:00)  #    Comments [0]

Lately, I've been doing some work with integrating some of my managed applications with Outlook. There are a lot of code examples and articles out there on using the Outlook COM interop library for tying into Outlook, but be prepared for a lot of security prompts for the user. I understand the reasoning behind those security prompts, but man are they annoying.

You basically have two options at this point if you don't like the prompts. Extended MAPI or Outlook Redemption. Seriously, those seem to be the only two options available, unless your application is actually an add-in using VSTO. Extended MAPI is essentially the low-level side of Outlook. To program against it, you're looking at using C/C++ or Delphi, because your only interface is header files. I took a look at it and it is HAIRY. If you are interested in that option, though, check out MAPIEx at the Code Project. It has some great examples of using Extended MAPI and also showed me enough to scare me away from this option. I would love to spend my company's time and resources learning this and code in C++, but I don't think they would appreciate that very much.

Okay, next. Outlook Redemption. It is a COM wrapper around the Extended MAPI interface that works great. Dmitry Streblechenko created a lot of safe objects around their Extended MAPI counterparts. You code against the Outlook Interop library (add a COM reference to "Microsoft Outlook 11.0 Object Library") and tie that in with Redemption. Everyone uses this thing. Just about every newsgroup post, website, etc. that mentions tying into Outlook recommends this library. I guess this is another recommendation.

My only real complaint with Redemption had to be the stupid Fields collection off of just about every Redemption object. For example, let's look at the Redemption.AddressEntry. It exposes a name, address, and a few other handy properties, but that is about it. If you want to get anything else, you have to use the Fields collection, which takes an Integer and returns an Object. The Fields collection could be compared to a Dictionary object in the .NET Framework. The name is a unique integer that is a lookup to a value. A little annoying but hey, if we have constants, who cares right? Right??? ... What do you mean we don't have any constants? Ohhh, we have to find those out for ourself or buy Outlook Spy! I hate magic numbers!

I was fairly confident that the lookup constants were defined somewhere so I began hunting them down and discovered the MAPITags.h file (mine was at C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\Include). All of the constants use a macro called PROP_TAGS (see MAPIDefS.h) that takes a ULong propID and a ULong propType. Internally, Outlook uses a multitude of different property types like PT_NULL, PT_LONG, PT_BOOLEAN, etc. The PROP_TAG macro takes the type and a unique lookup. That's why the Fields dictionary returns an Object: it might be a long or a boolean or a string or an internal Outlook structure. I ended up writing a console application that read in a header file and spit out a list of VB constants. The regular expression I used was "\#define\s+?(?<name>[\w|\d]+?)\s+PROP_TAG\(\s?(?<type>[\w\d]+?),\s?(?<id>[\w\d]+?)\)".

Anyway, long story short, I'm working with Outlook now and it is really cool. I'm able to, based on a name and my generated VB constants, lookup a property of a contact in my address book. Another programmer and I have been spamming each other testing with meeting appointments and emails ever since. Fun, eh?

posted on Monday, March 06, 2006 8:08:35 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Thursday, March 02, 2006
Thanks to a post from Jeff Atwood, I discovered the blog of Francesco Belana. He's the author of some great books including Programming Visual Basic.NET, which my company has been using to get our developers up to speed on .NET.

I'd like to point out a couple of posts of his that give great examples of using generics in .NET 2.0.

Check them out:
posted on Thursday, March 02, 2006 8:04:15 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Wednesday, March 01, 2006
Roy Osherove posts today about different ways to accomplish thread-safe GUIs using .NET 2.0... and C#.

Since we're primarily using VB.NET at work, we don't get the anonymous delegate love... oh well. Ever since I discovered that JavaScript could do the same thing*, I've been wanting to use it in managed code as well. I guess I'll have to do it on my own time for now.

* like so:  document.body.onload = function () { alert("I've been loaded!") }
posted on Wednesday, March 01, 2006 7:46:28 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Friday, February 24, 2006
Larry O'Brien talks about the myth of better programming languages and how "there is not a shared psychology of computer programming." Seriously, it really does have to do with how you think about things. I work with people who can type all day and then compile and run their program without any errors... in COBOL. Does that mean that it is a better programming language? Maybe for them. Most definitely not for me.

As a side note, Kona and the Big Island of Hawaii rule.

(found via the Daily Grind)
posted on Friday, February 24, 2006 7:46:19 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
If you've never seen some of the posts from Kevin Moore regarding WPF (commonly pronounced Avalon), you should definitely check them out. In particular, some of the things you can do with ListViews and XAML are incredible! He points to this post to show some of the XAML that is required and, really, it doesn't look that bad. To get something like that out of the built-in ListView in .NET 1.1 or .NET 2.0, you would have to do some owner-drawn madness... or do the entire thing yourself.

I don't know about you, but I'm looking forward to WPF!
posted on Friday, February 24, 2006 7:26:44 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Saturday, February 18, 2006

I'd like to talk a little bit about what I did to get my personal site up and running.

First off, I wanted it to support blogging for my wife and I. I tried a lot of different ASP.NET blogging engines like CommunityServer and SUB (Single User Blog). CommunityServer is great, but it had way too much for my needs. I really liked SUB, particularly version 2 because it was in ASP.NET 2.0 and Master pages rule. My only problems with it were probably more my fault, but I had some weird issues with the ASP.NET Development Server (aka Cassini). Something about files existing in two different places. I imagine if I had installed the Web Application Project things might have worked better. Still, I would suggest checking out SUB if you can.

I ended up going with dasBlog. I was already somewhat familiar with it and it is extremely easy to set up. It allows multiple logins by adding multiple users to the siteConfig.config file. My only obstacle was encorporating my own pages (Photos) and creating my own theme. I'd like to say thanks to James Snape for the Project84 theme (the default here), because I based my new theme off of it. If you're going to create your own dasBlog theme, I recommend starting with one you already like. Copy it to a new directory under the themes folder and then started changing things. See what happens. That's really all I did. Since dasBlog is written under ASP.NET 1.1, we can't use Master pages, but we get something pretty close. dasBlog uses template files that are very easy to change and that give you almost complete control over the way your blog will look. If you're interested in using my theme, let me know and I'll zip it up and post it.

The other primary addition to the standard dasBlog setup is that I added a Photos page written in ASP.NET 2.0. It is proof that you can run ASP.NET 1.1 and 2.0 side by side for relatively simple applications. My photos page relies primarily on Picasa, which is a great photo album application. I'm relying primarily on the "Make a webpage..." ability, which will export a selected album into a directory with appropriately sized images, thumbnails, and an index file. The best part is that you can choose to export to an XML file. The XML file is very simple, but it provides a simple way to provide image galleries in a format other than the Picasa defaults. My page basically has a Galleries subdirectory with exported albums. It grabs all of the albums in the gallery and parses the XML file to display the images. All my wife has to do to add albums is export from Picasa and drop the folder into the Galleries directory. How easy is that?

I'll be the first one to admit that there are issues with my Photos page (the exported albums' name are exactly the safest for the web), but it works. At some point, I'd like to clean up the names and add the ability to display our comments as well as to take comments from visitors to the site.

That pretty much sums up what I've done with the site. If you'd like to know more, let me know!

posted on Saturday, February 18, 2006 8:24:05 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Wednesday, February 15, 2006

Let's say you have the following class:

   51 Public Class Person

   52     Private _name As String

   53 

   54     Public Event NameChanged As EventHandler

   55 

   56     Public Property Name() As String

   57         Get

   58             Return _name

   59         End Get

   60         Set(ByVal value As String)

   61             _name = value

   62             OnNameChanged(EventArgs.Empty)

   63         End Set

   64     End Property

   65 

   66     Protected Sub OnNameChanged(ByValAs EventArgs)

   67         RaiseEvent NameChanged(Me, e)

   68     End Sub

   69 End Class

We've set up the [Property]Changed events so that DataBinding will work correctly. Now, let's assume you want to bind the name property over to the text property of your TextBox control. We'll go the simple data binding route here for simplicity.

    3 Public Class Form1

    4     Private txtName As New TextBox

    5     Private _person As New Person

    6 

    7     Public Sub New()

    8         ' This call is required by the Windows Form Designer.

    9         InitializeComponent()

   10 

   11         ' Add any initialization after the InitializeComponent() call.

   12         Me.Controls.Add(txtName)

   13 

   14         _person.Name = "cool"

   15         txtName.DataBindings.Add("Text", _person, "Name")

   16     End Sub

   17 

   18     Private Sub Form_Click(ByVal sender As ObjectByValAs EventArgs) _

   19         Handles Me.Click

   20         _person.Name = "clicked"

   21     End Sub

   22 End Class

There! Now the txtName will display "clicked" whenever you click on the form. Magic! Now, let's change that Click event like so to see what happens:

   18     Private Sub Form_Click(ByVal sender As ObjectByValAs EventArgs) _

   19         Handles Me.Click

   20 

   21         Dim newPerson As New Person

   22         newPerson.Name = "new person"

   23         _person = newPerson

   24     End Sub

Why would I ever want to do is this way? Well, let's say you're remoting somewhere to get your data and your background thread returns a fully populated object. The easiest thing to do is to just point to the new object... except that it doesn't work.

All we did was change our instance over, but the textbox never changed. Why not? Because of REFERENCES, POINTERS, and MEMORY ADDRESSES! That's why! Check this out:

   18     Private Sub Form_Click(ByVal sender As ObjectByValAs EventArgs) _

   19         Handles Me.Click

   20 

   21         Dim newPerson As New Person

   22         newPerson.Name = "new person"

   23 

   24         Debug.WriteLine("Are references equal? "Object.ReferenceEquals(txtName.DataBindings("Text").DataSource, _person))

   25         _person = newPerson

   26         Debug.WriteLine("Are references equal? "Object.ReferenceEquals(txtName.DataBindings("Text").DataSource, _person))

   27     End Sub

Whoa! The first Debug.Writeline will give you TRUE, but the second will give you FALSE. You see, understanding how references and pointers work is important. The textbox's DataSource is holding onto a reference of the old Person instance. You now have two different instances in memory, whether you like it or not.

What do you do about it? Well, as far as I can tell, you can either update your DataSource reference (it did change after all) or you can move your properties over manually so that your references don't change. I'm open to suggestions on other methods here.

posted on Wednesday, February 15, 2006 1:05:04 PM (Central Standard Time, UTC-06:00)  #    Comments [0]

For those two or three who missed it, Yahoo! released two libraries yesterday: the Yahoo! Design Patterns Library and the Yahoo! User Interface Library. I particularly like the UI library. First of all, it was released under as open source, so as long as you include the copyright at the top, it looks like you can use it. I checked out their JavaScript code and it looks pretty good. It seems that the whole object { name : value }* notation of declaring objects is becoming more popular. It is also becoming much more common to see entire frameworks being developed (I'm thinking of the JavaScript libraries that come with Atlas). Anyway, interesting stuff. It will be a lot easier to add some nice, production quality JavaScript to pages now.

* Instead of:

var newObject = new function () {
   this.name = value;
}

It is:

var newObject = {
   name: value;
}

posted on Wednesday, February 15, 2006 7:53:14 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Friday, February 03, 2006

Check this out.

For those who are unfamiliar, Lisp is a functional language often associated with AI programming. I took an AI class in college and Lisp was the primary language used to explain the AI concepts. It is very cryptic to look at if you haven't ever used it, because it makes heavy use of parentheses. It also makes a lot of use of recursion. If I remember correctly, it doesn't actually have any looping structure (i.e. while, for, etc.) other than making use of recursion. It can really help with looking at common programming problems in a different way.

CORRECTION: After looking over the book just a little bit, it appears that Lisp DOES have loop operators in addition to recursion. I wonder if it was one of those academic things, sort of like how they don't tell you about the STL until you've made it through the data structures class and coded your own linked list, binary search tree, and graph. Oh well.

posted on Friday, February 03, 2006 4:04:14 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Sunday, January 29, 2006

I just finished reading an article from Hacknot that describes the predicament that developers are in while attempting to define a software product's requirements as specified by the user. Here is a quote from the article that I find quite telling:

In their efforts to be "user focused", guided by simplistic notions of "usability", many managers and programmers uncritically accept whatever users tell them as a mandate. "The customer is always right" makes a nice slogan but a poor substitute for critical thought. If you want to deliver a product that is genuinely useful, it is important to moderate the user feedback you receive with your own knowledge of usability principles, and to seek independent confirmation of the information they relate. For it is a fact seldom acknowledged in the text books that users are frequently uninformed, mistaken or deliberately deceptive.

I work in an organization which is highly user focused, as opposed to product focused. Essentially, whatever the customer says goes.

Here is a little background: My employer has been relatively slow in adopting new technologies. A large portion of the software that runs is what might be called "legacy" code (i.e. COBOL, JCL, and even Assembly); however, there is still new development being written in that environment. Thankfully, much of the front-end has been moved to an intranet base. Quite recently, there has even been a push to Windows Forms development with .NET.

The problems that the users have is that they do their business work in three different environments at a bare minimum: green screens, intranet webpages, and Windows applications. When my company first began the move to intranet pages, the user requirements would basically be, "make it look like what we have." They had no idea of what the capabilities were with webpages. The first few webpages all looked just like their green screen counterparts, except that they were black text on a white background, instead of green text on a black background.

Today, with some of our new development in .NET, we're running into the same problem again. The users know webpages and their capabilities, but not those of Windows applications. There is a fundamental misunderstanding about what these new applications are. They want a button for everything, when a toolbar or menustrip might be more appropriate. I've really been encouraging my users to look at examples like Office applications for ideas while thinking about what they want the new software to do. Some might argue that Office applications aren't the best example, but the truth is that Office is one application that the users really know.

As software developers, I really think that, to be user focused, you can't always give the user exactly what they asked for. Alternatives can, and often are, much better in the end. The difficult part is communicating that. Is this a common scenario for others? (I know it is!)

posted on Sunday, January 29, 2006 7:53:16 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Thursday, January 26, 2006

Check this out.

"The A to Z of Programmer Predilictions" is a funny little article that categorizes programmers into various stereotypes, most of which are surprisingly accurate. As I read through the descriptions, I started spotting people in my organization. Though I (and everyone else) can probably fit into a variety of different personas described there, I probably am most like "Zealous Zack." I DO download all of the betas (even at work!) and, when someone blogs about the "Next New Thing," I've got the download started before I've finished reading the post about it.

Speaking of, I need to download the newest WinFX bits...

(via Digg)

posted on Thursday, January 26, 2006 7:41:44 AM (Central Standard Time, UTC-06:00)  #    Comments [0]