VirtualBox 1.6.0 setup another example of the second law of thermodynamics

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/>

Windows Installer

Comments (2)

Permalink

RFC: Vitality

The msidbFileAttributesVital File attribute bit says to Windows Installer that the file is vital to the operation of the installation and if it can’t be installed, the installation should fail. In an installation showing user interface, if a file can’t be installed, MSI shows a dialog box to let the user retry, ignore, or cancel the install. If a file is marked vital, however, the ignore option is taken away.

Generally, if a file can’t be installed, it’s bad news; most apps don’t react well to missing files. You might wonder why it’s not the default. Yeah, well, join the club. Unfortunately, it’s not the default and if you want "file vitality" in WiX, you need to set the Vital attribute to "yes" on every File element.

Providing better defaults is part of our ongoing attempts to make the WiX language easier to use and understand. Unfortunately, simply making Vital="yes" the default would be a change in behavior. Granted, it’s a good change in behavior but we’re at a point in WiX v3 development and use where we generally avoid changes in behavior.

A minor new feature I added to WiX in the latest weekly release is the ability to indicate that all files should have the msidbFileAttributesVital bit set by default. If you use MSBuild projects, the FilesVitalByDefault property can be set for the whole project. If you use Candle directly, you have to specify -fdvital on every Candle command line invocation.

An alternative would be to reverse it: Set the msidbFileAttributesVital bit by default and let you turn off that behavior with another command-line switch or MSBuild property.

So we’re looking for feedback. Would it be disruptive to your use of WiX v3 to have the msidbFileAttributesVital bit set by default? Would it be preferable to using the new -fdvital switch or FilesVitalByDefault property?

Please post your votes/comments/questions/criticisms/concerns/praise here or via mail to the wix-users mailing list.

WiX

Comments (5)

Permalink

Highlights of WiX v3.0.4102.0

WiX v3.0.4102.0 was released on Friday, 02-May-08. You can download it from http://wix.sourceforge.net/releases/3.0.4102.0/.

New features

  • The assembly version numbers of assemblies like wix.dll are now “locked” at 3.0.0.0. Doing so lets anybody build a WiX extension for WiX v3 without having to rebuild it every time a new build of WiX is released. The file versions will continue to be updated with the build number in the third field.
  • Added -fdvital switch to Candle and FilesVitalByDefault property to wix.targets to specify that all files should get their msidbFileAttributesVital bit set by default.
  • 1908965

Bug fixes

  • Lots of minor features, tweaks, and bug fixes in Votive.
  • The Votive features in Wix3.msi can now be uninstalled if you first uninstall the corresponding version of Visual Studio. Previously, they’d be left behind even during a major upgrade or complete uninstall. This was caused by an overly aggressive feature condition.
  • 1603124
  • 1839779
  • 1879305
  • 1904861
  • 1905383
  • 1951034

WiX

Comments (3)

Permalink

Highlights of WiX v3.0.4025.0

WiX v3.0.4025.0 was released on Friday, 25-Apr-08. You can download it from http://wix.sourceforge.net/releases/3.0.4025.0/.

New features

  • Tweaks to the build system continue. The bin/wixenv.bat file sets up the environment for building WiX, including setting the path to include NAnt and Visual C++.
  • If you want to build WiX without using bin/wixenv.bat, you can do so now by setting one environment variable (down from several). Set WIX_ROOT to the root of the src directory.
  • With a version of Visual Studio 2008 that supports it — Team System Development Edition or Team Suite — you can run "Code Analysis for C/C++," also known as PREfast. From make.bat, use the prefast option. If you want to run NAnt directly, specify -D:codeanalysis=prefast.
  • In a somewhat ironic twist, the strsafe.h header for safer string functions is incompatible with code analysis, so I wrapped strsafe.h with a header that disables the warnings code analysis emits.
  • WcaAddTempRecord now takes an optional argument to retrieve the error code if inserting the temporary row fails.
  • The new WixGamingExtension for registering games in Windows Vista’s Game Explorer.
  • BinderFileManager is the new name for the extensibility point in the binder for customizing how WiX resolves files.
  • Multiple BinderExtension objects are now supported.
  • WixUI localization string sets for French, Italian, Japanese, Polish, and Russian are now included.

