WiX - How to declare global variables in WiX bundle? - wix

I am writing a WiX bundling project which involves two MSIs. My requirement is to declare a "global variable" in the Bundle context, so that it can be referenced anywhere in the wxs files of any of the two MSIs.
Is there a possible way to accomplish this?
P.S. I am building the project in WiX v3 using Visual Studio extension.

Declare a variable in the bundle and pass it to the msi's
For example in the bundle:
<Variable Name="InstallFolder" Type="string" Value="[ProgramFiles6432Folder]$(var.Manufacturer)\[WixBundleName]"/>
<MsiPackage Id="Product" SourceFile="$(var.Product.TargetPath)">
<MsiProperty Name="INSTALLFOLDER" Value="[InstallFolder]" />
</MsiPackage>

Related

How to pass AddLocal-Parameter from wix standard bootstrapper to a MsiPackage

With WIX Tools v3.10 I used to add a variable AddLocal to the bundle which I passed to the MsiProperty with the Name="ADDLOCAL" as described by BryanJ in "Pass parameters from bootstrapper to msi bundle package".
<Bundle>
...
<Variable Name="InstallLevel" Type="numeric" bal:Overridable="yes" Value="1"/>
<Variable Name="AddLocal" Type="string" bal:Overridable="yes" Value=""/>
<Chain>
<MsiPackage Id="Addin64bit_loc" Vital="yes" DisplayInternalUI="yes" ...
EnableFeatureSelection="yes" >
...
<MsiProperty Name="INSTALLLEVEL" Value="[InstallLevel]"/>
<MsiProperty Name="ADDLOCAL" Value="[AddLocal]"/>
</MsiPackage>
</Chain>
</Bundle>
Now after switching to v3.11 I get this warning which will turn to an error in v4:
Warning CNDL1149: The 'ADDLOCAL' MsiProperty is controlled by the bootstrapper and cannot be authored.
(Illegal properties are: 'ACTION', 'ADDLOCAL', 'ADDSOURCE', 'ADDDEFAULT', 'ADVERTISE', 'ALLUSERS', 'REBOOT', 'REINSTALL', 'REINSTALLMODE', or 'REMOVE'.)
Remove the MsiProperty element.
This restriction will be enforced as an error in WiX v4.0.
So what is the adequate way in v3.11 to pass an ADDLOCAL parameter from bootstrapper command line to the Msi?
you can influence on ADDLOCAL parameter in your custom bootstrapper project something like that:
_bootstrapper.PlanMsiFeature += (_, ea) =>
{
ea.State = (needToInstall) ? FeatureState.Local : FeatureState.Absent;
};
I ran into the same issue and ended up using a transform with only the ADDLOCAL property set.
Rather than using AddLocal, I found adding code like:
<Feature Id="FeatureB" Level="0">
<Condition Level="1">INSTALL_FEATUREB="1" OR FEATUREB_INSTALLED="1"
</Condition>
</Feature>
to my msi file behaved in a reasonable manner, allowing me to add/remove a feature.
Modified from:
using https://support.firegiant.com/hc/en-us/articles/230912227-Control-feature-states-for-silent-install-
I like using the 'Variable=X' syntax because I find it easier to read. Without the FEATUREB_INSTALLED test I found uninstall did not act as I wanted.
Well, you can always pass a value to a Variable from the Code behind like this.
Bootstrapper.Engine.StringVariables["AddLocal"] = "your value";

Generating an EXE from MSI in Wix

I'm tring to generate EXE file from MSI in Wix installer, I added a new project (Bootstrapper) but I can specifying the path of my MSI file
<Bundle Name="Bootstrapper" Version="1.0.0.0" Manufacturer="" UpgradeCode="e45fdbb6-192c-46f7-b4db-d04af69edada">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense" />
<Chain>
<!-- TODO: Define the list of chained packages. -->
<MsiPackage SourceFile="WixSetup.msi" />
</Chain>
</Bundle>
Can you help ?
Thanks in advance
Abdulsalam
Add a reference of your msi's wixproj to your bootstrapper application.
You can now reference the msi file like this
<MsiPackage SourceFile="$(var.WixProjName.TargetPath)" />
This will automatically point to the debug location or release location depending on your build mode.
You can see a list of well-defined vars passed to candle.exe in the output when building. You'll see a bunch of defines like "-dWixProjName.Property=Value" and then you can use those values in your bundle xml like so $(var.WixProjName.Property) which will get replaced by the Value before compiling.
You can see a list of the defined properties when you reference another project here: http://wixtoolset.org/documentation/manual/v3/votive/votive_project_references.html

Passing command line args to MSI from WiX bundle

