How can user in Managed Bootstrapper Application select packages to install - wix

In my Managed Bootstrapper Application I want to give the user the option to select which packages to install. Therefore I want to set a variable and pass it to the Wix Bootstrapper.
My approach was to do it similar like it is possible with the installfolder (described here) and check the value with the InstallCondition of the MsiPackage.
<Chain>
<MsiPackage ...
InstallCondition="[VariableName] = 1"
...>
</MsiPackage>
</Chain>
<Variable Name="VariableName" Type="numeric" Value="1"/>
Is this the right approach? If yes, has someone an example that works? If no, what is the best way to achieve that goal?

In our managed bootstrapper we provide the user UI to make a selection of the package they want to install.
Then this information from the model is propagated and handled in the OnPlanPackageBegin and OnPlanPackageComplete.
The package request state can be set to handle this.

Related

Wix: Reschedule RegisrySearch and set property in Merge Module

I have a merge module which searches for some registry locations to read values and save to Properties. Here is the code segment:
<Fragment Id="RegSearch">
<Property Id="HOST_APP_PATH" >
<RegistrySearch Id="HOST_App"
Root="HKLM"
Key="SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\HOST.exe"
Name="Path"
Type="raw"
/>
</Property>
<Property Id="HOST_ROOT_PATH" >
<RegistrySearch Id="HOST_Root"
Root="HKLM"
Key="SOFTWARE\HostApplication\Installation Info"
Name="HOST_Root"
Type="raw"
/>
</Property>
Windows Installer puts this search in AppSearch custom action.
Problem: AppSearch executes this search very early, before WriteRegistryValues of Host Installer, it won't get any values and properties with this search won't be defined, because registry to search was never written there.
Question 1: Can we reschedule this registry search from merge module after WriteRegistryValues of Host Installer?
Question 2: Is there any other way to search registry after Host Installer executes WriteRegistryValues? Probably with some custom action?
AppSearch is a standard action provided by the windows installer and by design is intended to run very early. This is because it's frequently used by the LaunchConditions standard action to decide if an installation can continue or not. It's also useful for deciding whether features and components should be installed.
MSI is a very opinionated framework. I suspect that there is something wrong with your current design that is going to be incompatible with MSI.
Is host installer the same MSI or a different MSI? Assuming it's the same, why couldn't you just put your data in some MSI properties and use those properties to write to the registry? Then you wouldn't need to read the values back in because you'd already have them in properties.
What do you need these properties for after writing them to the registry? Usually writing them to the registry would be the end game. I'm not sure what else you are doing next.
If host.msi is a different MSI, why are you having one MSI install another MSI? That's not MSI design. In this case you would need a bootstrapper. Host MSI would run first then this MSI. But even then it's kinda strange that a second MSI would depend on properties set by a first MSI. I'd think the bootstrapper UI and Application would gather this information and pass it as secure custom public properties to both MSIs.
To answer question 1: No a merge module can only insert actions into the sequence. It can't reschedule actions. 2: You would have to use a custom action. But as I said above, this feels like the wrong path to me.

Getting Package InstallCondition In Wix Managed Bootstrapper Application

I have a Wix Bundle that contains several packages. A couple of packages are mutually exclusive. By that I mean they are both included because one needs to be installed on 32-bit machines, the other on 64-bit machines. To solve that problem, I have defined a package group like this:
<Fragment>
<PackageGroup Id="Drivers">
<MsiPackage Id="Driversx64" InstallCondition="VersionNT64" SourceFile="SRC\drivers64.msi" DisplayInternalUI="no" Visible="no" ForcePerMachine="yes" EnableFeatureSelection="yes"/>
<MsiPackage Id="Driversx86" InstallCondition="NOT VersionNT64" SourceFile=".SRC\drivers32.msi" DisplayInternalUI="no" Visible="no" ForcePerMachine="yes" EnableFeatureSelection="yes"/>
</PackageGroup>
</Fragment>
And then, in the chain I just include the <PackageGroupRef Id="Drivers"/>
Things work as expected in that the engine correctly plans the installation based on the operating system.
The trouble I'm having is I want to display a list of packages that will be installed and I would like to:
determine from the custom bootstrapper whether a package is supposed to be visible to the UI or not, and maybe it's level
determine from the custom bootstrapper whether a package's InstallCondition evaluates to true of false
The bottom line though is I want to make sure my custom BA can obey what's declared in the bundle as far as what packages are allowed to be installed on the target system.
During runtime, there will be a file called BootstrapperApplicationData.xml. This file will contain information about each package, including InstallCondition (not sure when it was added, may require v3.10.3). You'll be able to pass the value of each condition to the Engine's EvaluateCondition method to determine whether it is true or false.

