Localizing more than strings in WiX v3.6

Localizing an MSI package—primarily the user interface but also bits like the product name, shortcut names, and other user-visible, localizable strings—has been pretty much unchanged since WiX v2.0:

  • Localizable strings are specified in the appropriate attributes in your WiX authoring using !(loc.stringid) syntax.
  • Strings are specified by id in per-language WixLocalization (.wxl) files.
  • Light, the WiX linker, takes a list of cultures to use when resolving !(loc.stringid) in the authoring.

As you can see, localization is all about the strings. However, strings can vary dramatically in length among languages. In the WixUI dialog library, controls were sized to handle string lengths for all the languages WixUI supported. Unfortunately, that resulted in some controls being far wider than necessary. The Install button, for example, is wider than the other buttons on the same dialogs. We hadn’t had to resize any controls in WixUI for a while—and then a bug said otherwise.

Rather than yet again resizing a control, WiX v3.6 gets a new feature so we never have to do that again. In WiX v3.6, the WixLocalization schema has been extended with a UI child element that lets the localization for a particular culture change the attributes of an individual control or an entire dialog. For example, a later bug indicated the need for another big button in WixUI_Advanced. The fix in the ru-RU localization file was easy:

<UI Dialog="AdvancedWelcomeEulaDlg" Control="Print" X="50" />
<UI Dialog="AdvancedWelcomeEulaDlg" Control="Advanced" X="124" Width="85" />

The first line moves the Print button to the left, to make room for a bigger Advanced button, which the second button supplies. The dialog and control attributes identify a particular control.

The WixLocalization UI element (unrelated to the UI element in the WiX namespace) lets you:

  • Resize a control using the Height and Width attributes.
  • Move a control using the X and Y attributes.
  • Change the control’s localization-related attributes: LeftScroll, RightAligned, and RightToLeft.
  • Change the control’s text using the inner text of the UI element.

You can also use the UI element on dialogs by omitting a Control attribute:

  • Resize a dialog using the Height and Width attributes.
  • Change the dialog’s centering values using the X and Y attributes.
  • Change the dialog’s title using the inner text of the UI element.

Don’t forget native code

Though localization files are most often used inside MSI packages using WixUI dialog sets, they’re also used extensively in the WixStandardBootstrapperApplication for Burn. And even if you use a managed bootstrapper application, you’re still using WixStandardBootstrapperApplication when the managed host needs to install .NET.

 

New WiX feature: Firewall extension

WixFirewallExtension is a new WiX extension that lets you configure the Windows Firewall from your program’s installer. Windows has had a built-in firewall since Windows XP was released in 2001, though it was XP’s Service Pack 2 that introduced a firewall of sufficient power for most people to use it. (It helps that in SP2, the firewall is turned on by default. The same is true on Windows Vista, Server 2003 SP1, and Server 2008.)

Outgoing connections — from the local computer to a server — aren’t blocked. (In fact, the firewall on XP SP2 and Server 2003 SP1 doesn’t support blocking outbound connections. That feature was added to the firewall in Vista and Server 2008.) Incoming connections are blocked unless the firewall is configured to allow them. If your program is any kind of a server, it needs to add itself to the firewall’s exception list or it won’t receive any connections that originate from another machine.

There are two types of firewall exceptions:

  • Application: A particular program for an incoming connection on any port/protocol.
  • Port: A particular port for a particular IP protocol (TCP or UDP). Any program can accept incoming connections from that port/protocol.

For both types of exceptions, the scope of the exception controls which incoming connections are accepted:

  • Any network, including the Internet.
  • Only the local subnetwork.
  • Custom IP addresses.

You can configure your program’s firewall exceptions using the FirewallException element. To configure an application exception, nest the FirewallException element under the program’s File element or under a Component element and specify the program’s file id in the File attribute:

<Wix xmlns=”http://schemas.microsoft.com/wix/2006/wi” xmlns:fire=”http://schemas.microsoft.com/wix/FirewallExtension”>

<Component Id=”MyComponent1″ Guid=”PUT-GUID-HERE”>
<File KeyPath=”yes” Source=”program.exe”>
<fire:FirewallException Id=”FWX1″ Name=”My Program” />

The Id and Name attributes are both required. You can adjust the scope of the exception using the Scope attribute, which takes values any or localSubnet or by using RemoteAddress child elements:

<Wix xmlns=”http://schemas.microsoft.com/wix/2006/wi” xmlns:fire=”http://schemas.microsoft.com/wix/FirewallExtension”>

<Component Id=”MyComponent2″ Guid=”PUT-GUID-HERE”>
<File KeyPath=”yes” Source=”program.exe”>
<fire:FirewallException Id=”FWX2″ Name=”My Program”>
<fire:RemoteAddress>127.0.0.1</fire:RemoteAddress>
<fire:RemoteAddress>127.0.0.2</fire:RemoteAddress>
<fire:RemoteAddress>127.0.0.3</fire:RemoteAddress>

RemoteAddress is a direct line to the firewall API’s support for remote addresses.

There’s also a Program attribute that lets you specify a formatted string that identifies the program that should get the firewall exception. It’s useful if you want to specify an exception for a program installed by a different package.

To specify a port exception, use the Port and Protocol attributes. Port takes an integer value and Protocol takes tcp, udp, or any. Note that any requires Windows Vista and Server 2008; on XP SP2 and Server 2003 SP1, specify two port exceptions, one with Protocol=”tcp” and another with Protocol=”udp” as a workaround.

<Wix xmlns=”http://schemas.microsoft.com/wix/2006/wi” xmlns:fire=”http://schemas.microsoft.com/wix/FirewallExtension”>

<Component Id=”MyComponent3″ Guid=”PUT-GUID-HERE”>
<File KeyPath=”yes” Source=”program.exe”>
<fire:FirewallException Id=”FWX3″ Name=”My Program” Port=”1025″ Protocol=”udp” />

Both types of exceptions also support the IgnoreFailure attribute to specify whether firewall configuration failures should be ignored or cause the installation to roll back.

Sponsored by ACES

The firewall 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 WiX community.

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.

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. 😀