Wednesday, December 5, 2007

WiX: More powerful foreach

I've been meaning to post about this for a while but just never got around to it. A few months ago I extended the implementation in WiX to allow foreach loops using any variable over any given set of values. Previously it was limited to only those variables that were defined in your preprocessor extension.
 
While this example wont do much for you, it demonstrates what a foreach loop will do. <?foreach?> loops can simplify authoring in many ways, especially for complex products.

Example:

<?foreach number in 1;2;3 ?>
    <Property Id="Property$(var.number)" Value="value$(var.number) />
<?endforeach ?>

Will result in the following being passed to the compiler:

    <Property Id="Property1" Value="value1 />
    <Property Id="Property2" Value="value2 />
    <Property Id="Property3" Value="value3 />

I want to note as a caveat, It can be very easy to break component rules by changing the contents of a component by simply changing the values you iterate over. I recommend not using foreach loops anywhere near components unless you have really thought it through.  Also, while using the preprocessor can be very handy for minimizing the amount of wix code you need to maintain, it can really confuse some of the tools that are out there that help you generate or maintain your wix source. In general, think about other options before you use the preprocessor as a solution but if you think its your best option, enjoy :)

This was originally posted here and may have additional comments.

Friday, November 2, 2007

WiX: Writing your own WiX Extension Part 2: Preprocessor

The preprocessor in WiX allows extensibilty at a few levels. In this article I will describe how to add a PreprocessorExtension to your WixExtension and have it handle variables and functions you define in your own namespace.
 
[This sample assumes you have already gone through Part 1]
 
1. Add a new class to your project called SamplePreprocessorExtension.

2. If you added a new file for this class, make sure you add: using Microsoft.Tools.WindowsInstallerXml to you file.

3. Make your SamplePreprocessorExtension class implement PreprocessorExtension.
public class SamplePreprocessorExtension : PreprocessorExtension
 
4. Add your SamplePreprocessorExtension to your SampleWixExtension class and override the PreprocessorExtension property from the base class. This will make it so when WiX asks your extension for your preprocessor extension, you extension will know what to do.
private SamplePreprocessorExtension preprocessorExtension;
public override PreprocessorExtension PreprocessorExtension
{
    get      {         if (this.preprocessorExtension == null)
        {
            this.preprocessorExtension = new SamplePreprocessorExtension(); 
        }
        return this.preprocessorExtension;
    }
}

5. Now, back in your SamplePreprocessorExtension class, you need to specify what prefixes (or namespaces) your extension will handle. For example, if you want to be able to define a variable $(sample.ReplaceMe) then you need to specify that your extension will handle the "sample" prefix.

private static string[] prefixes = { "sample" };
public override string[] Prefixes { get { return prefixes; } }

6. Now that you have specified your prefixes, you now need to handle variables and functions that are passed to you from WiX. You do this by overriding the GetVariable and EvaluateFunction methods from the PreprocessorExtension base class.

