Saturday, 31 December, 2005

Year end recap

This has been most interesting and satisfying year for me in quite some time.  A recap:

  • The beginning of the year found Debra and me hard at work training for the ride to Harlingen.  We completed the trip, 335 miles in three days, as I chronicled here.  The great achievement for me wasn't in completeing the ride--I'd already done that.  The great thing for me was seeing Debra go from never having ridden a bike more than 10 miles (April 2004), to riding 100 miles with me in October 2004, and then completing this ride a year after she started training.  It's amazing what you can do when you set your mind to it and work on it a little bit every day.
  • In May, I finally got the contract I'd been working towards for over six months.  I had become increasingly disillusioned with my consulting job at Catapult Systems, and was eager to move on to something new, different, and exciting.  A week after I got the contract, I was on the airplane to Japan for meetings with the client and a huge culture shock.  I wrote up some of my experiences here in my May 2005 entries.
  • Debra and I didn't travel much this year, and to tell the truth I didn't keep up with my Random Notes as much as I would have liked to.  Working on the 3D graphics project kept me busy, with little time for exploring and writing about new things.
  • My truck died in October, and after considering my options for a while, I decided to replace the engine myself.  This from a guy who used to say, "I don't work on cars."  I amended that to mean, "I don't work on cars when there's a deadline," because I really wanted to see what was involved in replacing an engine.  It's been an interesting project, but I think the major bit of knowledge I'll take away from the experience is a better understanding of why I pay other people to maintain my automobiles.

Those were the major happenings over the year.  A few others of note:

  • Debra and I disconnected the cable TV in January and haven't missed it a bit.  What little time we spend in front of the idiot box these days is with DVD movies and some select TV series that we got on DVD.  No longer are we slaves to the idiocy that the networks call entertainment.
  • I still haven't settled on a blogging tool.  I keep using this one (CityDesk) because it mostly works and I haven't found anything that I like better.  That might change soon, though.
  • My shoulder got worse, then better, and then I discovered that there's a structural problem in there.  I'll almost certainly need surgery if I want it repaired.  No amount of massage, chiropractic, or physical therapy is going to fix the underlying problem.
  • I had a heck of a time with technical support departments this year.  I'm glad I don't need to call them very often.
  • I finally broke down and bought a laptop computer.  For years I viewed them as nice toys or convenient indulgences.  Two weeks with the new machine and I couldn't imagine living without it.  Ditto wireless.
  • A friend from high school found me on the Internet, and I managed to meet another friend whom I hadn't seen in almost 25 years.
  • Debra and I joined Toastmasters in order to improve our public speaking skills.  I'm somewhat surprised at how much I enjoy those weekly meetings.  As of this writing, I'm halfway through the CTM program--10 speeches to get the "Competent Toastmaster" award.
  • I had lots of fun with ham radio:  a new antenna, pedal-powering a radio on Field Day, emergency communications with hurricane Rita, some emergency exercises, and learning a few new things.  All in all, though, I'm finding ham radio somewhat lacking in excitement.  It's an interesting hobby, but I think I need to put it aside until I can build a workshop and tinker with the hardware.
  • We found a leak under the concrete in our master bathroom on the day before Thanksgiving.  We had the leak repaired, and the insurance company has cut us a check for the damages.  Now comes the big job:  remodeling.  We've finally decided to spend the money and have the work done.

All in all it's been an excellent year.  The year end finds us healthy and happy, and ready to start the next one.

Monday, 26 December, 2005

Home auto repair

If everything goes as expected, I should have the truck on the road sometime before the 15th of January.  Beyond the obvious things I'm learning by replacing the engine myself, I'm also learning a few things that aren't so obvious--mostly about the shops where I've had work done on the truck over the years.  For example, when I removed the starter I discovered that there was a bolt missing.  I know for certain that the starter had been removed at least once by the dealer's mechanic.  But I can understand a missing bolt.  People make mistakes.

What bothers me the most is the condition of some of the parts in the engine compartment.  Almost every rubber vacuum hose, for example, was so brittle that it broke when I pulled it off the fittings.  The rubber in both motor mounts (the brackets that attach the engine to the frame and dampen vibration) were broken, the rubber so brittle that I could flake pieces off with my fingernail.  Various wiring conduits were cracked or burned.  Of course, since I have everything taken apart, I'll be replacing or repairing all of these things.

