Installers, COM and Legacy

I’ve used a variety of installers over the past few years while doing Windows Client development.  InstallShield, Nullsoft Installer, Caphyon’s Advanced Installer and last, but not least, Visual Studio Setup/Deployment projects.

They’re all intended to shield the developer from the innards of Windows Installer (or the custom installer technology).  With varying degrees of success they make it easy to create the typical interaction between the user and the computer during an application install.  Or at least that’s the idea.

Try as they might, these installers can’t entirely shield you from the underlying components, tables, properties, binary files and obscenely verbose MSI logs that are the world of the Windows Installer.

One such case has bedeviled a recent project as it relates to COM components.  Whilst most of the codebase is managed code a few components (including a critical one) are still packaged as COM libraries.  Registration-free COM, as I describe in an earlier post, relieves us of the perils of system-wide, centrally registered libraries that get installed and reinstalled by separate, not-necessarily cooperating applications.

However, one of the libraries is a 3rd party library that gets installed (and uninstalled) with several different applications.  This is a problem because these applications are not always installed/uninstalled at the same time.  They’re also versioned independently.  In every case that I’ve seen installers will uninstall COM libraries when an application is uninstalled.  This breaks every other application on the machine that depends on that COM library.

It turns out that the way to prevent application A from breaking application B when application A is uninstalled (and the shared COM library is uninstalled along with it) is to mark the COM library as a Shared, Reference Counted DLL.

No matter the installer this feature is controlled by a property taken directly from the guts of Windows Installer: msidbComponentAttributesSharedDllRefCount.  This bit field determines whether or not Windows Installer will uninstall the DLL when the application is uninstalled.

The classical problem with using reference counting to track “liveness” (when a component is still in use) is the problem of circular references.  If Components A and B depend on each other then they can never be removed entirely because their reference counts can’t be reduced to zero until they’re both zero.  Fortunately this scenario hasn’t reared its head.  When it does I’ll be sure to post.

HOSTs, CNAMEs, SRVs Oh My!

DNS is a bit of an undiscovered country for me.  I’ve never had to set up a zone file.  As far as I know I’ve never even configured BIND (though it might have been configured on a linux distro by default).

Exchange 2007 introduced this wonderful thing called Autodiscover.  It is what it sounds like, a discovery service that Outlook 2007 clients can use to get information about exchange.

It works out-of-the box (mostly) if you’re hosting exchange yourself and your users are on a domain.

Getting it to work when you’re neither on a domain nor hosting exchange yourself is a bit of a bear involving, potentially, CNAMEs, SSL certificates, http redirection and, lastly, SRV records.

Outlook 2007 makes educated guesses about where it can access Autodiscover.  Unfortunately one of those guesses results in a persistent Security Warning if you’ve gone the CNAME route and your CNAME points to someone else’s (your mail hosting service) domain.

The recommended way (after applying this hotfix) to deal with this is to create an SRV record, a kind of specialized DNS entry pointing to the real Autodiscover service.  If you’re lucky enough to be handling DNS on a Windows box then there’s a handy GUI that makes setting up the SRV record a snap.

If you’re unlucky enough to have to use a paper-thin Web-based interface on top of DNS zone files then you, like me, get the joy of experiencing an anachronistic, extremely sparse configuration syntax (think sendmail.conf) that will choke on the slightest grammatical variation (e.g., forgot to end the host, which is actually a domain, with an extra .?  Clearly you weren’t thinking that would fly even though in every other context a trailing . on a domain name will *break* the request…).

What’s more, since DNS is a decentralized confederation every change you make takes a while to make its way through the system.  And while you can trick nslookup into using the nameservers where you made the change (surely they’d be up to date, right?), it’s about the only software you can trick into doing that – making it useless for any end-to-end testing.

The Programmer’s Abridged Guide for Investigating Errors

Consider the following sources in order:

  1. You probably screwed up.  This is the most likely cause.
  2. The library author screwed up.  The is less likely than a personal screw up but more likely than subsequent sources of error.
  3. Microsoft screwed up.  This is even less likely than the library author screwing up but more likely than the last source of error.
  4. Intel (or AMD) screwed up.  This is the least likely source of error and is only to be considered when all else fails (or you’ve run out of time and need someone to blame!).

As with any guide, YMMV.  Best taken with a grain or two of salt :)

Why Extension Methods?

Extension Methods, introduced in the C#3.0, provide a way to add a method to an existing type without having access to the source code of that type.

Although Extension Methods were added to support LINQ (a MOST awesome innovation) if you use generics (introduced in C#2.0) to create strongly typed collections and find yourself storing these strongly typed collections as strings in a file then Extension Methods provide a very natural way to extend the strongly typed collection.

For example, take List<MyCustomClass>.  If this gets stored in a file, say as name=value pairs, then it would be great to be able to parse the contents of that file simply by calling List<MyCustomClass>.Parse(fileContentsAsString).

Unfortunately, unless you’re at Microsoft (or Novell ala Mono) you probably don’t have the source code to the generic List type.  Even if you do have access to the source code you can’t anticipate all of the specific types users will create or the way they will represent them as a strings.

Enter Extension Methods.  They provide a way to extend List<MyCustomClass> (and, more generally, any type including generic types like List<T>).  So you can add a Parse(string) method to go from string form to List<MyCustomClass> form.  You can also add a ToString() method to go from a List<MyCustomClass> to a string.

The only peculiarity I’ve found so far is that the Extension Method must be invoked on an instance of the type even though they’re defined as static methods of a static class.  Not sure why the language designers chose to go this way but I’m sure there’s guidance on this out there somewhere.

Triple Monitor LCD Desk Stand

I’ve gotta tip my hat to Ergotech.  They’ve managed to make a Triple LCD Desk Stand (model 100-D16-B03) that’s easy to put together, adjust, mount and dismount. 

I opted for the three-way horizontal configuration over the four-way two-tiered configuration to minimize eye strain.

triple monitor lcd desk stand

VS2008 – Online Help finally useful!

After installing Visual Studio 2008 I usually turn off 2 help options: “Partial Matching” and “Online Help”.

“Partial Matching” because it returns way too many results.

“Online Help” because it slows down searches.

While searching for the syntax to check a VARIANT_BOOL, I decided to give it a try.  Lo and Behold, the Online Help returned something useful!  Looks like specifications showing up on MSDN library might not be a bad thing after all…

variant_bool