public override string GetVariableValue(string prefix, string name)
{
     string result = null;
    // Based on the namespace and name, define the resulting string.
    switch (prefix)
    {
        case "sample":
            switch (name)
            {
                case "ReplaceMe":
                   // This could be looked up from any where you can access from your code.
                   result = "replaced";
                   break;
            }
            break;
    } 
    return result;

  
public override string EvaluateFunction(string prefix, string function, string[] args)
{
    string result = null;
    switch (prefix)
    {
        case "sample":
            switch (function) 
            {
                case "ToUpper":
                    if (0 < args.Length) 
                    {
                        result = args[0].ToUpper();
                    }
                    else
                    {
                        result = String.Empty; 
                    }
                    break
            } 
            break
    } 
    return result;
}

7. Build

8. With this you can now pass your extension on the command line to candle and expect variables and functions in your namespace to be passed to your extension and be evaluated. To prove this, try adding the following properties your WiX source.
    <Property Id="VARIABLETEST" Value="$(sample.ReplaceMe)" />
    <Property Id="FUNCTIONTEST" Value="$(sample.ToUpper(lowercase))" />
You resulting msi should have entries in the Property table with the values "replaced" and "LOWERCASE" in the property table.

WiX: Writing Your Own WiX Extension Part 1

Wix extensions are used to extend and customize what WiX builds and how it builds it. I plan on talking about the 3 most common types of extensions in this article series; ProprocessorExtension, CompilerExtension, and BinderExtension.
 
The first step in creating any set of extensions is to create a class that implements WixExtension. This class will be the container for all the extensions you plan on implementing.

Creating a bare-bones WixExtension
1. Create a new C# library (.dll) project named SampleWixExtension
2. Add a reference to wix.dll to your project
3. Add a using statement: using Microsoft.Tools.WindowsInstallerXml;
4. Make your SampleWixExtension class inherit from WixExtension.
 public class SampleWixExtension : WixExtension {}
5. Add the AssemblyDefaultWixExtensionAttribute to your AssemblyInfo.cs.
 [assembly: AssemblyDefaultWixExtension(typeof(SampleWixExtension.SampleWixExtension))]
6. Build
7. Although it wont do anything yet, you can now pass the your SampleWixExtension.dll on the command line to the candle and light with the -ext flag like this: candle Product.wxs -ext SampleWixExtension.dll

The next article in this series will explain how to add a Preprocessor extension to your WixExtension.

Friday, June 29, 2007

WiX: Building a Patch using the new Patch Building System - Part 3

This example is aimed at demonstrating the workflow and command lines required to build a patch using the Patch element and Pyro.exe. I would appreciate any feedback anyone has.

Setting up the Sample:

1. Create a Directory that you plan on running the sample from. I will call this directory the sample root

2. Under the sample root directory create two subdirectories called "1.0" and "1.1"

3. Create a text file in the 1.0 directory called Sample.txt and put some text in it telling you that it is the 1.0 version of the file.

4. Create a text file in the 1.1 directory called Sample.txt and put some text in it telling you that it is the 1.1 version of the file.

You should now have 2 sub-directories under your sample root called 1.0 and 1.1 each containing a Sample.txt file whose contents state which version it is.

5. Create your product authoring in the sample root folder called Product.wxs with the following contents:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Product Id="48C49ACE-90CF-4161-9C6E-9162115A54DD" Name="WiX Patch Example Product" Language="1033" Version="1.0.0" Manufacturer="Dynamo Corporation" UpgradeCode="48C49ACE-90CF-4161-9C6E-9162115A54DD">
        <Package Description="Installs a file that will be patched." Comments="This Product does not install any executables" InstallerVersion="200" Compressed="yes" />
        <Media Id="1" Cabinet="product.cab" EmbedCab="yes" />
        <FeatureRef Id="SampleProductFeature"/>
    </Product>
    <Fragment>
        <Feature Id="SampleProductFeature" Title="Sample Product Feature" Level="1">
            <ComponentRef Id="SampleComponent" />
        </Feature>
    </Fragment>
    <Fragment>
        <DirectoryRef Id="SampleProductFolder">
            <Component Id="SampleComponent" Guid="{C28843DA-EF08-41CC-BA75-D2B99D8A1983}" DiskId="1">
                <File Id="SampleFile" Name="Sample.txt" Source=".\$(var.Version)\Sample.txt" />
            </Component>
        </DirectoryRef>
    </Fragment>
    <Fragment>
        <Directory Id="TARGETDIR" Name="SourceDir">
            <Directory Id="ProgramFilesFolder" Name="PFiles">
                <Directory Id="SampleProductFolder" Name="Patch Sample Directory">
                </Directory>
            </Directory>
        </Directory>
    </Fragment>
</Wix>

6. Create your patch authoring in the sample root called Patch.wxs with the following contents:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Patch
        AllowRemoval="yes"
        Manufacturer="Dynamo Corp"
        MoreInfoURL="http://www.dynamocorp.com/"
        DisplayName="Sample Patch"
        Description="Small Update Patch"
        Classification="Update"
        >
       
        <Media Id="5000" Cabinet="RTM.cab">
            <PatchBaseline Id="RTM"/>
        </Media>
        <PatchFamilyRef Id="SamplePatchFamily"/>
    </Patch>
    <Fragment>   
        <PatchFamily Id='SamplePatchFamily' Version='1.0.0' Supersede='yes'>
            <ComponentRef Id="SampleComponent"/>
        </PatchFamily>
    </Fragment>
</Wix>

You should now have a Product.wxs and Patch.wxs file in the sample root.

Instructions for building a Patch using the sample:
Open a command prompt where you normally run the WiX tools from.
Required WiX executables:
Candle.exe
Light.exe
Torch.exe
Pyro.exe
Your WiX toolset version should be at least 3.0.3001.0

1. Build Target Layout:
> candle.exe -dVersion=1.0 product.wxs
> light.exe -sval Product.wixobj -out 1.0\Product.msi

2. Build the Upgrade Layout:
> candle.exe -dVersion=1.1 product.wxs
> light.exe -sval Product.wixobj -out 1.1\Product.msi

3. Create the transform between your products:
> torch.exe -p -xi 1.0\Product.wixpdb 1.1\Product.wixpdb -out Patch\Diff.Wixmst

4. Build the Patch:
> candle.exe Patch.wxs
> light.exe Patch.wixobj -out Patch\Patch.WixMsp
> pyro.exe Patch\Patch.WixMsp -out Patch\Patch.msp -t RTM Patch\Diff.wixmst

I am currently working on reducing the number of command line switches required for building a simple patch. Sometime soon I hope to have the commands somewhat simplified by making the defaults match up with the patch building system.

Verifying what you have done here works: 
1. Install the 1.0 Product by running 1.0\Product.msi
2. Go to "Program Files\Patch Sample Directory" and open up Sample.txt. You should see that it is the 1.0 version.
3. Close Sample.txt.
3. Install the Patch from the sample root Patch\Patch.msp.
4. Repeat step 2 and notice that Sample.txt now contains the new 1.1 content.
5. Go to Add/Remove Programs and make sure "Show Updates" is checked.
6. Uninstall the Patch and repeat step 2 to see that the file was rolled back to its original version.
7. Uninstall the Product itself to clean off your system.

This was originally posted here and may have additional comments.

Sunday, June 17, 2007

WiX: Building a Patch using the new Patch Building System - Part 2

I dont have much time today to write but I wanted to take a chance to answer a few questions that I've been asked a lot recently.
 
What is Pyro?
Pyro is the new tool in the WiX toolset that will pull together your patch authoring and your product transforms in order to build you an msp.

What is the new system and what is the old?
It is important to distinguish the new patch building system from the previous one provided by WiX. There has been some confusion and I want to try and clear it up. 

The Previous Way:
The PatchCreation element has been supported in WiX for a while to help people build patches. It essentially helps users build a pcp file which is then used as input to the PatchWiz tools. The PatchCreation element is not used in the new patch building system.

The New Way:The Patch Element is a newly added element that lets you describe the contents of your patch. It contains information about where the files your patch contains should be stored as well as summary information that describes your patch to your end user. It also supplies a mechanism to filter out specific changes to be included in your patch. When this element is passed to candle to be compiled and the resulting wixobj's are passed to light to link, the result is a WixMsp. This is an xml representation of the patch database (msp).

What Next?
The next thing I'd like to do is to provide a simple example of how to build a patch using Pyro.exe. I plan on getting this started in the next few days. Keep bugging me if I dont to remind me to do it and feel free to ask me more questions as this new functionality isn't all that well documented yet.

Friday, June 8, 2007

WiX: What is a WiX Extension?

A WiX extension is a dll that allows users to add their own custom elements, preprocessor functionality, and build customizations. These extensions take advantage of the various extension points in WiX. The most commonly used ones are Preprocessor, Compiler, and Binder extentions.

Mosts WiX extensions shipped with the WiX toolset are used to encapsulate common funtionality and make it easy for users to author things into their setups. They are targeted at solving setup problems in a standard way so everyone can benefit from and build on the WiX toolset.

Example: WixNetFxExtension.dll

Many people who write applications for the .NET Framework have various needs. I will discuss 2 here in an effort to describe 2 uses of extensions.

AppSearch (ComponentSearch, RegistrySearch, etc..):

Sometimes people want to find information about the system as part of their install. One way to get current system info is using an AppSearch.

Detecting if the .NET Framework is installed:

In reality, in order to detect if the .NET framework is installed, you need to search for a specific registry key and set a property if that key exists. Using the WixNetFxExtension you can just add the following to detect if the 2.0 Framework is installed.

<PropertyRef Id="NETFRAMEWORK20"/>

 The logic defining this property and all the logic behind it is stored in a WixLib which embedded inside the WixNetFxExtension.dll

Custom Actions:

Sometimes people want to do things that are not supported by Windows Installer. In this case they write custom actions. WiX provides a good mechanism for sharing custom actions.

Ngen’ing an Assembly:

To add a custom action to a product there is a lot of authoring to do. You need to define it and its binary, schedule it, and condition it. This doesn’t even consider that most custom actions come in sets, all sequenced at different times. This can all be done using a CustomActionRef in a similar way as the previous example.

After that, you need to populate any custom tables your custom action may rely on for its data. This is a lot complexity for users to author using standard WiX constructs. One use of a compiler extension can be to add your own element to the authoring and have that translate into a custom table in your msi that your customaction can read. The ngen custom actions have such an element.

<netfx:NativeImage Platform=”all” … />

The compiler will take this line and its context and populate a NativeImage table in the resulting MSI that will contain all the data needed by the ngen custom actions. The custom action also requires a dll binary in the binary table. In WiX v2 you had to ship your binary along with your extension. WiX v3 has support for binary WixLib’s. The key thing here is that the binary will get added into the WixLib for you and you don’t have to worry about shipping 2 separate files.

The resulting extension file:

The result of this is a .NET dll with a WixLib embedded in it as a resource. That WixLib then in turn has a cabinet at the beginning of it that contains the custom action binary. All of this nesting is handled for you by the linker and the binder so all you have to do to use stuff you put in your WixLib is add the extension to your candle and light command lines and reference the things defined in the WixLib from your product authoring.

Saturday, May 5, 2007

WiX: Preprocessor error and warning

This is simple but could be handy. You can now add preprocessor instructions to you WiX authoring that will allow you to display a warning or error message when the preprocessor encounters that line.
Often errors and warnings would be used inside other prepropcessor constructs.

Example:

<?warning Must define the variable variableThatMustBeDefined ?>
<?ifndef variableThatMustBeDefined ?>
    <?error You did not define the variable variableThatMustBeDefined ?>
<?endif ?>

Friday, April 27, 2007

WiX: PatchFamily patch filtering

 

Using the Patch system in WiX 3.0 allows you to select which differences between 2 builds you want to ship. By default, all the changes will go into a patch, but sometimes people want to ship a targeted update to fix a security issue or major customer problem. This can be done using the PatchFamily concept built into WiX.

A patch family has 2 meanings in this context, it specifies which changes you would like in any given patch, and also provides a mechanism for supercedence and dependency tracking. I'm not going to get into supercedence here other than to say that for each patch family in a patch will get an entry in the MsiPatchSequence table.

The PatchFamily element is a child of the Patch element. You can have as many PatchFamily elements in a Patch as you want. Under a PatchFamily element, there is a set of Reference elements that can be used to pull various items into your patch. Just as in your product authoring, referencing anything in a Fragment will result in that entire fragment being pulled in. WiX will handle file and media sequencing as well as the Sequence tables for you.

Example:

This PatchFamily would select the Fragment that contains the Component "MyComponent" and add it to the patch.

<PatchFamily Id="MyPatchFamily" supercede="yes">
    <ComponentRef "MyComponent" />
</PatchFamily>

Sidenote:
One thing to note is that there are rules about patch families. Once you ship a patch family, you must keep its references the same or add to it (grow it) but never remove items from it. All items in your product must be a part of only one patch family. When you change the build that you are targeting (re-baseline), patch families start over so you can change the contents and asociations at this time.

WiX: Functional Preprocessing


The preprocessor in WiX has a new feature called Functional Preprocessing. It is a way for WiX users to define functions that they can use in their authoring to dynamically fill in content.

 Most people who use WiX are familiar with preprocessor variables which look like:

 "$(var.VariableName)"

 The preprocessor now has support for functions in addition to variables which look like:

"$(func.FunctionName(arg1,arg2,arg3))"

While there have been no additions as of yet to the standard WiX preprocessor function library many functions have been implemented and are being used in people's preprocessor extensions. In an extension you tell the preprocessor that you would like to have all functions with a specific qualifier be handled by your extension.

Example:

Say you want to keep track of all of your component GUID's in a single file. The file has 4 pieces of data for each GUID. Id, Language, Architecture, and of course the GUID.

MyComponentId, English, Intel, 365453-34235-32525-23325345223

If you implement a preprocessor extension to handle "guid" functions and define a function called "GetGuid" that takes 3 arguments you could represent the guid in your authoring as:

"$(guid.GetGuid(MyComponentId,English,Intel))"

This function would be replaced in your authoring with "365453-34235-32525-23325345223".
 There are a lot of possible uses of this type of functionality. I'd love to hear how other people use it.

This was originally posted here and may have additional comments.

WiX: Building a Patch using the new Patch Building System - Part I

A new patch building system has been built into WiX 3.0. The purpose of this post is to describe, at a very high level, the process of using this new system.
1. Build and ship your product using WiX v3.0. (Candle, Light)
2. Make changes to your product and build again. (Candle, Light)
4. Produce a transform based on your baseline and upgrade build. (Torch)
3. Author and build your patch. (Candle, Light, Pyro)
This system will allow you to build patches that apply to multiple products as well as multiple versions of the same product.

Building your Product (the one you ship is called your baseline)
The entire system is based on using the WiX XML representations of your product. Because of this, the process you use to build may need to change slightly. When building your product you will want to make 2 seperate calls to Light. The first call will be to link the product and create a WixMsi using the 'xo' command line option. The second call to Light will pass the WixMsi back into Light to Bind it into a Windows Installer Database.
When calling Light the first time, a set of flags are required to be passed on the command line in order to make a patchable WixMsi. 'xo', 'sdut', and 'tsa'. This tells Light to output the linked XML in WixMsi format, keep all unreal table information, and to preserve/auto-generate section id's.

Building your Upgrade 
This build represents the result you want on the target machine when your patch is applied to the Baseline build.
When you need to ship a patch or update to your customers, you need to make the changes to your product and build the product with all the changes the same way you built the baseline. This build is called your Upgrade build.

Building a Transform
To build a transform you simply need to call Torch with the two WixMsi's from your Baseline and Upgrade builds. This will produce a WixMst that represents the difference between your two builds.
When calling Torch you need to use a certain set of command line options. 'xi', 'xo', and 'p'. This means, you are giving xml inputs, you want an XML output, and you want all information preserved in the WixMst even if it hasnt changed.

Build your Patch
I will not go into all the details of how to author your patch. This is fairly well documented in the WiX.chm help file. I will also follow up on this in a later post.
The first step once your patch is authored is to build the patch using Candle and Light the same way you built your product. The result of calling Light with patch authoring is always a WixMsp.

Next, you will need to call Pyro with your WixMsp and your WixMst(s). A WixMst is passed on the pyro command line using the 't' option. The 't' option requires two inputs, the baseline identifier to tie the transform to and the path to the WixMst. The baseline identifier needs to be the same one you tied to a Media element in your Patch authoring.

Summary
 This system is fairly new and a large effort is currently being made to stabilize this system. Support for binary delta patching is also something that is coming down the road using this system. If you want to use this system in the future, the first step will be to start building your product using the process I documented above where you break the call to Light into 2 seperate steps.

This was originally posted here and may have additional comments.