A good mechanic who cares about the vehicle he's working on would notice these things and replace them.  But a mechanic who's working on somebody else's car is in a somewhat difficult position.  If he were to suggest replacing every part that looks worn, it's likely that many people would be less than happy--feeling that the mechanic is trying to "nickel and dime" them to death.  A brittle vacuum hose, for example, will continue to work for a long while.  At some point it'll break and the owner will bring the car in for service.  At that point, the mechanic will probably inspect all of the hoses and suggest replacing those that are worn.

The motor mounts are a different matter altogether.  One would think that the motor mounts would be inspected during the regularly scheduled service.  I've taken the truck to the shop for scheduled service every 15,000 miles, and at nobody ever suggested to me that I replace the motor mounts.  From their condition, I'd say that they've been broken for several years.

In retrospect, I'm not terribly surprised by what I've learned.  I haven't been able to find definitive numbers, but in general people don't keep their new cars for very long.  Many people sign 3-year leases and get a brand new car every three years.  Others buy a new car every five years or so.  In most cases, people don't keep a car long enough for the warranty (or extended warranty that they purchased at a highly inflated price) to expire.  They take their cars to the dealer, whose mechanics are instructed to fix the immediate problem and move on to the next car.  The dealer makes very little money on warranty repairs.  So by the time a car's extended warranty expires, there are many things that should be replaced.

If, like me, you keep your cars for many years, then you're in a difficult position.  Warranties probably don't recover preventive maintenance like replacing a brittle vacuum line before it breaks, and in any case it's unlikely that a dealer's mechanic would suggest doing such a thing anyway.  If you want to keep a car after the standard warranty expires, your best bet is to find an honest mechanic who will suggest such things, and then follow his advice.  Either that or do the work yourself.

When I first posted the note about my truck dying, I tried to evaluate the costs and benefits of buying a new truck, buying a used truck, or repairing mine.  At the time, I figured that a used truck would cost between $6,000 and $10,000.  The dealer wanted $5,600 just to replace the engine, and that didn't include replacing any other parts (like vacuum hoses, motor mounts, and any other wear items) that might need replacement.  Doing the work myself, I figure I'll be into it for about $6,000 by the time I'm done, but I'll have an essentially new drive train (I had the transmission rebuilt), all new hoses, and I'll know that everything is done right.  I also have the peace of mind knowing everything else about the vehicle.  All told, I'm financially much better off than I would be had I bought a new or used truck.

The only thing I'm out is my time.  If I were 100% billable, then it'd definitely be a loss.  But I haven't spent any billable hours working on the truck.  What I've done instead is use the time that I'd normally use for other hobbies:  ham radio, bicycling, playing games, reading, etc.  Plus, I've learned something new, which is always a good thing.

Saturday, 24 December, 2005

The engine comes out

After more time than I thought it would take, the engine is out of the truck.  I had planned on spending maybe one full day disconnecting things from the engine and transmission before hooking up the cherry picker and pulling the engine.  It ended up taking closer to three full days to get everything disconnected and labeled and by the time I was done, the only major piece of equipment still attached to the engine was the distributor.  I ruined a few bolts in the process by rounding them off with the wrench.  I think somebody got a little carried away with the air impact wrench.  Or, perhaps the steel bolts in the aluminum cylinder head just corroded enough to be really difficult to remove.  Maybe a combination of both.

The picture to the left is of the truck finally giving up the engine and transmission.  My neighbor Tom, who has a small collection of 1950s era automobiles, was kind enough to lend me his cherry picker and his expertise.

Now comes the fun part.  With the engine out of the truck, it's time to clean ten years worth of accumulated oil and grime from inside the engine compartment, take parts (alternator, starter, transmission, drive shaft, etc.) to be examined, fixed, or replaced, and replace the bolts that I had to destroy in order to take things apart.  One of the transmission dust cover bolts was amazingly resiliant.  It took us over an hour with a hammer and cold chisel to get it to turn.  This was another case of a steel bolt in an aluminum housing.  I wonder if there's a Never Seez product to prevent that.

