Google today released (after a bit of a comic-book pre-release, presumably due to the Labor Day holiday in the US) Google Chrome, its long-rumored open-source browser. Plenty of people will talk (endlessly) about the implications of another browser and how well Google Chrome and Chromium (the open source project) do the job. Blah, blah. Whatever. What’s really interesting is a couple of choices Google made about deployment:

  1. The Google Chrome download is a svelte 474K bootstrapper that downloads the setup bits. No offline installer is available (unless it’s well-hidden).
  2. Google Chrome is a "composite" setup: The guts of the application are installed by a non-MSI self-extractor. However, Google Chrome includes Google Gears, the browser add-in/library that adds a bunch of functionality for making apps-in-the-browser more powerful. The Gears in Google Chrome is installed by an MSI package. And yes, it’s built with WiX.
  3. The Google Updater is no longer a LocalSystem service; instead, it starts at logon from the HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run registry key.
  4. Last and absolutely not least: Google Chrome is a per-user application. It even installs in the per-user LocalAppDataFolder. (The included Google Gears is marked as "UAC compliant.")

That Google Chrome is a per-user app is amazing. Even with UAC on Windows Vista and Windows Server 2008, it’s so easy to say that "everyone’s used to needing admin privileges to install." That Google took the extra effort to limit themselves to the capabilities of a per-user app says a lot about their desire to have:

  • a low-impact setup
  • and absolutely no barriers to entry.

I wonder if it’s the start of a trend…

Posted in Windows Installer at September 2nd, 2008. 10 Comments.

When you include deferred custom actions — that somehow modify the machine — in your setup, you have two big responsibilities:

  1. Provide rollback custom actions that "undo" what the deferred CAs do so that the installation transaction is actually transactional.
  2. Test.
  3. Test.
  4. Test.

OK, so numbers 2 through 4 are kinda the same but not really: Even a simple installation (say, without patching or upgrades) has three different scenarios you need to test when you have deferred/rollback custom actions:

  1. Installation rollback.
  2. Repair rollback.
  3. Uninstallation rollback.
  4. All of the above.

The right behavior for each kind of rollback is usually the opposite action. Rolling back installation is uninstallation. Rolling back uninstallation is installation. Rolling back repair is usually installation. Mixing installation, repair, and uninstallation is possible if your package has user-selectable features and users go into maintenance mode to turn on and off features. And, of course, it’s always an option from the msiexec.exe command line using the ADDLOCAL/ADDSOURCE/ADDDEFAULT, REMOVE, and REINSTALL properties.

Testing rollback means testing failure

Windows Installer initiates rollback when an action fails, so to test rollback you need to cause a failure. WiX includes an easy way to trigger failure: The WixFailWhenDeferred custom action, part of WixUtilExtension, triggers a failure when it’s executed. Include it in your package by referencing WixUtilExtension (in your Votive .wixproj or via the -ext switch to the light.exe command line) and adding a CustomActionRef to your package authoring:

<CustomActionRef Id="WixFailWhenDeferred" />

WixFailWhenDeferred automatically schedules itself in InstallExecuteSequence before InstallFinalize, with a condition of:

WIXFAILWHENDEFERRED=1

The condition means that you can have one package to test all the different possible combinations of "normal" installation and rollback. Just pass the WIXFAILWHENDEFERRED=1 property value on the msiexec.exe command line to trigger rollback. For example:

msiexec /qb- /i intermediate.msi /L*vx installfail.log WIXFAILWHENDEFERRED=1
msiexec /qb- /i intermediate.msi /L*vx install.log
msiexec /qb- /fvamus intermediate.msi /L*vx repairfail.log WIXFAILWHENDEFERRED=1
msiexec /qb- /fvamus intermediate.msi /L*vx repair.log
msiexec /qb- /x intermediate.msi /L*vx uninstallfail.log WIXFAILWHENDEFERRED=1
msiexec /qb- /x intermediate.msi /L*vx uninstall.log

WixFailWhenDeferred has been in WiX v3 weekly releases since April.