Bug fixes

  • The InternetShortcut extension and custom action had a bug that the directory they were to be created in wouldn’t be automatically created. Added the code to create them if needed using temporary rows in the CreateFolder table.
  • To support Visual C++ 2008 projects, we took a dependency on MSBuild 3.5. The former was intentional; the latter was not. For an immediate workaround, so you can run WiX tools on .NET 2.0, we reverted to MSBuild 2.0 dependencies. The downside is that the MSBuild targets no longer support references to Visual C++ 2008 projects. We’re working on a long-term fix.
  • 1947028
  • 1947549
  • 1948860

WiX

Comments (1)

Permalink

New WiX feature: Gaming extension

The Game Explorer is a new feature in Windows Vista to collect and richly present installed games. Game Explorer is a shell folder that includes detailed information about each game, including box art, content ratings (and parental-control restrictions based on them), and performance requirements (using the Vista performance rating system).

Most of the details shown in Game Explorer come from the game developer in the form of the Game Definition File (GDF) that’s embedded as a resource in your executable. Details and samples on the GDF and Game Explorer are available in the DirectX SDK, especially in Getting Started with Game Explorer.

The WiX Gaming extension is a compiler extension with custom actions to do the following:

  • Register a game in Game Explorer.
  • Create tasks in the context menu of a game in Game Explorer.
  • Register a game on Windows XP so it’s available in Game Explorer after an upgrade to Windows Vista.
  • Register extensions with support for the rich saved-game preview handler.

[Update: WixGamingExtension will be available in the next weekly release of WiX v3.]

Registering games

To register a game, add a Game element and specify its instance ID in its Id attribute as a child of the File element for the game executable. For example:

<File Id=”MyGameExeFile” Name=”passenger_simulator.exe” KeyPath=”yes”>
<gaming:Game Id=”985D5FD3-FC40-4CE9-9EE5-F2AAAB959230″>

The DirectX SDK suggests letting the Game Explorer COM object create a new GUID for every installation. It then suggests writing the new GUID to the registry or file system to persist it or to use WMI to query Game Explorer for the GUID. The prior release of Flight Simulator used WMI, which was a fairly regular source of failures during uninstall and repair operations. Following the mantra of minimizing runtime dependencies during setup, I chose to let the setup author specify a static ID. No persistence or runtime dependencies required.

Creating tasks

Game Explorer tasks are simply shortcuts shown on the context menu on the game icon in Game Explorer. Play tasks are plain ol’ shortcuts to the game executable with optional command-line arguments. Support tasks are shortcuts to URLs. The shortcuts must be created in specific directories for Game Explorer to find them.

WixGamingExtension translates strongly-typed PlayTask elements into rows in the Shortcut table; the Name attribute is the name of the shortcut and Arguments are the command-line arguments. WixGamingExtension translates SupportTask elements into WixUtilExtension InternetShortcuts; the Name attribute is the name of the shortcut and Address is the URL.

<File Id=”MyGameExeFile” Name=”passenger_simulator.exe” KeyPath=”yes”>
<gaming:Game Id=”985D5FD3-FC40-4CE9-9EE5-F2AAAB959230″>
<gaming:PlayTask Name=”Play” />
<gaming:PlayTask Name=”Play in Deity Mode” Arguments=”-deity” />
<gaming:SupportTask Name=”Help!” Address=”http://example.com” />
<gaming:SupportTask Name=”Cheat codes” Address=”http://example.com” />
<gaming:SupportTask Name=”Get P0wned” Address=”http://example.com/1337″ />
<gaming:SupportTask Name=”Get owned” Address=”http://example.com/non1337″ />
<gaming:PlayTask Name=”Show no mercy” Arguments=”-cutenfluffy” />
<gaming:SupportTask Name=”Forums” Address=”http://example.com” />
</gaming:Game>

Registering for OS upgrades

When you install a game on Windows XP and later install Windows Vista as an upgrade, the Vista upgrade can automatically register the game in Game Explorer. All that’s required is writing the task shortcuts and a few registry values. WixGamingExtension does that automatically; no extra authoring is required.

Rich saved games

Vista includes a special preview handler for file extensions registered as a saved-game file. Most of the effort required to support rich preview is in the game itself; the burden on setup is just to register the extension for the preview handler. WixGamingExtension supports this registration as a simple yes/no attribute on the standard WiX Extension element:

<ProgId Id=”MyGameProgId”>
<Extension Id=”MyGameSave” gaming:IsRichSavedGame=”yes” />
</ProgId>

Sponsored by ACES

The gaming extension is part of the work I’m undertaking to convert ACES Studio’s products from our old script-based installer to a declarative installer built with WiX. Studio management was pleased to contribute the work to the wider WiX community.

If you happen to publish a cool game that uses WixGamingExtension, feel free to send a copy my way. :-D

WiX

Comments (3)

Permalink

Raymond Chen on setup UI

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.

Windows Installer

Comments (2)

Permalink

Highlights of WiX v3.0.4014.0

It’s been a while since the last “weekly” release. As Rob explained, Mike was working on changes to the build system to support 64-bit builds; we made the changes incrementally, so we could continue working on fixes and features.

WiX v3.0.4014.0 was released on Monday, 14-Apr-08. You can download it from http://wix.sourceforge.net/releases/3.0.4014.0/.

New features

  • WcaUtil, DUtil, and WixCA are now built for x86, x64, and IA64. We’d been able to support 64-bit portions of the file system using WOW64 API functions to suppress the normal redirection that happens for a 32-bit process. Unfortunately, that’s not available for registry operations, so Mike volunteered to bite the bullet and support native 64-bit custom action builds. Hooking the WixCA 64-bit builds into WixUtilExtension will come in a future build.
  • Added WcaGetComponentToDo to WcaUtil to provide a single value to indicate whether a component is being installed, reinstalled, or removed. For many operations, it’s a convenient shorthand instead of calling MsiGetComponentState, WcaIsInstalling, WcaIsUninstalling, and WcaIsReInstalling.
  • Internet shortcuts, as I described before.
  • Added to the OSInfo custom action the ability to determine localized names for well-known SIDs: WIX_ACCOUNT_LOCALSYSTEM, WIX_ACCOUNT_LOCALSERVICE, WIX_ACCOUNT_NETWORKSERVICE, WIX_ACCOUNT_ADMINISTRATORS, WIX_ACCOUNT_USERS, and WIX_ACCOUNT_GUESTS.
  • The command-line tools now support the –wxn switch to promote specific warnings into errors.
  • The MSBuild tasks now support SuppressAllWarnings, SuppressSpecificWarnings, TreatWarningsAsErrors, TreatSpecificWarningsAsErrors, VerboseOutput, and NoLogo properties on all tasks.
  • The command-line tools store their strings in resources for localizability.
  • Added Package/@InstallScope.

Bug fixes

WiX

Comments (0)

Permalink

Google Earth setup experience

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.

Windows Installer

Comments (5)

Permalink

Feature states in component conditions

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.

Windows Installer

Comments (0)

Permalink

New WiX feature: Setting package installation scope

For flexibility at deployment time, MSI uses the value of the ALLUSERS property in determining the type of an installation—whether it’s per-machine or per-user. That lets a network administrator easily control whether the package’s shortcuts (for example) show up for all users or just one. There’s also the it-looks-good-at-first idea of ALLUSERS=2, which theoretically lets a package adapt to either an admin or non-admin user.

Problem is, in the era of UAC, a genuine per-user package wouldn’t require a prompt for elevation. Unfortunately, most “per-user” packages still need admin rights, because they still install to per-machine locations, like ProgramFilesFolder on the file system and HKEY_LOCAL_MACHINE in the registry.

To avoid lots of mysteriously failing packages, MSI 4.0 and later require packages to opt in as not requiring UAC elevation prompts. In WiX, that’s expressed by setting the Package/@InstallPrivileges attribute to limited. Confusingly, the default for ALLUSERS is null, which means to install the package per-user, so to get a per-machine package, you have to remember to instead set ALLUSERS to 1.

It’s easy enough to forget that, so I added the InstallScope attribute to the Package element to centralize the per-machine/per-user choice:

perMachine
Set this value to declare that the package is a per-machine installation and requires elevated privileges to install. Sets the ALLUSERS property to 1.
perUser
Set this value to declare that the package is a per-user installation and does not require elevated privileges to install. Sets the package’s InstallPrivileges attribute to “limited.”

This attribute doesn’t deprecate InstallPrivileges and you can use both (though it’s redundant to do so). If you specify perMachine, you must remove any Property element that sets ALLUSERS.

WiX

Comments (5)

Permalink