The old engine now sits on the floor of the garage with all of its old parts removed.  The new block is on an engine stand, waiting for me to start bolting parts to it.  But first I have to clean all the old parts and decide just how much I'm going to attach to the new engine block before bolting the transmission back on to it and sliding the whole mess back into the truck.  Maybe next weekend.

Monday, 19 December, 2005

Getting ASP.NET to work

When I tried to create an ASP.NET project from Visual Studio, I got this error in my error log:

aspnet_wp.exe could not be started. The error code for the failure is 80004005. This error can be caused when the worker process account has insufficient rights to read the .NET Framework files. Please ensure that the .NET Framework is correctly installed and that the ACLs on the installation directory allow access to the configured account.

Of course, before I checked the error log, I tried all manner of different things:  changing directory permissions, sharing folders, etc.  I don't remember what tripped me to checking the error log, but once I saw the error I was able to this Microsoft's Bnowledge Base article which supplied the solution.  The article talks about a domain controller, but the solution was the same for my Windows XP Pro system with Service Pack 2.

There are three solutions to the problem, all of which involve modifying the .NET Machine.config file (located, on my system, at C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\CONFIG).  The easy solution is to change the userName attribute in the <processModel> section to SYSTEM.  Doing so has serious security implications because the SYSTEM user is a highly privileged account.  You could do the same thing by using an administrator account.

The safe but slightly more involved way around the problem is to create an ASPUSER account and configure it as recommended in the Knowledge Base article.  Doing so ensures that your ASP.NET pages will run, but restricts the permissions so that a malicious program can't wreck havoc on your system.

Oddly, the KB article says that this bug was fixed with .NET Framework 1.1.  I have 1.1 on my system, and the bug still exists.  Perhaps the old version (.NET Framework 1.0) has some pieces left?  Or maybe it's a separate bug.

Wednesday, 14 December, 2005

Bathroom leak repair

The plumber arrived this morning to see if he could find and repair the leak in our bathroom.  After a few hours of chipping out concrete, he located four pinhole leaks in a three foot section of the hot water supply pipe.  A couple hours later and we supposedly have no more leaks.  We do, however, have a large hole in the floor of our bathroom:

We can only guess at what caused the leak.  The plumber said that the copper pipe was touching the steel rebar in the concrete, so it's likely that the cause was corrosion due to dis-similar metal contact.  I'm kind of surprised, though, that it took 28 years for that to show up.  I would have thought that the corrosion would be faster than that.  What's scary is that this kind of thing often causes pinhole leaks to appear along the length of the affected pipe, so it's possible that we could have other leaks that we don't yet know about.  We're going to leave the hole there for a week or more to see if we discover more water.

The plumber mentioned something that I hadn't even considered:  homeowner's insurance.  He said that most insurance companies will pay for discovering the leak and for putting things back the way they were, but won't pay for the actual leak repair.  It that's true then we should be almost fully reimbursed for the plumber's time, since it only took him about 30 minutes to fix the leak after he found it.  I wonder if the insurance will pay for a new cabinet and new floor coverings, too.  You can bet that I'll be on the phone tomorrow to find out.

Sunday, 11 December, 2005

Replacing an Engine: Part 1

My new engine arrived Friday evening, so I spent this afternoon removing various things from under the hood of my truck so that I can get to the old engine.  It's really surprising how much stuff is packed around the engine block in a modern automobile.  In my first car, a 1970 Chevy Impala, there was enough room for me to stand inside the engine compartment next to the engine.  Today there are so many hoses, wires, pumps, and other assorted doodads that a dropped wrench might not hit the floor but instead get caught on something halfway down.

It's been an interesting learning experience so far.  I'm taking my time and labeling everything that I remove, wrapping tape around wires and hoses and labeling them so that I know which wires and hoses connect to what when it comes time to put it all together.  My friend who helped today was giving me a hard time, but he does this stuff for a living.  I don't relish the thought of trying to puzzle out where everything goes when it comes time to put things together again, so I'm taking pictures of every little step.