Posted in WiX, Windows Installer at June 18th, 2008. 5 Comments.

As I mentioned previously, one of my favorite examples of a tight, clean Windows Installer package for a real product–VirtualBox–succumbed to a dreaded VBScript custom action when they released v1.6.0. Predictably, it caused errors (during uninstallation, because this custom action ran during uninstall only).

VirtualBox 1.6.2 dropped that custom action. The VirtualBox installers still have a few ICE errors and warnings so here’s hoping the VirtualBox team continues cleaning those up.

Posted in Windows Installer at June 13th, 2008. No Comments.

There’ve been a couple of reports that WiX v3.0.4123 doesn’t include mergemod.dll. That’s unfortunate because it’s a really annoying bug and worse, I was the last one to touch mergemod.dll (to fix 1965131) so it was probably my fault.

I couldn’t reproduce the problem, however; mergemod.dll was present in Wix3.msi, Wix3_x64.msi, and wix3-binaries.zip. I was about to ask for install logs to investigate when a likely cause occurred to me. The bug fix was to revert from a version of mergemod.dll with a bug to a prior one that doesn’t have the bug. Unfortunately, downgrading files is problematic with major upgrades: Windows Installer wants very much to keep higher-versioned files around. After all, the latest version probably has all the latest bug fixes, right?

If you install WiX v3.0.4123 over v3.0.4116, the log will contain a line like this:

MSI (c) (34:D4) [10:47:26:734]: Disallowing installation of component: {AAF02F71-9684-4F4F-8EEA-FC99A61EAA9A} since the same component with higher versioned keyfile exists

Simple workaround: Uninstall the earlier version of WiX, then install v3.0.4123.

Posted in WiX, Windows Installer at May 27th, 2008. 3 Comments.

The WiX installer had a bug that I noticed during our transition from Visual Studio 2005 to Visual Studio 2008. If you had the Votive feature installed for VS2005 and VS2008, then uninstalled VS2005, the Votive feature was "orphaned" and couldn’t be uninstalled. The cause is that the Votive features are enabled only when the corresponding version of Visual Studio is installed. (The Feature/@Level attribute is 0 with a Condition child element to enable it.) MSI sees the feature as disabled in maintenance mode and won’t remove it.

Oops.

The solution is easy, though: Add OR REMOVE to the condition that enables the feature. That ensures the feature is enabled during whole-product uninstall or an attempt to remove that particular feature.

Posted in WiX, Windows Installer at May 16th, 2008. 2 Comments.

VirtualBox, the desktop virtualization product acquired by Sun Microsystems in February, shipped version 1.6.0 on Friday. I previously mentioned VirtualBox in my blog post on setup testing with virtual machines. I lauded their clean setup and low custom-action count.

Unfortunately, the latest version hasn’t kept up that standard of Setup Goodness™.

The x64 package isn’t marked with the x64 platform template. I suspect that was intentional, as it allows the package to be opened and then canceled with a more friendly error message than the stock message Windows Installer provides. Nonetheless, it throws a bunch of ICE errors because MSI treats the package as 32-bit.

They also added a custom action: ActionRemoveDataFiles. Nothing to get too worked up about, but it’s like they tried to cram into one CA all the possible wrong things you can do with CAs:

  1. It’s VBScript. Evil. One day after release, a user started a thread on the VirtualBox support forum about getting a 2738 error on Windows Vista.
  2. It’s an immediate CA that modifies machine state.
  3. As an immediate CA, it runs impersonating the installing user, so attempts to delete files outside that user’s profile will fail unless the user started the setup as an administrator.
  4. It doesn’t have a “matching” rollback CA to undo what it does.
  5. It tries to “clean up” user data — including the virtual machine and disk configuration.
  6. It tries to clean up all users’ data, even those who aren’t logged in. That’s going to fail for roaming profiles, because the MSI server doesn’t have permissions to the remote data.
  7. It’s scheduled in InstallExecuteSequence but shows message boxes to prompt the user for permission to clean up files. CAs scheduled in InstallExecuteSequence should never show UI; all UI should be handled via CAs scheduled in InstallUISequence or via dialog boxes in the Back/Next wizard sequence.
  8. The CA’s condition in InstallExecuteSequence uses “UILevel>2″ presumably so the message boxes are shown when the user uninstalls VirtualBox from Add/Remove Programs (Programs and Features on Vista). Unfortunately, it violates the contract MSI provides for “basic UI” mode. Using the /qb or /passive switches is commonly used in automated installations to show modeless progress UI without ever showing a modal prompt. ActionRemoveDataFiles will show modal UI during any uninstall other than with the /silent or /qn switches.
    To be fair, the shell folks who designed ARP and the MSI folks are partially responsible: They didn’t provide a UI level that says “I’m uninstalling interactively from ARP, so it’s OK to show some modal UI.”

