When a good application won’t leave (or the brother-in-law app)

Filed under Uncategorized

I have an InstallShield-authored MSI installation for an application I work on.

In testing one of the recent interations, I ran into a peculiar problem.

It installed perfectly fine, and after an uninstall, virtually everything was removed properly, except for one particular component.

It didn’t go away.

I turned verbose MSI logging on (see here for details how), and reran the install/uninstall.

For the install, somewhere toward the top of the log, you should see a block that looks like this:

MSI (s) (9C:D8) [16:43:17:376]: Feature: Some Feature; Installed: Absent;   Request: Local;   Action: Local
MSI (s) (9C:D8) [16:43:17:376]: Feature: Some other feature; Installed: Absent;   Request: Local;   Action: Local
MSI (s) (9C:D8) [16:43:17:376]: Component: InstallMSXML6; Installed: Absent;   Request: Null;   Action: Null
MSI (s) (9C:D8) [16:43:17:376]: Component: InstallSQLSMO; Installed: Absent;   Request: Null;   Action: Null

Notice the Installed state is absent and the action is local, meaning that the feature/component doesn’t already exist on the machine and it’s going to be installed locally (the normal installation type).

After an uninstall, the log will contain a similar block, but just reversed:

MSI (s) (9C:B8) [17:00:19:887]: Feature: Some Feature; Installed: Local;   Request: Absent;   Action: Absent
MSI (s) (9C:B8) [17:00:19:887]: Feature: Some Other feature; Installed: Local;   Request: Absent;   Action: Absent
MSI (s) (9C:B8) [17:00:19:887]: Component: InstallMSXML6; Installed: Absent;   Request: Null;   Action: Null
MSI (s) (9C:B8) [17:00:19:887]: Component: InstallSQLSMO; Installed: Absent;   Request: Null;   Action: Null

Note the Installed state of Local but the action is now absent (at least on the two features noted above).

However, my problem component looked like this

MSI (s) (9C:B8) [17:00:19:887]: Component: ProblemComponent; Installed: Local;   Request: Absent;   Action: Null

And what stumped me was, why a null action? The Request was absent, so why wasn’t the action?

I researched the problem a little and got nowhere, then tried tweaking the install several different ways; still no joy.

I finally broke down and put a call into Macrovision. Ended up talking to one of their guys (Thanks, Cary!) and the first thing he asked was, “Search for Disallow” in the log starting at the top and see if there’s anything mentioned.”

Ok. And sure enough, I had several lines like this.

MSI (s) (9C:B8) [17:00:19:626]: Disallowing uninstallation of component: {997FA962-E067-41D1-9396-00A0C90F27F9} since another client exists

After a little GUID spelunking (you can find GUIDs easily in InstallShield by opening the direct editor

image

clicking on the component table and sorting by the component ID)

image

I was able to determine that the problem component, was indeed one of those whose uninstallation was disallowed.

(You might see a number of “Disallowing” lines in your log, often as a result of including Merge modules of standard libraries, like the COM libraries or the VB runtime files, so you have to just ignore them).

So I figured, just search the registry for the GUID in question and remove whatever junk was left over, probably from an aborted install.

No dice. The component information used to track reference counting (which is how MSI knows to “disallow uninstallation since another client exists”) is locked up in a binary registry entry, from what I can tell.

In the end, you’ll generally have two options.

  1. Change the Component GUID. Only do this if you know that component won’t need the same GUID (for upgrading in later releases, for instance).
  2. Pave your test machine or try the install on a different machine.

Not fun, but not too bad.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*