All the major pieces that I have to remove in order to get to the engine are off now.  There are still some hoses and wires to label and disconnect, and I have to either disconnect the engine from the transmission or disconnect the transmission from the drive shaft and pull them both off together.  The benefit of removing them together is that it's easier to connect the transmission to the new engine when the transmission is off the vehicle.  The disadvantage is that I might have to pull more stuff out of the engine compartment in order to make enough room to pull the transmission out.  We'll see.

To give you an idea of what's involved, I've included two pictures:  before I started taking things off, and now, with most of the stuff surrounding the engine removed.  Here's the before shot:

The important thing to note here is that you can't see the engine!  The resonator, fan shroud, radiator, air conditioning compressor, and other things completely obscure the engine.  There also are untold zillions of wires and hoses connected to various things here and there.  The engine is in there, though, trust me.  You just have to uncover it.

This view is a bit closer, and now you can see the engine down there.  There still is some stuff in the way, but at least I can tell that there's an engine block in there somewhere.  Most of what you see in the center of the picture is connected directly to the engine block, and will come out with the engine.  It's much easier to remove those pieces after the engine is out of the vehicle and you have space to work.

With shipping, the new engine cost about $3,400.  Figure that I'll put another $500 or so into replacement parts (water pump, oxygen sensor, various belts and hoses, etc.).  I figure this is going to cost about $4,000 by the time I'm all done.  That's compared to $5,600 for the dealer to do it, and that price doesn't include replacement parts other than the new engine itself.  That's assuming, of course, that I manage to get everything back together and don't have any parts left over.  This is one do it yourself project that could end up costing way more than having somebody else do it.

Saturday, 10 December, 2005

Traveling Adventures

Debra and I drove to Dallas this morning for a friend's wedding.  On the way we passed three outlet malls--stores where manufacturers sell their wares directly to the public rather than going through normal retailers.  One of the outlet malls is still under construction just north of Round Rock.  One was in Hillsboro, and the other in, I think, McKinney.

What I found odd is that these malls are on the outskirts of major urban areas.  My understanding of the whole outlet mall concept was that the outlet stores would be far enough away from large cities so as to be at least somewhat inconvenient for shoppers to get there.  That way, retailers wouldn't be quite as upset by the manufacturers selling their goods direct.  I wonder what changed.

Leaving the area this evening, I elected to take the toll road so I could avoid most of downtown Dallas.  I pulled up to the toll booth, tossed my 40 cents into the hopper, and waited for the light to turn green.  It didn't.  So I backed up and threw another 50 cents into the hopper.  Still no light.  I didn't know what to do.  A very prominent sign says, "Warning: Stay in Vehicle," and the toll booth person three lanes away was busy doing other things.  So I just drove on through the red light.  Alarm bells went off and lights flashed, but I just kept on going.

I wonder what the penalty is for running the toll booth.  They undoubtedly have my license plate number, and if they were real interested in stopping me they could have caught me at the next tool booth where I dutifully paid my 75 cents to get off the toll way.  I guess I'll see if I get a nastygram in the mail.

I'd appreciate it if somebody who is more familiar with toll way etiquette would tell me what I should have done in that situation.

Thursday, 08 December, 2005

Working with older tools

Circumstances have me working with old stuff lately, and I'm noticing that I miss a few niceties.  I was kind of surprised at exactly which niceties I miss the most.

Since the truck's been down waiting for a new engine (to be delivered tomorrow), I've been driving a 1986 Mustang Convertible that Debra inherited a few years ago.  It's an okay car, although not something I would have purchased myself.  I've been driving that car for two months now, and other than the ability to haul things, the thing I miss most is ... a cup holder.  There is not a single cup holder in that car.  I never really noticed how often I stop for a soda at the convenience store or pull up to the drive through for food.  But now I avoid such things because there's nowhere to put the cup or can.

Auto manufacturers went a little overboard with including cup holders in the mid 1990s, to the point of it being a joke.  But one or two would certainly be nice, and those silly plastic things that hang on the door--if I could even find one today--never were very good.  You won't know how much you miss a cup holder until you drive a car that doesn't have one.

The project I've been working on since May is written primarily in C, with C++  (Microsoft Foundation Classes) for the user interface stuff.  Most of the coding I've done on the project over the last six months has been in C.  You know what I miss the most?  The ability to just declare a variable wherever I need it, without having to open a new scope.  After years of C++, C#, and Visual Basic, going back to straight C is terribly inconvenient.  Try it some time.  It really is primitive.