Worst of all: This particular custom action makes it way too easy to delete gigabytes of virtual machine configuration and drives with no more than an accidental Yes button click. <shudder/>

Posted in Windows Installer at May 5th, 2008. 5 Comments.

Raymond Chen, famous Windows shell ninja, suggests today in his blog that the “action” button in a setup wizard, should be labeled Next instead of Finish. While I wholeheartedly agree that Finish is a bad label for the button that kicks off the actual installation process, Next has its own problems. In WixUI, each installation action gets its own label: Install, Change, Remove, Repair. Buttons labeled Next are reserved for pages that lead to more options.

Raymond can undoubtedly call upon legions of minions to punish me for my heresy, but I think the current WixUI model is better because it’s more explicit. And it means you can “page surf” to your heart’s content as long as you see Back and Next buttons.

Posted in Windows Installer at April 22nd, 2008. 2 Comments.

Google announced the release of Google Earth 4.3 today. Given the recent release of their WiX-based setup for the Google App Engine SDK, I had to give it a shot. (It helps that my day job also deals with 3-D terrain imagery.)

When you click the link to “Download Google Earth 4.3” (and accept the EULA), you download not Google Earth but “Google Updater.exe.” Run it and it starts downloading the Google Earth installer.

Personally, I much prefer to download the actual installers for the software I use. Some of it’s purely practical: I can stick it on a network and put it on multiple computers (EULA permitting, of course) without waiting for multiple downloads. Perhaps more importantly, for the paranoid among us, is the ability to virus-scan the installers. (Google Updater requests elevation, so it has admin rights to install multiple packages.)

Google Updater also runs as a startup app, optionally showing an icon in the increasingly-unusable system tray. (Yes, I know it’s technically the “notification area,” but come on, who calls it that?) I don’t think I need 24/7 instant access to software that doesn’t get updated that often. In fact, I’m sure I don’t.

Naturally, installing a packaging system with update capabilities is a boon to many users (and Google itself, of course, which has a nicely visible entry point to suggest additional apps for download). Apple does it with iTunes and Microsoft does it with Windows Live. Luckily, Google Updater has its own entry in Add/Remove Programs so you can remove it without impact to Google Earth.

Google Earth installer

The Google Earth installer is built with InstallShield, using its support for “dynamic file linking.” (If you haven’t used it, think of running Heat or Tallow with every build.) Interestingly, it uses the CAQuietExec custom action from WiX and has wixca.dll in the Binary table.

The .msi package fails ICE validation, with errors in ICE03, ICE15, ICE34, ICE38, ICE43, ICE44, ICE57, ICE64, and ICE99, and warnings in ICE45, ICE60, ICE82, ICE86, and ICE91.

There are 36 custom actions, some of which are mildly disturbing:

  • registerFlashSOL is a deferred, no-impersonate custom action that runs an included .exe with a “-install” command-line switch. Oh joy: self-reg.
  • InstallToolBarCA is an immediate custom action that runs an installed .exe. It’s not scheduled and is only available from the UI sequence – the one that’s suppressed because Google Updater runs the installation silently.
  • SetGEUserStats is another custom action run only from the suppressed – but still included – UI sequence.
  • SET_RES_READ_ONLY sets QtExecCmdLine to run the WiX CAQuietExec custom action. What is it hiding? It’s running attrib.exe to turn off the read-only attribute on a recursive set of files/directories. Doesn’t the File table let you control the read-only attribute? Yes, it does, but apparently not when you use InstallShield’s dynamic file linking to harvest a directory tree at build time. In a previous life, I used that functionality and turned off the read-only attributes in the build script before harvesting. Doing it as part of installation is bad karma on Google’s part.