I’m on Wix 3.7. I have an MSI that I would like to set a registry key (perhaps via a Custom Action, as he will have to check if the key already exists).
I understand that a Bundle in a bootstrapper project can't change the machine state (such as setting the registry). Therefore, I'm attempting to pass a command line argument via <MsiProperty>, but doesn't appear to show up as a command line argument in my log file for the bootstrapper.
Is it possible to set a registry key up in a Bundle?
If not, how can I add a command line argument (or some other piece of custom data)
to be passed to the MSI.
How can the MSI read whatever it is I pass to it (whether It ends up being a command line arg or something
else).
Bundle:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Bundle
Name="MyInstallerBootstrapperLocalDb"
Version="1.0.0.0"
Manufacturer="some company"
UpgradeCode="PUT-GUID-HERE">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense" />
<Chain>
<MsiPackage Id="MyInstallerInstaller"
SourceFile="$(var.MyInstallerInstaller.TargetPath)"
Compressed="no">
<!-- TODO - if this is being set correctly, the MSI needs to
interpret it and set up the key-->
<MsiProperty Name="SetLocalDb" Value="yes"/>
</MsiPackage>
</Chain>
</Bundle>
</Wix>
Your MSI needs to define a property like so:
<Property Id="SOMEPROPERTY" Value="Default"/>
You can then set this property from the bundle:
<MsiPackage SourceFile="<package>.msi" Id="SomeId">
<MsiProperty Name="SOMEPROPERTY" Value="[SomeProperty]" />
</MsiPackage>
After this you can set the property in the Bootstrapper as described here: WiX Bootstrapper: How do I set burn variables from the command line?
Notice that SomeProperty is a Burn variable which you have to define:
<Variable Name="SomeProperty" Type="string" Value="DefaultValue" />
Update:
In the MSI you are then able to do a registry search based on this property:
<RegistrySearch Id="GetSomeValue" Root="HKLM" Key="SOFTWARE\<Manufacturer>\[SOMEPROPERTY]" Name="<ValueName>" Type="raw" />
Just to add an extra bit of information. To alter the variable values with command line, I actually had to set it as overriable.
<Variable Name="SomeProperty" Type="string" Value="true" bal:Overridable="yes" />

How do I pass a default 'install location' to the RtfLicense bootstrapper?

I'm using an rtflicence standard bootstrapper to install dotnet before my poject msi in a chain.
I noticed that there's an 'options' button which displays an install location dialog and allows the user to change the default installation directory.
I need to either:
Prevent this options button from being displayed, or
Populate the install location with a default path, and pass this back to the installer should the user change it.
I read that it's possible to pass Burn variables to msipackages from bootstrapper but I haven't found any further details and would appreciate being pointed in the right direction.
Thanks
To go with option 1, you'd have to roll your own BootstrapperApplication and remove the options button from the menu.
Option two is significantly easier to implement. The bootstrapper uses a special Burn variable called InstallFolder to get and set what is in the text block on that view, which you can assign inside the Bundle element.
<Variable Name="InstallFolder" Type="string" Value="[ProgramFilesFolder]"/>
The constant ProgramFilesFolder will set the value of that text block when the program starts, and if the user browses to a different directory, it will be stored in that same variable. To pass it to the MSI, in your chain, you pass the InstallFolder using the MsiProperty tag (INSTALLLOCATION is the name of the property in your WiX project).
<MsiPackage Vital="yes" DisplayName="Your Name" Id="MsiId" SourceFile="path/to/file.msi">
<MsiProperty Name="INSTALLLOCATION" Value="[InstallFolder]" />
</MsiPackage>
I just discovered the SuppressOptionsUI option that addresses your Option 1 without rolling your own BootstrapperApplication:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
<Bundle>
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
<bal:WixStandardBootstrapperApplication LicenseFile="..\eula.rtf" SuppressOptionsUI="yes"/>
</BootstrapperApplicationRef>
<Chain>
</Chain>
</Bundle>
</Wix>
I think you can try removing the options button by creating a theme. I haven't had to use themes myself but here are two related SO links that may get you pointed in that direction:
WiX bootstrapper theme file?
Theme for my WiX Installer

Specify the INSTALLLOCATION of packages in WiX inside the Burn managed bootstrapper

I have a WiX 3.6 bundle (using Burn) and managed bootstrapper that install several MSI packages. Some of the packages install to a common location (C:\program files\MyApp).
I want to let the user choose the install location inside the managed bootstrapper application (C# WPF, especially because the application is large to install; about 1 GB). How can I specify the INSTALLLOCATION for each MSI packages inside my bundle?
Use an MsiProperty child for each MsiPackage to specify INSTALLLOCATION=[BurnVariable]. Then use Engine.StringVariables to set BurnVariable.
For example, in your bundle you set:
<Bundle ...>
<Variable Name='BurnVariable' Value='bar' />
...
<Chain>
<MsiPackage Source='path\to\your.msi'>
<MsiProperty Name="INSTALLLOCATION" Value="[BurnVariable]" />
</MsiPackage>
</Chain>
</Bundle>
See also the FireGiant explanation on this topic.
Then in the managed bootstrapper you can do something similar to this:
Engine.StringVariables["BurnVariable"] = "C:\program files\MyApp";