dspiegs
dspiegs

Reputation: 568

How to install specific MSIs in WiX/Burn

I am writing a custom UI for a WiX/Burn installer. There are going to be up to 30 different applications that can be installed by this installer when it is done.

I currently am able to figure out which MSI files the installer is expecting using

 protected void DetectPackageComplete(object sender, DetectPackageCompleteEventArgs e)
 {
      Installer.Dispatcher.Invoke((Action)(() => Applications.Add(new Installable
      {
          Name = e.PackageId,
          State = e.State
      })));
 }

What I am trying to figure out now is how to detect which MSIs are missing from the client machine, and how to allow the user to select which non-installed programs they want to install and vice-versa.

Does anyone know how to do it/is it possible?

I am using .NET 4.0 (requirement) and WiX 3.8

Upvotes: 0

Views: 383

Answers (2)

John Wright
John Wright

Reputation: 4607

I wrote a series of blog entries that talk through this topic, which you can find here: https://www.wrightfully.com/part-1-of-writing-your-own-net-based-installer-with-wix-overview/

Specifically, the posting on Handling Current and Future State walks through detecting the current install state and setting the future state (the action to be taken).

Using the DetectPackageComplete, which you appear to currently be using, e.State will provide you the current install state of the package, which is one of these (where Present and Absent are the key ones you'll care about):

public enum PackageState
{
    Unknown,
    Obsolete,
    Absent,
    Cached,
    Present,
    Superseded,
}

To set the action the user wants to perform, you'll need to register an event handler for PlanPackageBegin where you'll need to set the State property. For example:

BootstrapperApplication.PlanPackageBegin += SetPackagePlannedState;

private void SetPackagePlannedState( object sender, PlanPackageBeginEventArgs planPackageBeginEventArgs)
{
    var pkgId = planPackageBeginEventArgs.PackageId;

    planPackageBeginEventArgs.State = RequestState.Present;
}

Full details can be found in the blog post.

Upvotes: 0

ZeRj
ZeRj

Reputation: 1708

To find out which MSIs are missing from the client you can parse the "BootstrapperApplicationData.xml" file. This file contains general information about your bundle. It should be located in the temp directory (%temp%{guid of the installer}\ba1\ you can press win+r and write %temp% to get to the tempfolder). Its where Burn extracts your BA dll and runs it so you can access it at runtime with Assembly.Location.

Example to access it at runtime:

string path = this.GetType().Assembly.Location
string manifestNamespace = "http://schemas.microsoft.com/wix/2010/BootstrapperApplicationData";
XElement manifestData = null;
var workingFolder = Path.GetDirectoryName(path);
var bootstrapperDataFilePath = Path.Combine(workingFolder, "BootstrapperApplicationData.xml");
using (var reader = new StreamReader(bootstrapperDataFilePath))
{
   var xml = reader.ReadToEnd();
   var xDoc = XDocument.Parse(xml);
   manifestData = xDoc.Element(ManifestNamespace + "BootstrapperApplicationData");
}

manifestData then contains the information you need. Best is you insert a breakpoint here and take your time to actually look how the file looks ;) With this information you can find out what packages you are missing (the ones not detected).

After that you can offer the user the packages to chose (it's up to you how you want to do it) you just have to remember the packageId of the packages the user wants to install.

Use the PlanPackageBeginEvent after calling Engine.Plan(LaunchAction.Install) to actually tell the Engine what packages should be installed (its called for every package once) by setting the State property from the event argument to Absent or Present.

I recommend reading this: https://www.wrightfully.com/part-1-of-writing-your-own-net-based-installer-with-wix-overview

Upvotes: 1

Related Questions