Overall, it’s not a bad installer, but I hope Google cleans it up a bit before it loses the “beta” label.

Posted in Windows Installer at April 16th, 2008. 5 Comments.

MSI has some funky syntax to support checking the action state (what MSI is planning to do during the current install transaction) and install state (what MSI already did, in a previous install transaction) of both features and components. See Conditional Statement Syntax for the details and Examples of Conditional Statement Syntax for some examples. (As an aside, would it have been too much to ask to avoid the Perl-like prefix characters and have something function-like such as FeatureActionState(featureId)?)

A couple of people on the wix-users mailing list have asked about using the feature action state in component conditions. There’s good news and bad news.

Good news for simple cases

The good news is that in simple cases with simple conditions, there’s probably another way to get the behavior you’re looking for. For example, one component can be assigned to multiple features, so if you’re trying to install a component when any of several features are being installed, just reference the component in all the features. MSI will install the component once, regardless of how many features reference it.

The bad news

If you want to conditionalize a component based on whether a particular feature is being installed (i.e., its action state), you can’t rely solely on the component’s condition. The Component Table doc has this to say:

The Condition field enables or disables a component only during the CostFinalize action. To enable or disable a component after CostFinalize, you must use a custom action or the DoAction ControlEvent to call MsiSetComponentState.

The CostFinalize action doc says:

The CostFinalize action queries the Condition table to determine which features are scheduled to be installed. Costing is done for each component in the Component table.

Unfortunately, it doesn’t state explicitly that the order of the two sentences is the order of execution. But, even if it did, there’s this table in Conditional Statement Syntax:

Feature and Component State Values

The following table shows where it is valid to use the feature and component operator symbols.

Operator <state> Where this syntax is valid
$component-action In the Condition table, and in the sequence tables, after the CostFinalize action.
&feature-action In the Condition table, and in the sequence tables, after the CostFinalize action.
!feature-state In the Condition table, and in the sequence tables, after the CostFinalize action.
?component-state In the Condition table, and in the sequence tables, after the CostFinalize action.

So there are two fairly explicit strikes against being able to use a feature action state in a component condition:

  • Conditional Statement Syntax doesn’t list the Component table as a valid place to use the &feature-action syntax.
  • It says the syntax is valid only after CostFinalize but according to Component Table, that’s too late to use the component condition to enable/disable the component.

The Component Table says to use a “custom action or the DoAction ControlEvent to call MsiSetComponentState.” I haven’t quite deciphered whether the doc is saying to use DoAction to call a custom action from the UI or whether there’s a special, secret way of calling MsiSetComponentState via DoAction. If it’s the latter, I’m not aware of it (hence “special, secret”).

Here be dragons

Having been a writer for many years, I try to be nice about doc that is correct, even if in retrospect it’s not as helpful as it could have been. So here’s me being nice. The following sentence from Component Table easily leads a trusting reader down the wrong path:

The Condition column in the Component table accepts conditional expressions containing references to the installed states of features and components.

So here we have a sentence that contradicts the table in Conditional Statement Syntax and it’s really easy to misread the “installed state[s]” as “action states.” At the very least, it deserves clarification.

Posted in Windows Installer at April 9th, 2008. No Comments.

Reggie Burnett, creator and developer of MySQL’s Connector/NET ADO.NET provider, announced an alpha release of the MySQL Connector/NET. Among the new features:

Perfmon counters are now created using Wix code instead of a managed custom action. This seems to help the problem where some installation were failing becausing of being unable to register the counters.

Great job! Now, about the two remaining managed custom actions and the H2Reg CAs that don’t have rollback…

Posted in Windows Installer at February 11th, 2008. No Comments.