Actually, the variable scoping limitation is just the thing that trips me up the most when working in C these days.  I'd be more than willing to put up with that if I could have the .NET Framework's graphics library and collection classes (or at least the C++ Standard Template Library).  Doing graphics with the GDI is painful, and the home-grown collection classes I'm working with are quirky.

The nice thing about working with older stuff is that you come to better appreciate the newer stuff when you next get to use it.

Wednesday, 07 December, 2005

Microsoft PowerToys for Windows XP

Microsoft's PowerToys for Windows XP has some interesting utilities.  By far the most useful for me is the "Open Command Window Here" tool, which adds an entry to the popup menu for a directory in Windows Explorer.  If I want to open a command window in a particular directory, I just right-click and select "Open Command Window Here."  No more typing long path names.

Other toys in the collection:

  • The SyncToy looks interesting and perhaps it can help me with consolidating seven gigabytes of archive CDs into a single backup set.  The white paper is full of praise but short on detail, and I haven't taken the time yet to install the program and drive it around.  It seems to be aimed primarily at digital photographers who want to keep their images synchronized, but the white paper indicates that it can be used for other types of files, too.
  • When working with graphics, a magnifier tool is indispensable.  The Taskbar Magnifier puts a little magnifying glass on the Windows taskbar, and will magnify the part of the screen under the mouse.  It's interesting, but I still prefer the old ZoomIn tool that shipped with Visual Studio and as part of the Platform SDK many years ago.  ZoomIn, by the way, isn't included with Visual Studio .NET.  I suppose they decided that the Windows XP Magnifier was better.  I disagree.  If you don't like Taskbar Magnifier or Windows XP Magnifier, you can download a this version of ZoomIn, which is very similar to the original SDK tool.
  • Some people like the Alt-Tab replacement tool.  It drove me batshit.  Tweak UI didn't do much for me, either.
  • I haven't used any of the other tools, but I'm keeping them in mind.  In particular, Image Resizer looks like it might come in handy.  And the HTML Slide Show Wizard could be useful if it generates portable HTML that doesn't require any ActiveX or server side components.  This Web site is running on a Linux box.

Tuesday, 06 December, 2005

Odds and Ends on a Cold Day

A few odds and ends on a cold day.  It was 20 degrees or so when I went out to pedal in the garage this morning.

  • And yet another reason to turn off your television permanently:  Al Sharpton wants his own sitcom.  It's bad enough when actors try to become political activists, but going the other way?  No thanks.
  • For years now I've been getting credit card applications that offer 0% interest for up to 18 months on transferred balances.  It's tempting to see just how long I could carry one of those.  Get a new card today and transfer a balance.  Next year, when I get another offer of a year at no interest, transfer the same balance again.  In theory, as long as I maintain my credit, I should be able to keep that going indefinitely.  But since I don't have a balance to transfer it'll just remain idle speculation.
  • I was backing up some data the other day when I noticed that my Thunderbird mail file was over 500 megabytes in size.  Now I might get (and save!) more mail than some people, but I looked at my saved messages and just couldn't see how they could add up to half a gigabyte.  I searched the menus and found "Compact Folders" under the File menu.  Now my mail files are a more manageable 100 megabytes.  That's still pretty big, but half of it is archived messages from the project I've been working on and most of the rest is my "Sent Items" folder, which I probably should go clean out.  It's hard to believe that 550 sent messages are occupying 37 megabytes.  Thunderbird chews up disk space.

MAKE Magazine's (see yesterday's entry) blog pointed me to the Tom's Hardware article Windows in Your Pocket, which describes how to create a bootable Windows USB drive.  With a valid Windows XP setup disk, some free utilities, and a fair amount of fiddling around, you can create an emergency boot device to be used for rescue, virus scanning, disk partition backup, and many other things.

I don't know if it's possible to use the thing to boot a computer other than the one on which you created it.  I suspect not, due to the Windows XP activation system.  Even if possible it's likely a violation of the license agreement.

Sunday, 04 December, 2005

MAKE Magazine

