2
votes

Given:

  1. Wix 3.0 is used to create MSI.
  2. The product consists of multiple feature.
  3. Each feature has few sub features. It’s a standard MSI feature tree.
  4. Each feature or sub feature depend on multiple external components. E.g. .NET 4, ASP.NET etc
  5. Custom action written in C# using Wix 3.0 SDK processes these dependency and evaluates if components are present or not for a given set of features.
  6. At time of install if dependent component is missing for given selection of features, installation fails.

To achieve: Ability to execute prerequisite check, which is already done in MSI as custom action during installation, without installing MSI on a given machine.

Failed Attempts:

1) Custom action have function signature like this

[CustomAction]
public static ActionResult ProcessFeaturePrerequisite(Session session);

In order to get session object I used following API present in Wix 3.0 SDK

Session session = Installer.OpenPackage("Pathto\\Product.msi", true); // true doesn’t install it. Also tried with false, but didn’t work.

When I invoke the above method with above session following things fail.

session.Features["SomeFeature"].CurrentState;

This throws exception.

System.ArgumentException was unhandled by user code
  Message=Feature ID not registered. SomeFeature
  Source=Microsoft.Deployment.WindowsInstaller
  StackTrace:
       at Microsoft.Deployment.WindowsInstaller.FeatureInfo.get_CurrentState()

Also below critical API which determines prerequisite status always returns false.

session.EvaluateCondition(prereq);

2) I know a command line way to specify features to the above MSI and install it. It goes like this

msiexec /i "Product.msi" ADDLOCAL=ALL REMOVE="Foo,Bar " 

I couldn’t find any API in SDK which allows me to pass additional params which returns session object without starting installation. My guess is passing such param will make session.Features more valid.

Questions: So how do I achieve above goal? Is there

  1. any API in Wix SDK which allows me to call custom action without invoking installation?
  2. any way to invoke custom action from command line for a given MSI without installing?
  3. any way to make Wix to change MSI into accepting a command string containing custom action name which only evaluates the action?
  4. any better way to do the same?
1

1 Answers

2
votes

I suppose you're trying to solve the problem with the wrong tool. As far as I understand, you would like to check the installation prerequisites from inside a certain tool, but not from the installation. As long as the functionality is implemented as a custom action in the MSI package, you'd like to utilize that functionality in order not to duplicate the code.

I would choose a different way in your situation:

  1. Extract the functionality which actually checks for prerequisites into a separate assembly, e.g. checkprereq.dll
  2. Refactor your custom action to reference checkprereq.dll. Note that you'll have to add checkprereq.dll to your Binary table as well as the customaction.dll. You should divide the responsibility here: the custom action part works with MSI stuff - in your case, it's defining which prerequisites to check based on the combination of features a user selected - and the functional part - the actual prerequisites verification, which is done by checkprereq.dll
  3. Use checkprereq.dll separately when you need to check prerequisites not triggering the installation process

The attempts you've outlined here demonstrate an important false assumption: the session object at install time is the same as the installation object you get by just opening the MSI database for read only purpose. IT'S NOT TRUE! Actually, I doubt it makes any sense to reference the session object outside the installation transaction. As its name states, it is an installation session, that is, available in process - not a static thing.

The MSI package should be treated just as a database when it is just a file and not a running installation. Hence, only static information living in MSI package can be queried and used when you just open it for reading and not installing. I mean you can query the Feature table, for instance, but don't expect it to contain information which makes sense in installation time only, like whether a user chose a feature for installation or not.

Hope this makes sense and shows you the right direction.