Saving All Attachments in Outlook

Back on January 3’rd, 2007 ( or I posted a useful macro that would save attachments on the selected items in a folder. Since then several have written asking for a version that would save all attachments for every item in a folder, whether it was selected or not.

UPDATE: Some users were having problems downloading the code, so I’ve posted it at:

I finally had a chance to experiment, and it turned out to be very easy. To create a version that saves attachments for all items, you only have to change three lines of code.

The first line is the name of the sub. I changed

Public Sub SaveAttachments()


Public Sub SaveAllAttachments()

Easy enough. Next, the variable declaration of

Dim Sel As Outlook.Selection

Has to be changed to

Dim Sel As Outlook.Items

The final change is to

Set Sel = Exp.Selection

It becomes

Set Sel = Exp.CurrentFolder.Items

And that’s it, it works. Let me explain what’s happening. In the original, I was cycling through the Selection collection of the Outlook Explorer object. The Selection is a special type of Items collection that holds what’s selected.

For our new macro we wanted all of the items in the current folder, not just what was selected. The first thing we had to do, after changing the sub’s name, was to change the data type of the Sel variable. I wanted to get away from the specific selection collection to the more generic items collection.

Then, all I had to do was have the Sel point to the Items collection of the current folder. Since both Selection and CurrentFolder.Items both support the Items interface, everything else just worked. That’s the power of OOP!

I’ve uploaded a new version of the file as Save All Attachments. It contains this version, the original SaveAttachements, and the GetOutputDirectory function. If you are installing this new, please don’t forget to set a reference to the Microsoft Scripting Runtime Library (scrrun.dll).

Select Tool, References from the VB Macros Editor. Scroll down until you find Microsoft Scripting Runtime, and check it. You’ll know it’s the right one when the file name is scrrun.dll.

[VB References Dialog]

I’ve tested this with messages stored in a variety of folders, including the Inbox. It’s based off the current folder, so it doesn’t seem to care where you are at. I’ve also gotten this to work with the calendar as well.

There you go, you now have a choice. Using my original macro you can save attachments for only the selected items in the current folder, or using this version you can save all attachments for all items in the current folder. I hope the folks who requested the change will find this fits their needs, enjoy!


What to do with Ubuntu

OK, you’ve now installed Ubuntu under Virtual PC or on your spare machine, or perhaps as your main computer. If you are a “newbie” to Ubuntu, as am I, you might want some suggestions on things you can do with your spiffy new OS. Never fear, I have scoured the web and found some sites and other blogs with some good suggestions.

Linux on Desktop: 13 Things to do immediately after installing Ubuntu. or

Has some really useful suggestions on some basic things you will want to do to make you Ubuntu experience more enjoyable.

Ten Tips for New Ubuntu Users

Just as it says, some useful tips for those new to Ubuntu.

Check out the Ubuntu Forums

Lots of good info and a good community to ask questions and learn more.


A great podcast on Linux. Chess Griffin does a really good job with lots of info, including (search the archives) a three part introduction to Ubuntu.


If you are here, most likely you have some interest in .Net development. Mono is the open source project to allow you to do .Net development on the Linux platform. Check out the Mono pages for more info on .Net programming in Ubuntu.

Installing Ubuntu 6.10 on Virtual PC 2007 Step by Step

Update April 24, 2008 – The newest version of Ubuntu, 8.04 is out. Look for complete install instructions here.

Update: October 18, 2007 – Ubuntu 7.10 is now out, for full instructions on installing it, see

Note: If you are looking for instructions for version 6.06, see my post at: There are still good reasons to install 6.06, mostly because it’s the version targeted as the LS, or Longterm Support version. Many companies will likely stick with 6.06 for some time. For the past few weeks I’ve been trying to install Ubuntu 6.10 under VPC 2007, using the standard install model. I’ve come to an important conclusion. It can’t be done. (If you’ve figured out how, leave a comment cluing the rest of us in on it!)

Now, before you become distraught and start with the wailing and gnashing of teeth, note I said “standard install model”. There is a way to get it working.

Before you get started, spend a few minutes getting familiar with VirtualPC if you have not already done so. You can find my step by step instructions for VirtualPC at Keep it handy, at various points I will be referring to it. OK, let’s get started.

First, you need the right installer. Go to the Ubuntu website ( Under desktop, click the Download link. Scroll down to the Ubuntu 6.10 area. Click on the region you live in, and find a mirror close to your location. Now, here is the inside trick, instead of “CD Image for desktop and laptop PC’s”, you should instead select “Other installation options”.

When the next screen comes up, scroll down to the “Alternate install CD” area. Find the link that says “PC (Intel x86) alternate install CD” and download the ISO it’s associated with. It’s a big download, so be patient.

[Ubuntu 6.10 Step by Step]

UPDATE! UPDATE! Ubuntu has changed their site, and so far I haven’t been able to find the alternate cd via their site. For now you can go to and grab the file ubuntu-6.10-alternate-i386.iso. This is the same file I was describing. We now return you to your regularly scheduled blog post…

Note that selecting the right version is the first thing you have to know, but there’s a few other tweaks you’ll have to do during the install process, so keep reading.

Once you have it downloaded, burn it to a CD or use Virtual CDRom Control Panel (see my post to load it into a drive.

In Step 1 of my VirtualPC Step by Step you are instructed to create a new machine, please do so. I’ve named mine “Ubuntu 6.10”. In step 2, you are prompted for your OS. You will need to pick Other. In step 3, you are asked about Ram. Ubuntu will run OK under 256 megs, however if you have the available space I’d highly suggest upping it to 512, especially if you intend to get into doing some graphics or mono coding. I’ve selected 512 meg for this tutorial.In step 4 you will want to create a new hard disk, and in step 5 confirm what you’ve selected. OK, now you are up to step 6, installing the OS, which is where this tutorial picks up.Your first screen comes up, but before you start pressing buttons there’s one tweak you have to make. So you can see everything correctly during the install, press the F4 (VGA) button. Select a video mode that ends with 16, in my example you can see I changed to 800 x 600 x 16.
[Ubuntu 6.10 Step by Step]
Now you can proceed, press enter to start the “Install in text mode” option.

The first screen to come up asks about your language. I took the default of English, but if you are elsewhere please select your language, then press Enter to continue.
[Ubuntu 6.10 Step by Step]

Next you are asked for your location. Select your location, or the one closest to you, and press Enter.
[Ubuntu 6.10 Step by Step]

Next you are asked to let the installer determine your keyboard. Take the default, Yes, which will take you to the next screen.[Ubuntu 6.10 Step by Step]

You will then be asked to press a series of keys. Here’s the first screen in the series:
[Ubuntu 6.10 Step by Step]On some screens there may be keys you don’t have, if so just wait for the time out.

After going through each screen, you will see what keyboard pattern Ubuntu detected for you. If it’s correct just click Enter to continue, if not you can go back and reselect.
[Ubuntu 6.10 Step by Step]

Next Ubuntu will scan for your CD rom, then begin loading components. Just kick back and wait, it will go through all sorts of detection steps as it finds hardware, networking, and more.
[Ubuntu 6.10 Step by Step]

If all went well, you will now be asked for a host name. I took the default of Ubuntu, but you are free to change it. Enter your host name, or just hit Enter to continue.
[Ubuntu 6.10 Step by Step]

Next Ubuntu will begin detecting your disks and hardware. Be patient. You will then be asked about partitioning disks. This should be a new partition, so take the default by pressing Enter to continue.
[Ubuntu 6.10 Step by Step]

The next screen is the first place you don’t want to take the default. It’s asking you to confirm the partition format plan. Use your left arrow to move the red bar (shown below on No) over to the Yes side, then you can press enter.
[Ubuntu 6.10 Step by Step]
Wait while Ubuntu formats your drives.

Next you are asked for your time zone. Select it, then press Enter.
[Ubuntu 6.10 Step by Step]

Next you are asked if the system clock is set to UTC. I just took the default of Yes, this is easy enough to fix if it’s wrong.[Ubuntu 6.10 Step by Step]

Next you are asked for your name. Note this is not your login user name, but your real name. Ubuntu will use this in your documents and e-mails. I entered a name, and pressed enter to continue.
[Ubuntu 6.10 Step by Step]

On the next screen you are prompted for the user name you want. This is what you will enter when you login. Enter something that suits you, then press enter to continue.
[Ubuntu 6.10 Step by Step]

If you’ve done this sort of thing before, you’d probably guess Ubuntu wants your password next, and you’d be right. Enter a password and press enter to continue.
[Ubuntu 6.10 Step by Step]

Now you are asked to re-enter the password, to confirm. Do so and press enter to go on.
[Ubuntu 6.10 Step by Step]

Now sit back and wait. Ubuntu will start installing itself.
[Ubuntu 6.10 Step by Step]

After running for a while, you are next asked about video modes. Use the space bar to toggle the modes you want, and use the arrows to move up and down. When you’ve selected the modes you want, press enter to continue. Below you can see I’ve selected a few common modes for my system.[Ubuntu 6.10 Step by Step]

OK, sit back and wait some more, while Ubuntu installs various software packages. This step takes a loooooooooong time.[Ubuntu 6.10 Step by Step]

Ubuntu has completed it’s install. But don’t hit enter quite yet! First, on the Virtual PC menu pick CD, Release Physical Drive Z: (where z is the drive you are installing Ubuntu from). This will let Ubuntu to boot from your newly installed virtual hard drive instead of the CD. After you’ve released the drive, you can hit Enter to continue.
[Ubuntu 6.10 Step by Step]
When the system reboots, you will see your login screen, but it’s going to look very trashy. Don’t worry, we’ll fix in a moment.

Key in your user name, and press Enter. You probably won’t be able to read what you are typing so be careful.[Ubuntu 6.10 Step by Step]

If all went well, you’ll now see another garbled screen where you enter your password. Carefully, do so and press enter.[Ubuntu 6.10 Step by Step]

More garbled screens will appear. When it appears as if Ubuntu has loaded (see below, if you look close you can make out the menu across the top), press the CTRL+ALT+F1 key combo.
[Ubuntu 6.10 Step by Step]

This key combo exists the graphic interface and puts Ubuntu in text mode. Key in your user ID, then (when prompted) password to login.[Ubuntu 6.10 Step by Step]

You’ll now see a command line, below.
[Ubuntu 6.10 Step by Step]We need to modify your xorg.conf file to change the color depth. First, let’s back it up. Type in this command:sudo cp /etc/X11/xorg.conf /etc/X11/xorg.conf.backupNote to copy it exactly, Linux is case sensitive, so if you were to type in say x11 instead of X11 your command will fail. Also, because you are attempting to run the command as the root user (the sudo part of the command) you will be prompted for your password.

Now that we’ve backed it up, we need to edit it. Type in this command:sudo nano /etc/X11/xorg.confYour new screen should look like this:[Ubuntu 6.10 Step by Step]

Press CTRL+W (Where is) and when prompted key in DefaultDepth and press enter.You should now be landed on DefaultDepth. Cursor over to the 24…
[Ubuntu 6.10 Step by Step]

And hit delete twice, then type in 16.
[Ubuntu 6.10 Step by Step]Now hit CTRL+O (WriteOut) to save the file, and press enter to take the default xorg.conf file name. Then hit CTRL+X to exit.

You’re now back at the command prompt. Just type in this command:sudo reboot
and press enter.
[Ubuntu 6.10 Step by Step]

Give it several minutes to shut down and restart. If everything worked, you should now see a beautiful, non garbled Ubuntu screen.[Ubuntu 6.10 Step by Step]

Key in your user name and password and you will be logged in to your working copy of Ubuntu 6.10 on Virtual PC 2007![Ubuntu 6.10 Step by Step]

Virtual PC 2007 Released

Not sure when they slipped this in, but Microsoft has now release Virtual PC 2007. Like it’s predecessor, 2004, it’s still free.

Learn more at or

or go directly to the download at

I’ll keep you updated as to my experiences, please feel free to leave a comment with yours…

Arcane Review: Why Software Sucks

I promised myself I wasn’t going to have a blog filled with a lot of book reviews. But having just finished “Why Software Sucks” by David S. Platt ( or, I find I can’t resist mentioning it.

David S. Platt is a software developer, author, and teacher at Harvard University Extension. However this book is not targeted at the experienced software developer, but instead at the average computer user. He gives the reader a basic knowledge of how software works, so they will know what is possible and what is not. Armed with knowledge about the possibilities of software development, the average joe can then determine when software sucks as opposed to just bumping into current limitations.

One reviewer on Amazon said he “…didn’t find anything new in the book for seasoned UI developers.” That’s a shame, as it shows he clearly didn’t get the point of the book. This book is not targeted at developers. It’s for users, so they will know when you’ve written good software, and when you’re handing them crap.

While it’s true this book is not packed with development techniques, it’s still an important read for any programmer. As a developer with over twenty years experience, what Mr. Platt’s book gave me was insight. To be reminded that the code I write is to be used by people other than developers. He helped me to see my application through the eyes of an average user, or to quote Mr. Platt, “Your users are not you!”

This was not a thick or expensive book, and was filled with enough humor to keep it a quick yet enjoyable read. At the same time it was serious enough to deal with the subject of user interfaces in a meaningful way. After reading this book, I think the best compliment someone will be able to give me about my applications is “it just works!”

For more information see the authors site at

Standard disclaimer, I make no money from book sales, nor have I any financial affiliation with Amazon, the author, David S. Platt, the publisher, the guys who grew the trees that got turned into paper the book was printed on, the truck drivers that delivered the books, the company that hosts the authors website, nor am I the father of Anna Nicole Smith’s baby. Just so that’s all clear.


[Why Software Sucks Book Cover]


Today’s alphabet soup has to deal with an issue we struggled over this week at work. For those unfamiliar, SSIS is SQL Server 2005 Integration Services. It’s the rewrite of SQL Server 2000 DTS (Data Transformation Services). You use SSIS to pull data from one database and put it into another.

You develop SSIS in BIDS, Business Intelligence Developers Studio. BIDS is Visual Studio with the BI tools added in. The issue we’ve been fighting had to do with getting our SSIS packages to use Oracle 10g drivers to talk to the Oracle 9i data source that was the beginning point for our packages.

Over and over we got an error that the OLEDB provider could not “Acquire” the database, yet the data source kept passing the “Test Connection” test. It was one of my associates who came upon the clue.

In our environment, we don’t normally use a TNSNAMES.ORA file. TNSNAMES is where Oracle normally stores information about a schema name. Schema names are kind of like URLs. You use a human readable schema name, something like WAREHOUSE1. Oracle driver then goes into TNSNAMES to find the server information so it knows where to route the data to.

As I said, in our environment we don’t use TNSNAMES, instead we have another file. The data driver looks there to get the server that TNS info is stored at for the whole company. This allows us to have a single place to store (and update) TNS data instead of thousands of workstations.

The problem was, BIDS didn’t like that. Even though we had it redirected, BIDS didn’t recognize that and kept going to the TNSNAMES file to find schema info, and in our case it couldn’t find it because it wasn’t there. Once we added a TNSNAMES file BIDS was able to acquire it’s schema info, connect to the database and get whatever data it needed.

The moral of the story is, if you are having problems in BIDS connecting to an Oracle data source verify that you do indeed have a valid TNSNAMES.ORA file.

Collections in C# – The Stack

Yesterday we looked at the Queue class. The queue is used when you need a first in, first out (FIFO) way to read through your collection. Sometimes though you need to read so that the first item you retrieve is the most recently added item, much like the computer’s stack, or a Pez candy dispenser (

With the stack class, the most recently added item is the first one you pull out. Stacks have a count property and peek method, much like it’s cousin the queue. However, the stack uses push and pop to get items on and off the stack. Let’s take a look.  

      Stack myStack = new Stack();

      myStack.Push(“1. Carl Franklin”);

      myStack.Push(“2. Richard Campbell”);

      myStack.Push(“3. Mark Miller”);

      myStack.Push(“4. Kimberly Tripp”);

      myStack.Push(“5. Billy Hollis”);


      while (myStack.Count > 0)






[Picture of Stack Output Example 1]


As you can see, the pop operation removed the items from the collection in the reverse order from which they were loaded. In other words, the last item on is the first one you’ll be pulling off.

The peek method works just like it does with the queue. Modifying the while loop above thusly:  

      while (myStack.Count > 0)


        Console.WriteLine(“Peek: “ + myStack.Peek());

        Console.WriteLine(“Pop : “ + myStack.Pop());



Produces this output:


[Picture of Stack Output Example 1]


Stacks are handy when you want to keep track of objects that need to be handled in the reverse order, say for creating and disposing. Like queues, stacks enforce reading your data in a specific order. Whenever you have a requirement to read in a LIFO order, the stack class will add the extra safety you need to make your applications work as you designed.

Collections in C# – The Queue

Most .Net developers are familiar with the ArrayList collection. The ArrayList has become a stable in most .Net applications, replacing in most cases the array. But did you know there are other types of collections?

This will begin a series discussing some of the other types of collections available in C#, and how to use them. Most are pretty straight forward, it’s just a matter of getting to know them. We’ll start things off with the queue.

A queue is a type of first in – first out, or FIFO collection. Unlike an array list, you must read things in order. Queues are very structured, you can’t go sifting or randomly plucking data out of the middle of the collection. OK, I can see you out there, scratching your head and asking “well why would I want to use a queue if it’s not as flexible as an arraylist?”

In a way you’ve answered your own question. Because queues are very structured, you can ensure that your application (or consumers of your application) can’t violate your intent.

Queue’s are simple, they have a grand total of three methods and one property. The property, Count, is almost self explanatory. It tells you how many items are in the Queue.

To get data into the queue, use the Enqueue method. Using the Dequeue method will return the next item, removing it from the collection. What if you want to see what the next item is, but don’t want to remove it? You can use the final method, Peek. Let’s take a look at a sample, done as a Console application.  

      Queue myQueue = new Queue();

      myQueue.Enqueue(“1. Carl Franklin”);

      myQueue.Enqueue(“2. Richard Campbell”);

      myQueue.Enqueue(“3. Mark Miller”);

      myQueue.Enqueue(“4. Kimberly Tripp”);

      myQueue.Enqueue(“5. Billy Hollis”);


      Console.WriteLine(“Count = “ + myQueue.Count.ToString());

      while (myQueue.Count > 0)




      Console.WriteLine(“Count = “ + myQueue.Count.ToString());




This routine prints the following output to the command window:

[Pic of Queue Output Example 1]


As you can see, the Dequeue method returned the items in the same order they were loaded in. There’s really not much to explain, you load objects into the queue using Enqueue (in this case strings), and remove objects using Dequeue.

I also mentioned a Peek method. This allows you to look at the next item without removing it. Here I’ve modified the while loop to first show the next item on the queue using peek, then actually remove it.


      while (myQueue.Count > 0)


        Console.WriteLine(“The next DNR person is:” + myQueue.Peek());

        Console.WriteLine(“Dequeuing them……..:” + myQueue.Dequeue());



[Pic of Queue Output Example 2]


There are several instances where you may want to use a queue over an array list. Perhaps you are processing messages, or are reading through a list where it’s important you read them in order, say a list of transactions from a database. Data that needs to be processed chronologically could be placed on a queue.

Any time you have data that must be processed in the order in which it was loaded, use a queue. The rigidity of the queue will add an extra layer of safety to your application, ensuring data is read in the order in which you intended.

Arcane Thoughts: Designing for Use

Last week I traveled on business, and the hotel I stayed in had some interesting features that got me to pondering the dilemma of design versus usability. In the bathroom the sink looked like a piece of furniture. Four wooden legs held up a black marble table, atop of which was a large white bowl which was in fact the sink.

Visually, this was quite pleasing, the colors worked well, the contours were pleasing to my eye. The issue came when I tried to actually use the area. There was virtually no counter top area to work with. I had a very tiny space to put my contact lens stuff and my shaving kit. Further, there was no place to sit the hand towel while I was scraping my whiskers or putting my eyeballs in. This was a classic case where the builder went with a design that was visually pleasing over one that was usable.

Another conflict I found was the frosted glass that divided the bathroom from the bedroom. Where the frosted glass pane was located, if someone got up during the night to, well you know, and turned on the light, the light would hit right in the face of the person remaining in the bed. (Since I was alone it was a non issue, but if I’d been with my wife it could have been a problem.) In this case it was something with a design that looked good having negative side effects when put into use.

Lest you think I’m all whiny, there were some good points to the place, such as the closet. When I opened the closet door, the light came on. Didn’t have to think about it, didn’t have to fumble for a switch, it just worked. Simple yet very effective and pleasing.

My point on this post is not to complain about hotel rooms but to get you to think about design versus usability when it comes to your applications. How many websites have you been to that were confusing or hard to use, but visually stunning.

A good example of a bad example is Brown University. ( If you try to put your mouse over a menu item in an area that is collapsed, that area pops up to show a pretty picture. You then have to slide your mouse up to be able to click on the item you were just hovering on a second ago, before the page helpfully slid the menu up to show you a pretty picture you probably don’t care about. Visually, the effect is cool and the page looks nice, but if you are trying to actually click on a menu option it sucks.

On the other hand, let me mention my favorite site, Google ( Yes, I said Google. It’s simple, not too much being thrown at you, and it’s obvious what I’m supposed to do (type something in and click Search). Like the light in my hotel room’s closet, it just works.

Windows Presentation Foundation (WPF) included in the new .Net 3.0 Framework gives us some powerful new tools for designing beautiful applications. Like all new technologies, this can be a double edged sword. I hope this post gets you to spend some time thinking about the user experience. Be sure the pretty pictures and cool effects don’t actually get in the way of getting the job done. Spend some time actually using your app. Key in data, do searches, etc. In short, be sure your program isn’t so pretty it’s ugly.

Installing openSUSE 10.2 on Virtual PC Step by Step

My “Installing Ubuntu on VirtualPC Step by Step” post ( continues to be one of the top read posts on my blog each day. I thought it was about time to look at another Linux distribution, openSUSE.

In November 2006 Microsoft and Novell announced a new initiative, stating they were collaborating on Linux / Windows interoperability. Read the full press release at or

In the spirit of collaboration, many of you may wish to explore openSUSE but may not have a spare machine to use it on. VirtualPC is the answer to your problem.

Before we begin, you’ll need to download a few components. First, you need Microsoft VirtualPC itself. or I’m using the 2007 Beta RC1, but this should work with 2004 as well. Previously I’ve installed openSUSE 10.1 on VirtualPC 2004 with no problems.

Next you will need the openSUSE.distribution, or is the place to grab it.

Be warned OpenSUSE ISO image is quite large, you’ll be a while downloading it. You will probably want to burn it to a DVD. If you don’t have a DVD burner handy, you can also use the Microsoft Virtual CD tool (which will work for DVDs too). I blogged about it at

A quick note, there are, as of this writing some issues with openSUSE 10.2 not recognizing the sound drivers with Virtual PC 2007 RC1. If sound is important to you, consider staying with Virtual PC 2004, or use openSUSE 10.1. As sound wasn’t that big of a deal, I used 10.2 and VPC 2007, but I’ve also installed 10.1 under VPC 2004 and my experience was almost identical to what I write about here.

Finally before you get started, spend a few minutes getting familiar with VirtualPC if you have not already done so. You can find my step by step instructions for VirtualPC at Keep it handy, at various points I will be referring to it.

Like now. In Step 1 of my VirtualPC Step by Step you are instructed to create a new machine, please do so. I’ve named mine “openSUSE”. In step 2, you are prompted for your OS. You will need to pick Other. In step 3, you are asked about Ram. openSUSE will run OK under 256 megs, however if you have the available space I’d highly suggest upping it to 512, especially if you intend to get into doing some graphics or mono coding.

In step 4 you will want to create a new hard disk, and in step 5 confirm what you’ve selected. OK, now you are up to step 6, installing the OS, which is where this tutorial picks up.

The first thing you will see is the boot screen. Here it asks if you want to boot from the hard drive (you can’t as nothing’s installed yet on your virtual hard disk) or install in a variety of methods. Hit the down arrow so “Install” is highlighted and hit the Enter key.

[openSUSE 01]

The screen will turn blue, churn for a bit, then black with a little clock. Be patient, it’s working. Finally, you get to see a screen to begin your installation journey. On the first one, you get to select which language you want. Select your language of choice, and click next.

[openSUSE 02]

Next you are shown the license agreement. If you are hyped up on Jolt Cola and Double Espressos and need some sleep go ahead and read through it. Otherwise, click the “Yes I agree”, then click next.

[openSUSE 03]

Now you are asked what mode you are doing the install in. Since this is a fresh machine the only valid option is New Installation. If there had been an older version of openSUSE on the machine you would also have the upgrade option. For now, take the default of New Installation and click Next.

[openSUSE 04]

The openSUSE installer will now do some System Analysis. It will read over your system and produce you a list of what it’s going to install. It’ll take a minute or two, so be patient.

On the next screen you are asked about the Time Zone. Pick the time zone you live in and press next.

[openSUSE 05]

Now comes your first difficult decision. openSUSE wants you to pick a default desktop. Unlike Windows, Linux will let you pick from a variety of desktop shells. The desktop defines the look and feel of what you see as you interact with the computer.

If you are a Windows user, you might be more comfortable with the KDE desktop. It has a start bar and “K” menu across the bottom. On the other hand Gnome has something more akin to a look and feel from the Mac line. There are others out there, but these are the top two.

There’s one other item to take into consideration. If you intend to do any coding using Mono, you will need to use the Gnome desktop. The last time I checked, the majority of the Mono development tools were designed for the Gnome desktop. (I don’t claim to be a Mono expert, so if this is incorrect please feel free to leave an enlightening comment.) Mono, by the way, is the open source implementation of the Microsoft .Net Framework. Using Mono you can write C# code for a Linux environment.

Don’t stress over this too much. The nice thing about Linux is you can change your mind later, or you can try out a new desktop just to see what it’s like without making a permanent change to your default desktop.

Since one day I hope to dabble in Mono, I will pick the Gnome desktop and click Next.

[openSUSE 06]

OK, getting close. Now openSUSE will show you an installation summary, with everything it’s going to do and install. Give it a glance, and if you are happy with your options click Next.

[openSUSE 07]

This is where the folks at Novell like to play an April Fool joke, in that you only thought you were done with license agreements. In the 10.2 version I downloaded, I’m additionally asked to confirm the licenses for some Adobe product and the Flash player. I clicked OK on both.

[openSUSE 08]

[openSUSE 09]

OK, openSUSE asks you one last time if you are sure. We are (well at least I am) so click Install to begin the install.

[openSUSE 10]

Now sit back and wait. And wait. And wait some more. This thing takes a long time to install, for me the counter started at over 2 hours, although in the end it didn’t take that long.

First you’ll see some screens that talk about preparing your hard disk. Don’t worry, it’s the virtual disk it’s formatting, you’re safe. Finally you’ll see this screen as it begins the process.

[openSUSE 11]

Over to the right you’ll see the count down timer, and the center part will change during the install, giving you nice little tidbits and tricks. This would be a good time to refill your coffee, put some Jolt Cola on ice and order that pizza. You’ll be sitting here a while. (While you’re waiting might be a good time to explore some of my other posts, LOL.)

One real important thing: if your VirtualPC screen goes blank during the install, don’t freak out! Believe it or not, the screen saver is actually active during the install. All you have to do is click inside the VirtualPC window. The screen will then update to show you where it’s at in the install process.

After it’s finally done, it will tell you it’s going to reboot. Go ahead and let it, obviously. If you do nothing, the machine will reboot itself.

After the reboot you’ll see the same screen you saw when you first started, assuming you didn’t eject the openSUSE dvd. Pick the “Boot from Hard Disk” option, or if you do nothing it will take it as the default.

[openSUSE 12]

The next screen asks if you want the default of openSUSE 10.2, to boot off of Floppy, or the Failsafe mode for 10.2. Failsafe is kind of like Safe Mode under XP. Normally you’ll pick the openSUSE 10.2 option, which is what we will do now. (Doing nothing by the way will automatically select this.)

[openSUSE 13]

After the system finally gets done rebooting, there are some final installation steps that need to take place. First, you are taken to a screen and asked what you want the root user password to be. This is the master password for the system, you need this to install software or do any serious maintenance. Enter something secure, but easy to remember. Most of all don’t forget it, or your lovely Linux install will become severely handicapped. Enter your chosen password now, then click next.

[openSUSE 14]

Next you are prompted for a host name and domain name. Take the defaults and click Next.

[openSUSE 15]

In the next window you are asked about the network configuration. Be patient while openSUSE examines your virtual system. When done, just click Next to take the defaults it finds.

[openSUSE 16]

At the end of the network configuration, openSUSE wants to test your connection. Assuming you are connected to the web, leave Yes selected and click next to perform the test. Now, when I tried to do the test, it kept failing on me. I puzzled, fumed, changed things, but could find nothing wrong.

Finally, out of desperation, I clicked the Back button to return to the screen below, then told it to skip the test, and go on. By golly, it actually worked just fine! I guess the problem is on the Novell end, as openSUSE happily proceeded to download all sorts of online updates with no problems. Your experience may vary a little, but if you try the test and it fails, try using the Back button, tell it No, skip the test, and go on from there. I’m betting it’ll work OK for you too.

[openSUSE 17]

The online update is next, here openSUSE will try to download the latest patches and what-not for your system. You have the option to skip by picking No, but I would suggest you let it run so you can have all the latest security updates and bug fixes. (Note if you are not hooked to the internet, or were unable to get the networking to work, you will want to skip this step.)

As the first step in the updates, you are asked about additional installation sources. For now, take the defaults as shown and tell it Yes, to register the checked sources.

[openSUSE 18]

You will now see a series of update screens flash by as your system is updated from the internet. The screen will look something like this:

[openSUSE 19]

Just let it go, it will take a bit (especially if you have a slow connection). When it’s done openSUSE will automatically take you to the next area.

In this next area you are prompted for users. First, you are asked about the method for authenticating users. There are some nice options here, including the ability to check against a windows domain. For our purposes though, the default of Local (/etc/passwd) will do just fine, so click Next.

[openSUSE 20]

Next you are prompted for user info. Enter your name, what user name you’d like to have, and a password for that user. There’s also a checkbox for Automatic Login. If you will be the only one using this VirtualPC, you can leave this checked on.

On the other hand, if you will be sharing this VPC with friends, you may wish to uncheck this. When you do so openSUSE will request you to login each time. One last note, you will want to make your password different from the one you entered for the root user. It’s not a requirement, but it is a good idea. Once you have entered everything, click Next.

[openSUSE 21]

OK, now sit back and wait a few minutes, as openSUSE is going to finish setting up your user account, then is going to run some cleanup.

[openSUSE 22]

When the cleanup is done you are automatically shown the release notes. This describes changes and the like since the last version. Take a quick glance, and know that you can always pull these up later if you are in a hurry. Go ahead and click Next when you are done.

[openSUSE 23]

In this last step you are shown your hardware configuration and asked to confirm it’s what you want to use. While it’s examining your config your screen may switch back to a text display, then back to the graphical installer. This is normal behavior, just be aware of it.

When it’s done examining, you’ll be ready to click Next. Note one item, there have been some issues with openSUSE not detecting the sound card of Virtual PC 2007. If sound is extremely critical to you, consider sticking with either VPC 2004, or drop back to openSUSE 10.1.

I can wait for the sound issue to get fixed in a later patch, so I’ll be clicking Next at this point.

[openSUSE 24]

You’ve hit the finish line! You installation is complete, all you have to do now is click the Finish button.

[openSUSE 25]

When you do, openSUSE will complete a few tasks, then ‘reboot’ your virtual system. This will take a few minutes, and when done you are logged in and ready to use your openSUSE Virtual PC.

[openSUSE 26]

Click on the “Computer” icon in the lower left, to begin exploring your openSUSE installation.

[openSUSE 27]

To get up and running with openSUSE I’d recommend a good podcast to you called Linux Reality. Chess Griffin is the host, and did a great three part tutorial on openSUSE at these links:

Part 1:




Part 3:


His original tutorial was for 10.1, so there may be a few minor differences but not enough to make a difference.

There’s also a support site for SUSE Linux you can find at or

That’s about it, one final note. As I tell my kids, when you are done playing make sure to put away your toys. To shut down your Virtual PC openSUSE, just select Logout from the Computer menu, and it will give you a screen with the standard Logout, Shutdown, etc. menu options. Just pick Shutdown and you are free to go get that cup of coffee you’ve been waiting for.

IEnumerator in C#

In yesterday’s post I mentioned the IEnumerator interface. To be honest it probably was not the best example to cite for an interface, since it is implemented in a non-standard fashion. However, it’s also the interface you will probably want to implement the most often, so I thought it worth showing you a quick example.

For today’s lesson I will continue to use the Employee example I’ve shown over the last few days. The only change I need to make is to the Employee’s class declaration, for easy coding I want it to have a public scope. In looking back I hadn’t put a scope qualifier on the class declaration, and when you omit a scope the compiler defaults to internal.

  public class Employee : IPersonM, IPersonP


Now that’s done, let’s create a class that will hold multiple employees. We’ll call it Employees (plural) and have a method to add employees to it. Internally we’ll store the individual Employee objects in a generic List<T> collection.


using System;

using System.Collections.Generic;

using System.Text;


namespace OOPDemo


  public class Employees


    private List<Employee> _employees = new List<Employee>();


    public void AddEmployee(Employee emp)





    public IEnumerator<Employee> GetEnumerator()


      foreach (Employee emp in _employees)


        yield return emp;







Before I explain the details, let’s look at how to use the new collection.


      Employees myEmployees = new Employees();


      Employee emp1 = new Employee();

      emp1.FirstName = “Carl”;

      emp1.Lastname = “Franklin”;



      Employee emp2 = new Employee();

      emp2.FirstName = “Richard”;

      emp2.Lastname = “Campbell”;



      Employee emp3 = new Employee();

      emp3.FirstName = “Mark”;

      emp3.Lastname = “Miller”;



      string everyone = “”;

      foreach (Employee emp in myEmployees)


        everyone += (emp.FullName() + Environment.NewLine);



      MessageBox.Show(everyone, “Everyone”);


As you can see this is pretty straight forward, it created 3 employee objects and called the AddEmployee method to add them to our collection. The code then enters a foreach loop retrieving each individual Employee object from the collection of Employees.

What makes this work is the IEnumerator interface. By having the Employees class have a GetEnumerator method that returns an IEnumerator, we enable it to be used anywhere that an IEnumerator can be used, such as a foreach loop.

The only other thing to explain would be the new keyword yield. Each time through the loop the yield will exit the loop and return to the calling routine. The next time through the foreach loop, the GetEnumerator picks right back up at the yield statement, and loops to the next item in our internal List.

To your method, he yield keyword is sort of like sleep mode is to the computer. It pauses, then returns control to the calling routine. When you return, you re-enter the routine right where you left off, with all the routines and variables just as you left them. Not unlike powering up your computer again from sleep mode.

What makes this a little different is that the method GetEnumerator is what implements the IEnumerator interface. Normally, interfaces are implemented by the entire class, not just a single method.

While not the best example of a standard interface, it does demonstrate the power of extending an existing .Net interface. In this example it suddenly allowed your class to be used by a foreach loop. Take advantage of the built in .Net interfaces to make your own classes even more powerful and fit into the .Net environment.

More OOP: Interfaces in C#, Part 2

Yesterday I introduced you to Interfaces in C#. There’s a bit more about interfaces I wanted to share. With a normal class, it can only inherit from one base class. However, it can implement multiple interfaces.

By the way, this seems like a good time for a little lesson in terminology. A class inherits from another class, but it implements one or more interfaces.

Let’s look at our IPerson interface from yesterday. For various reasons our architect has decided it should actually be implemented as two interfaces, one with the properties and another with the method. (For demo purposes I left both interfaces in the same file, in real life I would have each in it’s own file.)

using System;

using System.Collections.Generic;

using System.Text;


namespace OOPDemo


  public interface IPersonP


    string FirstName { get; set;}

    string Lastname { get; set;}



  public interface IPersonM


    string FullName();





Now we need to modify our Employee class to implement both methods.


  class Employee : IPersonP, IPersonM


Notice all it took was separating the interface names with commas. If we were also inheriting from a base class, we would list it first. Yes, you can both inherit from a single base and implement one or more interfaces for a class.

Finally, we need to make a quick update to our ShowName, since the old IPerson has been replaced with an M and P version:  

    private void ShowName(IPersonM per)


      MessageBox.Show(per.FullName(), “ShowName Method”);



You need to be careful when designing your interfaces, not to get too focused. In the above example, what if in the ShowName method you need to also access the FirstName property? Can’t do it with the code as it is now since IPersonM knows nothing about those properties. Instead you’d have to pass in an Employee, in which case we’ve limited our functionality. The ShowName would no longer be able to accept a Contractor or Vendor (assuming we ever created them).

So, we know that a good time to use an interface is when you have a base set of properties and methods, but not code, that you wish to share among classes so that you can treat them as the same generic type. What other times might you wish to use interfaces?

In his book Programming .Net Components ( Juval Lowy has an entire chapter devoted to interface based programming. When writing a class library (i.e. a dll) Mr. Lowy suggests only exposing interfaces. Why? This leaves you totally free to redesign even your base classes.

Even further, Juval advocates placing all of your interfaces into their own class library. Because it’s fairly quick to create interfaces, it allows both the user interface team and the class library team to get to work, both referencing the same interface dll.

A final reason for using interfaces is to extend your class so that it is compatible with items in the .Net Framework. .Net exposes a slew of interface types, and you can implement any of them in your classes.

A common example is the IEnumerator interface. If you were to implement the IEnumerator interface in your class, you could then use your class anywhere you would use an enumerator in .Net, such as in a foreach construct.

Hopefully by now you’ve seen the power of an interface, and will begin using them in your own applications.

More OOP: Interfaces in C#, Part 1

During our discussion on OOP (see my posts for the last few days) one of the key concepts was the base class. The base class was a place where we could put code that would in turn be used by the classes that descend from the base.

The use of the base class allows us to take advantage of polymorphism, the ability to treat a lot of specific child classes as if they were the same less specific, more generic type (the base). Notice a point I made a moment ago. The base class contains code, that will be inherited.

What if you have a situation where you want a common base, but you don’t have any code that will be reusable by it’s descendants? Interfaces step in to fill the need.

One classic example given in every book is the Shape. You never have “a shape”, instead you have rectangles, squares, circles, triangles and more.

An example from the real world might be the concept of lunch. Every day my coworkers and I go out for lunch. Lunch has a common method called Eat, yet the implementation varies depending on the type of food we pick. With Mexican we can eat chips and tacos with our hands. For Oriental we use chopsticks. For Italian, better use that fork. We have the common concept of Eat, but the implementation for each food type is so different we probably won’t be able to share any code.

Implementing an interface in C# is not difficult. Drawing back on our Employee example from the last few days, let’s say in your company you wanted to define a new type called “Person”. You will never have a “Person” object, instead you will always create an Employee, Contractor, Volunteer, and the like. To implement this, let’s create a Person interface.

First, right click on your solution and select Add, New Item, and select Interface from the long list. Set the scope to public.  

using System;

using System.Collections.Generic;

using System.Text;


namespace OOPDemo


  public interface IPerson


    string FirstName { get; set;}

    string Lastname { get; set;}

    string FullName();




There’s several areas I need to draw your attention to. First, after public we used the keyword interface. This is the signal to the compiler that this is a declarations only, and has no code.

Next is the name, you see I put the letter I in front of Person. A long standing tradition is to name all of your interfaces with the letter I in front, and it’s a tradition I’d suggest you stick to.

Notice the FirstName and Lastname areas, this is how we declare there will be properties with a get and set. The FullName line is how we specify there will be a method with the name FullName. Note too there is no scope qualifier in front of any of the return types (in this case they are all string). Because this is an interface, all items must have a pubic scope.

Now we need to actually use the interface. Let’s modify our Employee class to implement the Iperson interface. All it takes is a modification to our class declaration.

  class Employee : IPerson


Indicating the Employee class will now implement the Iperson interface carries certain connotations. It means we must implement all of the properties and methods the Iperson interface declares. Since we already have FirstName, Lastname, and FullName we are in good shape. However, if we had not we would have to create those properties or methods we were missing.

Now, via polymorphism we can treat the Iperson just as if it were a base class. Let’s modify the ShowName method from yesterday to use an interface instead of a base class.  

    private void ShowName(IPerson per)


      MessageBox.Show(per.FullName(), “ShowName Method”);



This now makes the ShowName more functional for us. In the future, if we do implement a Volunteer or Contractor they too could be used in the ShowName method.

Using interfaces will allow you to further extend the power of polymorphism. In addition it gives you a way to create base classes in situations where you have no common code to put in the base.

Tomorrow: More on Interfaces.


Object Oriented Programming Pillar #3: Polymorphism

The third plank of OOP is a concept called Polymorphism. In my last post we went over Inheritance. Inheritance allows us to go from something generic, like an Employee, to something more specific, like a Manager or Peon. Polymorphism allows us to go in the reverse direction, treating something specific as something more generic.

Why would you want to do this? In our example, payroll would be a perfect example. Let’s first create our Peon class. We’ll also be using the Manager and Employee classes we have been using over the last few days.  

using System;

using System.Collections.Generic;

using System.Text;


namespace OOPDemo


  class Peon : Employee


    public Peon(): base()




    public override string FullName()


      string retval;


      if (base.FirstName.Length > 0)

        retval = base.FirstName.Substring(0, 1) + “. “ + base.Lastname;


        retval = base.FirstName + ” “ + base.Lastname;


      return retval;





As you can see, Peon is pretty simple, I called the base constructor so I wouldn’t wind up homeless (see yesterday’s comments) and overrode the FullName method just because I could.

Now what we want is a routine that will call a method common to every Employee object. Here’s one I whipped up.  

    private void ShowName(Employee emp)


      MessageBox.Show(emp.FullName(), “ShowName Method”);



In the real world, we would probably be doing something here like call a “PayEmployee” method. PayEmployee is something we would do for all employees, regardless of whether they are a manager or a peon. For this example I’m just calling the FullName method, since we’ve been using it the last few days. Now we need to create our various objects and pass them to ShowName.


      Employee emp1 = new Employee();

      emp1.FirstName = “Carl”;

      emp1.Lastname = “Franklin”;



      Manager mgr1 = new Manager(); 

      mgr1.FirstName = “Richard”;

      mgr1.Lastname = “Campbell”;



      Peon peon1 = new Peon();

      peon1.FirstName = “Mark”;

      peon1.Lastname = “Miller”;



Here you can see I’ve created one Employee, one Manager, and one Peon object. But I can pass all three of them to the same ShowName method and treat them like Employees. Why? Because they are all descended from (or are) the Employee class. Polymorphism makes all this work.

You should note something very important here. If you actually run the program, you’ll see the following message boxes appear, in this order:

[Pic of Employee FullName]

ShowName with Employee

[Pic of Manager FullName]

ShowName with Manager

[Pic of Peon FullName]

ShowName with Peon


Do you see it? Even though within the ShowName method we are treating everything like an Employee, the compiler was smart enough to know they were not all Employees. Instead, it called the overridden method in the child class (Manager and Peon), not the one in the base class. This behavior is very important to understand. On one hand, it’s what makes Polymorphism so powerful, but if you are not expecting it, you can get bit.

Because this can get confusing, let’s see if I can relate this to a real world example. I have a wife and two daughters. Their base class might be “family member”, but their specific classes are wife (Ammie), daughter 1 (Raven) and daughter 2 (Anna).

On days where I might work from home, I can send family member a message (i.e. yell) “get daddy a Jolt cola”. The base implementation is open refrigerator, get soda, bring to daddy (that’s me). My wife Ammie just uses the base implementation of the “get daddy a Jolt cola” method.

My oldest daughter, Raven isn’t quite tall enough to reach the sodas on the top shelf, so she has to override the “get daddy a Jolt cola” method by adding a step to stand on a stool so she can reach them.

My youngest daughter, Anna is even shorter still, so her override calls for her to stand in a chair in order to reach the soda.

Now, in all three cases I simply call the “get daddy a Jolt cola” method of the “family member” object. When the individual object (Ammie, Raven or Anna) executes the “get daddy a Jolt cola” method, they each use their individual implementation to do so.

So where are some situations where Polymorphism would come in handy? Yesterday you may recall I said my classes in my Database Layer (often referred to as the DL) all descend from a common base class.

Within my program then, I can take all of my database objects and pass them into a “CloseConnection” method. The CloseConnection method does what it says, closes any database connections before exiting the program. Because of Polymorphism, it doesn’t matter what type of data object I’m dealing with (Purchase Order, Employee, Work Order, etc) they all need to close, and this lets me do it in an easy, consistent manner that’s easy to update and maintain.

Another real world example: I created a special combo box control to which I added some additional features. My new combo was descended from the standard combo box in the toolbox.

I then turned around and created four new combo boxes from my special base class combo. Each one was bound to a specific type of data, and I used these over and over in my application. Each one though had some common methods, such as Load and Reset.

When my form loaded, I passed each combo box to a method to load them. All this method did was called the load method for each box, and because I’d overridden the load method it called the correct Load for each type of combo box.

Over the last few days I’ve written on the basics behind Object Oriented Programming, using C# to demonstrate. You should understand I’ve only scratched the service as far as power and flexibility go, OOP is a big subject. But hopefully what I’ve discussed here will serve as a starting point for your OOP journey.

Object Oriented Programming Pillar #2: Inheritance

The second pillar of OOP is Inheritance. But if you read the title of today’s blog, you probably already guessed that. Inheritance allows us to both reuse and extend code, plus allow you to easily make changes to a class and have them ripple through to the decedents.

Take a look at the Employee class from yesterday. When I think of employees in a company, I can think of at least two kinds, Managers and Peons (like me). Both are types of employees, but both have some things different. Inheritance allows us to reuse the best parts of employees, but add special functionality as well.

Let’s create a new class, called Manager. Here’s what I coded:

using System;

using System.Collections.Generic;

using System.Text;


namespace OOPDemo


  class Manager : Employee


    // Constructor, call the base

    public Manager(): base()




    // Meaningless work, just like a real manager would do.

    public void MakeHairPointy()


      string myPointyHairOrder = “Write me a program by last week.”;






The first thing you may notice is the : Employee after the class Manager. This tells the compiler that the Manager class is descended from the Employee class. Any methods, properties, and events available in the Employee class are now automatically available in the Manager class.

Next you see a line that says public Manager(). This is the constructor for the class. In here you can put code that you want to execute when the class is created. Perhaps this is setting some defaults for class variables, creating other classes, or a variety of other items. I don’t need to do anything, so I’ve just left it blank.

After the Manager() you see the : base() construct. This tells the compiler “hey, before you run the constructor in Manger, go run the constructor in your base class, employee, then come back and run the Manager’s constructor”. Even though I don’t currently have any code in Employee’s constructor, one day I might. Plus if I’m following good encapsulation then I don’t know whether or not Employee has a constructor, nor do I care.

Using the base() keyword is not only common practice but a good idea. If you don’t, you’ll likely wind up on the side of the road, homeless holding a sign that reads “Will code() for food;”.

Enough on constructors, let’s look at a sample that uses our new Manager class.  

      Manager mgr1 = new Manager();  //Constructor runs here!

      mgr1.FirstName = “Arcane”;

      mgr1.Lastname = “Code”;


      MessageBox.Show(mgr1.FullName(), “Manager FullName Dialog”);

Even though you won’t find them in the code for the Manager class, you see I am calling FirstName, LastName, properties and the FullName method. The Manager inherited these from Employee.

Imagine you had not one or two types of employees, but fifty? Then imagine your boss wanted you to make a change to the FirstName property, so that if the length were only one character it automatically put a period at the end of the first name? Now you begin to see the power of inheritance.

You make your change to the Employee class, which is known as the base class. Recompile, and you are done. That change is automatically reflected in all of the child classes that inherit from the base Employee class.

What if you have a situation where you want to implement something in the base class in a slightly different way? You have the power to override the base classes implementation of that method. That’s a fancy way of saying you can create a method with the same name in your descended class, with your new code. But there’s a big “if” you need to know about. (Isn’t there always?)

When you create a method in a base class, you must use the virtual keyword in the method declaration. This flags the compiler that it’s OK to override in child classes. Without the virtual keyword, the compiler will produce errors and fail. So let’s fix our employee classes FullName method so we can override it later.  

    public virtual string FullName()


      string returnValue;

      returnValue = _firstname + ” “ + _lastname;

      return returnValue;



All that was really needed was to slip the virtual keyword between the scope and the return type. Now we are ready to rewrite this method in our Manager class. 


    public override string FullName()


      return “Oh great one “ + base.FirstName + ” “ + base.Lastname;



Now when I run my code, I will see the rewritten FullName for the manager appear.


[OOP Demo 2 Picture]


Note too the use of the base.FirstName and base.LastName. Through the keyword base, you can access any of the non-private properties and methods of the base class. I could just have easily have done:


    public override string FullName()


      return “Oh great one “ + base.FullName();



If you take some time to plan your code architecture (see my post or you can probably come up with many good relationships where you can go from abstract to something more concrete.

A real world example, in my database layer I descend all data handling classes from a base class that has common properties / methods such as the connection string and a connection object. This lets me write the connection “goo” once and use it over and over.

Don’t forget that at their heart, forms and toolbox items are classes as well, and you can inherit from them. A common technique is to override all of the common controls and use your version in your applications. The technique is slightly different so I will defer discussion on inheriting graphical stuff until another day.

A classic story I heard on DotNetRocks ( is the lead developer who gets a call three days before their 300 form application is due to go to production. “Oh by the way” says the customer, “we forgot to mention it but it’s a requirement that all text boxes force their letters to uppercase.”

Even though they had not tweaked the text boxes previously, they had still made a decision lo those many months ago to inherit from the base text box and use the new one in their project. Because of that, they made a quick change to one routine in their custom text box, and all 300 forms were fixed in less than half an hour.

Inheritance can be an incredibly powerful tool when used correctly, but as my favorite hero Spider-Man used to say, “with great power comes great responsibility”. Make sure your inheritance chain is well thought out, lest you feel trapped in a spider’s web of your own making.