I've always been something of a tinkerer.  I'm not in the same class as my friend Jeff Duntemann who designs and builds radios from spare parts--or of most of the guys in my ham radio club for that matter--but I enjoy building things from time to time.  At least I'm not dangerous with a screwdriver.

In any case, today I ran across MAKE Magazine (an O'Reilly publication), the tinkerer's dream.  Interested in making music instruments out of Lego blocks?  How about modding your espresso machine so that it always makes the perfect cup?  A headphone amplifier that fits in an Altoids tin?  That's just the current issue.  The previous issue focused primarily on car modifications, although the VCR Cat Feeder and The Night Lighter 36 potato cannon sure sound interesting.

A one-year subscription (four issues) is $34.95.  I'm ordering now...

One of the reasons I started this diary was to document things that I'd found so that I don't have to go searching for them again.  If somebody else finds them useful, that's just a bonus.  Sometimes in the heat of finding and implementing a solution I forget to make a note and post it here.

I do a lot of work at the Windows command line, especially on the computer that I use to build release versions of the project.  When I set it up, I had to go searching for the magic incantations that would enable file name and path name completion on the command line.  I made the required changes and went on my merry way.  I hate it when I do that.  I set up another test machine a couple of months ago and couldn't remember the magic.  Since I don't use that machine much, I just let it slide.  Until the other day when I got fed up.

To enable file name and path name completion on the command line:

  1. Start RegEdit
  2. Navigate to HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor
  3. Set the CompletionChar value (add it as a REG_DWORD if it's not already there) to the value of the control key (in hexadecimal) that you want to use for file name completion.  I like using the Tab character, value 09.
  4. Set the PathCompletionChar value (add it as a REG_DWORD if it's not already there) to the value of the control key (in hexadecimal) that you want to use for path name completion.  I set this to Tab (value 09), too.
  5. Close RegEdit
  6. Start a new command window.  This change won't affect any command windows that were open before you made the registry changes.
  7. Change directories to the root of the C:\drive.
  8. Type "dir win" (without the quotes) and then hit the Tab key.  It should expand to dir "WINNT" or "dir Windows", depending on the name of your Windows directory.

Path and file name completion appears to be on by default in Windows XP Pro.  The odd thing is that the registry values are set to 0x40, but the Tab key still works.  In fact, no matter what values I use for these two settings, the Tab key still performs file and path name completion.  The values you set will work, too.  For example, if I set the PathCompletionChar value to 0x10 (Ctrl+P), then pressing Ctrl+P will complete the path, but so will pressing Tab.

Friday, 02 December, 2005

Web Site Traffic

With other things on my mind in the past few months, I haven't kept a real close eye on my Web site statistics.  Perusing them today reveals some interesting things, and one puzzle.

Visits to my site rose quickly last spring, to a high of about 5,500 unique visitors in April, and then dropped quickly to 3,900 in May.  This drop corresponded with a huge decrease in the amount of referral log spam that I was receiving.

Visits in June were about the same as in May, but then it spiked again in July:  5,800 unique visitors.  August and September were about the same, and October came in with a whopping 9,932 unique visitors.  November was down to 7,000, but that's still way more than my average over the past two years.  And I don't know where they're coming from!  I still get a little bit of referral log spam, but nothing at all like what I was getting last spring.

Web browser traffic has been pretty steady over the months with Microsoft Internet Explorer usually right around 70 percent, Firefox in the 13 to 15 percent range, and a scattering of others including "Unknown" right around 10 percent.  That's probably not an indication of the entire Internet, but rather just this one site.

I was surprised to see that "emotional vampires" has placed in the top 10 search terms since I posted this entry in August.  Unsurprisingly, I'm not the only person to have come up with the term.  Psychologist Albert J. Bernstein has a book, Emotional Vampires: Dealing with People Who Drain You Dry.  Looks interesting.  I haven't read it.

Other notable search terms:

  • People are still looking for nude pictures of Ham So-Won, and wondering what "foxtrot uniform charlie kilo" means.
  • My monthly Random Notes archives contain a lot of words and as a result I get some odd hits from time to time.  One of the oddest recently is "email contact of fishermen captain's and people working in ocean".
  • I don't know why somebody was searching for "jim's buggy parts," but if you find a replacement for my left shoulder, please let me know.
  • "mexican illegal alien catapult" has to be a joke.  Right?
  • I suspect that whoever searched for "budgeting guncash" actually meant GnuCash, but it was amusing to wonder if he was selling guns or attempting to gain income at the point of a gun.
  • To the person who asked, "How do I clean a smoker's car?"  My advice is, "burn it."

Okay, so the search terms haven't been terribly funny lately.

Thursday, 01 December, 2005

Fun with Platform Invoke

About a year ago I wrote a series of three articles about using .CAB files from .NET programs.  The last article, Creating an Object-Oriented Interface to CAB Files (that article contains links to the first two), presented a .NET class library that programmers could use to read and write CAB files from within their .NET programs.  The article has been reasonably popular, I hear, and the code for the article gets about 100 downloads a month from my site.

I'm almost embarrassed to say that the code, as presented in the article, is unstable and probably unusable in a production environment.  I submitted it to what I thought was rigorous testing here by decompressing and re-compressing a rather large cabinet file from the Windows distribution media.  That all worked fine, but I apparently didn't test enough.  In the past year I've had many messages from people who have had problems with the code.

I fixed the major problem several months ago after a helpful reader sent me some information.  The fixed code is available for download at http://www.mischel.com/pubs/cabdotnet4.zip.  That fixes the error that most people were asking about (a System.NullPointerException during FdiCopy or FdiAddFile).  I neglected to take into account that the garbage collector would collect the delegates that I'd passed to FdiCreate or FciCreate.  The solution was to create private member variables to hold the delegates so that there was always a managed reference.  Problem solved.  I thought.

Recently, another reader contacted me about a different issue that occurred comparitively infrequently.  It was another System.NullPointerException, but we couldn't figure out what was causing it.  Running the program with ClrSpy looking at it didn't reveal anything, and no amount of setting breakpoints or other debugger tricks would identify the problem.  I had to resort to that tried and true (cough, cough) method of just poking at it until it worked.  That is, in the process of changing things so that maybe I could reveal the problem, the problem went away.  I "fixed" it, and I don't know how.

I think the problem was that the garbage collector was moving a managed structure around in memory while the unmanaged code had a reference to it.  When the managed code then tried to access the structure at its previous location, the system threw an exception.  The trouble is, I can't prove that was the error, and there is some evidence that that couldn't have been.  Furthermore, I can't prove that whatever I did solved the problem.  It's possible that I just made the problem's occurrence less common.

All of which leads me to my point:  you can't fix a problem if you don't know what's causing it.  You can maybe cure a symptom, but unless you can identify the cause you have absolutely no way of knowing for sure that you fixed it.  All the testing in the world can only reveal that the problem hasn't occurred in the situations that you've tested.

So now I'm left with the somewhat curious task of backing out the changes I made to the code in order to see if I can make the problem reappear.  That is, rather than poking at it until it works, I'm going to poke at it until it breaks.  If I can keep my incremental changes small enough, that should at least give me some idea of where the problem lies.  But there are serious problems with this approach.

The bug I'm trying to locate just happens sometimes.  Pretty infrequently, in fact.  I have a test suite that can make it happen, but it involves trying to decompress a large number of files and takes quite some time to run.  The bug would appear, on average, about once every other run, but I sat through three or four successful runs in a row before it appeared.  So let's assume that I make a change and run the test.  How many times do I run the test before I decide that the change I made had no effect on the bug?  Once?  Three times?  Ten?

Assuming that I come up with an answer to the first question, the next question is possibly worse:  how do I know if the change I made is the actual cause, or just the thing that makes the real cause show a symptom.  That is, it's possible that the cause of the bug isn't just one thing, but rather a combination of two or more seemingly unrelated things.  There's absolutely no way of knowing.

This is a fundamental problem with executing in a managed environment.  I can see pretty much everything that's going on inside the managed code and I can even single-step into the unmanaged (i.e. native) code with the debugger.  I can even step through the edges--the marshaling of data across the managed/unmanaged line.  What I can't do (or haven't yet figured out how to do) is peek at the garbage collector to see if it's pulling the rug out from under me.