WiX Bootstrapper WPF custom UI

I read and run sample from here.
Some questions:
How I can get actions names during the install/uninstall/remove process?
How I can pass variables and parameters to embedded MSI?
Is any way to get additional information from the embedded MSI (product version, company name etc) as it is done in WixSharp (WpfSetup sample)?
4. How I can get (set) from MSI file INSTALLFOLDER, TARGETDIR and other values?
I'm not sure you can or not. Microsoft.Tools.WindowsInstallerXml.Bootstrapper.BootstrapperApplication will tell you what msi package it is planning or executing, you may also be able to get information about which install action it is executing, check the events that get raised by this during your install process.
2.
In your bootstapper WPF app
//ba is an instance of BootstrapperApplication
this.ba.Engine.StringVariables["ServerInstallLoc"] = "YOUR DATA"
Bundle.wxs
<!-- Install paths provided by the managed bootstrapper interface -->
<Variable Name="ServerInstallLoc" bal:Overridable="yes" Type="string" Value=""></Variable>
And later reference this variable
<MsiPackage Id="MyInstaller" SourceFile="$(var.MyInstallerMsiProjectName.TargetPath)" Compressed="yes" DisplayInternalUI="no">
<!-- Pass wix bundle variable to MSI property -->
<MsiProperty Name="SERVER_INSTALL_OVERRIDE" Value="[ServerInstallLoc]"/>
</MsiPackage>
In your bootstrapper, you can reference properties of the bundled installers. the syntax is: !(bind.packageVersion.PackageName) assuming one of your <MsiPackage> elements is called PackageName. Binder variables reference
For question 4 look at this:
http://www.wrightfully.com/allowing-the-user-to-select-the-install-folder/
You can also look at the Wix managed bootstrapper as I believe it does this as well. You can download the source code here:
https://github.com/wixtoolset/wix3

How to modify xml on wix repair

I have an installer that is created with WIX and modifies a config via XmlFile, however I believe that the Wix Util Extension does not perform these actions on repair. This is causing problems when trying to perform a self-healing installer. Is there any way to accomplish what I am looking for
By piecing together a bunch of sources I came up with the following:
<Property Id="REINSTALLMODE" Value="amus"/>
<SetProperty Id="REINSTALL" Value="ALL" After="AppSearch">
<![CDATA[Installed AND REMOVE<>"ALL"]]>
</SetProperty>
Which forces a REINSTALL = ALL if it is not a remove or install
I have a similar scenario. Properties can be edited by the user through the UI, which are stored/loaded via the Registry and written to configuration files. Beyond Justin's answer, Secure="yes" must be set on each property, or MSI will ignore it (the log will show "Ignoring disallowed property").

wix bootstrapper

I have written a managed wix bootstrapper using WPF. The actual installation steps requires chaining of multiple msi's/exe's and batch files.
<Chain>
<MsiPackage SourceFile="xxx"/>
<ExePackage Id="Test" SourceFile="..\TestBatch.bat" Vital="yes"/>
<MsiPackage SourceFile="yyy"/>
</Chain>
During the execution of each package, a message should be displayed (preferably from the bootstrapper UI) indicating which msi/exe package/ batch file is being executed currently.
In short, a ProgressText is needed in the bootstrapper How can I make this happen?
Another question: I do not want all the msi's to be packaged into the bootstrapper exe. This is because: Each time an msi is changed we would like to ship only the updated/modified msi and not the entire bootstrapper exe. Is there a way to do this?
Two answers, one suggestion:
To get messages back during the MsiPackages being installed, handle the BootstrapperCore.ExecuteMsiMessage event. The event args there will contain a Message that contains the data you are looking for.
To configure how the packages are compressed or not, use the Compress attribute. You can either mark the entire Bundle/#Compress='no' or mark each package Compress='no' (or 'yes' if you want to go that way).
--
Suggestion: Be sure to add DetectCondition to the ExePackages so Burn will know if the ExePackages are already present or not.