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
Posted in WiX at April 26th, 2008. 1 Comment.

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

Posted in Flight Simulator, WiX at April 22nd, 2008. 3 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.

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

Posted in WiX at April 19th, 2008. No 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.

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.

Posted in WiX at April 1st, 2008. 5 Comments.