How to decouple things in Wix? - wix

I want to install a product with some dll with Wix 3.5.
These dll are determined during the msi installation through a radio buttons group.
I have :
a (fragment) wxs for myDllv1
a (fragment) wxs for myDllv2
a (UI fragment) wxs with the RadioButtonGroup to choose between myDll v1 and myDll v2 with a property INSTALLTYPE
a main wxs file which installs the correct version of myDll.
Problem : I have another set of dll to add and I want to modify as less files as possible.
I don't want to introduce bugs and I want to keep things decoupled.
I would like to modify only the UI fragment with the radio buttons and add a myDllv3 fragment (without doing any changes to my main wxs file, so no condition in that file..).
Is it possible?

Why don't you use pre-processors to select the correct fragments when building the msi?
<?if $(env.SomeBuildParameter) = SetA ?>
<?include myDllSetAv1.wxs ?>
<?include myDllSetAv2.wxs ?>
<?else ?>
<?include myDllSetBv1.wxs ?>
<?include myDllSetBv2.wxs ?>
<?endif ?>

I may be misunderstanding the question, but it sounds like your different set of Dlls should be grouped by features within WIX. I'd suggest creating independent WIX fragments that represents a feature for each of your set of Dlls and then you can tie your UI to install a specific feature as appropriate.
You represent a feature at the product level like so:
<Feature Id="Feature.One" Title="Feature One">
<ComponentGroupRef Id="FeatureOneDlls.Group" />
</Feature>
<Feature Id="Feature.Two" Title="Feature Two">
<ComponentGroupRef Id="FeatureTwoDlls.Group" />
</Feature>
And within each of the features I'd recommend using a separate wxs file to supply the fragment information that contains the files for that feature.

Related

WIX cannot find app.exe in x86/x64 output directory

I have a C# application which its build targets are x86 or x64. The build output is (for example) ProjectDir/bin/x86|x64/Debug|Release/*
In my *.wxs file I have defined thr following variable
<?define AppTargetPath = "$(var.MyApp.TargetPath)" ?>
Which points to ProjectDir/bin/Debug|Release/app.exe
If I build the installer, it fails because it does not find my app exe
<File Id="AppExe" Source="$(var.AppTargetPath)" KeyPath="yes"/>
If I look on Using Project References and Variables site (http://wixtoolset.org/documentation/manual/v3/votive/votive_project_references.html) I cannot find another variable.
Maybe try this:
Comment out your existing define.
Add the project building the EXE and your WiX project to the same solution.
Add a reference from the WiX project to the EXE / Binary project.
Try this markup (replace project name "TestConsoleApplication" with yours):
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component>
<File Source="$(var.TestConsoleApplication.TargetPath)" />
</Component>
</ComponentGroup>
</Fragment>
Rebuild All.
Toggle Release and Debug builds, then Rebuild All again.
Links:
Summary: My WiX Quick Start Tips.
Basic WiX Project: Step-by-step, Hello WiX project.
Real-World Sample: Real-World Example: WiX/MSI Application Installer
Actually I solved it by putting together the entire path on top of my wxs file:
<?define AppTargetFileName = "$(var.myApp.TargetFileName)" ?>
<?if $(var.Platform) = x64 ?>
<?define AppTargetPath = "$(var.myApp.ProjectDir)\bin\x64\$(var.myApp.Configuration)\$(var.AppTargetFileName)" ?>
<?elseif $(var.Platform) = x86 ?>
<?define AppTargetPath = "$(var.myApp.ProjectDir)\bin\x86\$(var.myApp.Configuration)\$(var.AppTargetFileName)" ?>
<?else ?>
<?define AppTargetPath = "$(var.myApp.TargetPath)" ?>
<?endif ?>

Using files 'included' in a wixlib

We use a wixlib that has all the dialogs (most of which can be shared with other products on our portfolio).
One of these dialogs will show a EULA. This EULA is added to the wixlib project as (RTF) content (Build Action: Content, Copy to output: DontNotCopy)
Now next to showing the EULA, I must also install it with all the products.
Can I some how reference the EULA that (has to be?) is embedded in the wixlib?
Or do I need to copy this file to all the wixproj of all products? Given it's a EULA, which won't change that much, it's still a hassle if it does change. I trying to avoid that.
I'm guessing, I need to copy it to all products, but I wanted to double check.
In hindsight, I overthought this. I simply added the file to a component in the wixlib project which can be referenced from the consuming Wix project.
In the wixlib:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<Component Id="C_General_EULA" Directory="INSTALLFOLDER" Guid="{INSERT_GUID}" KeyPath="yes">
<File Id="F_General_EULA" Source="Localization\EULA_en-us.rtf"/>
</Component>
</Fragment>
</Wix>
In the consuming Wix project:
<Feature Id="EULAFeature" Level="1" Display="hidden">
<ComponentRef Id="C_General_EULA"/>
</Feature>
Again, in hindsight really simple.

Wix Toolset - Variable Shared Across Projects/Solution

I am trying to share a variable across 2 of my wix projects but I am having issues.
Basically I am trying to accomplish having the version number of my bootstrapper and MSI in one file and then this referenced by the two projects.
I have three projects
Install - This is a setup project that creates an .msi file
Bootstrapper - This is a Wix Bootstrapper project that references and runs the .msi file at runtime
Shared - This is a wixlib project that contains a single variable in a fragment that is the version number
The shared project contains a single file i have called GlobalVars.wxs and looks like this
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<?define VersionNo = "6.86.123"?>
</Fragment>
</Wix>
The bootstrapper references this variable like this
<Bundle Name="ProgramName" Version="$(var.VersionNo)" Manufacturer="CompanyName" UpgradeCode="Guid" Compressed="no">
and the Install project references the variable like this - and has a reference to the .wxs from the shared project
<Product Id="*" Name="Program Name" Language="2057" Version="$(var.VersionNo)" Manufacturer="CompanyName" UpgradeCode="guid">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" InstallPrivileges="elevated"/>
<?include GlobalVars.wxs ?>
Both projects have references setup to the wixlib project that contains the variable
When i attempt to build I am getting this error on both the install and bootstrapper project
Undefined preprocessor variable '$(var.VersionNo)'.
If the <?include?> tag resolved the issue I would expect the install project to build
Does anyone have any ideas as to what I might be doing wrong here?
To me it looks like the variable has not been defined by the time the build attempts to call it, but I am unsure as to show to change the order to ensure the variable is defined before anything else
Thanks for the help
I believe the answer to this question will help. I've used it and noticed that properties seem to be usable in my main wxs file.
To summarise, you need to set up a fake componentGroup in your library fragment, and use it in your installer. You do not need the include anymore, as long as the fake componentGroup from your fragment is referenced as a componentGroupRef in your main install, and your wixlib project is referenced in your installer project through VS (you said you'd already done this in your comments above).
Your library fragment might look something like this.
<Fragment id="fragment_id_may_not_be_needed">
<?define VersionNo = "6.86.123"?>
<ComponentGroup Id="c.define_version_num" />
</Fragment>
If the define for whatever reason doesn't work, try using a property instead. I'd be interested to know which works. Properties seem to work for me.
Then reference it in your main install like this:
<Feature Id="Main_installation" Title="Main installation" Level="1">
<!-- bringing in fragments from the shared libraries -->
<ComponentGroupRef Id="c.define_version_num" />
</feature>
Give it a whirl.

Installer conditionally picking up files

I'm building a Wix installer and I need two separate versions of said installer. One that picks up the latest development build of the project and one that picks up the latest release build. Currently my fragment looks like this:
<Property Id="Program.ReleaseBuild" Value="0" />
<?define ReleaseBuild = [Program.ReleaseBuild]?>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="InstallFolder">
<Component Id="TheExe" Guid="GUID_GOES_HERE">
<?if $(var.ReleaseBuild) = 1?>
<File Id="ProjectExe" Source="(Rel Project Path)/program.exe" />
<?else?>
<File Id="ProjectExe" Source="(Dev Project Path)/program.exe" />
<?endif?>
</Component>
</ComponentGroup>
</Fragment>
And I have a transform on the msi that transforms the file after build. But the problem is that the file is picked up on compile time not install time, so both version of the installer end up having the same file contained in them. Any idea how I can conditionally grab a dev file or a rel file in the same wix project?
If you want to create installation packages based on build quality (debug versus release), you can use two product configuration and select the source based on it. This way, you can run msbuild twice, one for each configuration. I don't understand the purpose of the transform you mentioned.
So here are steps you could take to accomplish this:
Create an empty solution.
Add your wixproj to it.
Add your csproj to it.
Add a reference of the csproj to the wixproj.
Modify your File[Source] to use the project reference, this way:
<File Source="$(var.MyProject.TargetPath)" Id="ProjectExe" />
The $(var.MyProject.TargetPath) will automatically get the exe from the correct path.
Create a batch file to run the msbuild twice, one for each configuration, with the following commands:
C:\> msbuild mySolution.sln /p:Configuration=Debug
C:\> msbuild mySolution.sln /p:Configuration=Release
The result will be two installation packages, one for each configuration.

Dealing with orphaned components while linking wixlib

I am tasked to build 2 installers based on the same wixlib supplied by 3rd party. Full installer includes all Components, Lite only the core stuff. I assume the wixlib has the following structure:
<Fragment>
<ComponentGroup Id="CoreStuff">
<!-- List of components for this bit, roughly 5MB -->
</ComponentGroup>
</Fragment>
<Fragment>
<ComponentGroup Id="ExtraStuff">
<!-- List of components for this bit, roughly 45MB -->
<ComponentRef Id="BigFile1"/>
</ComponentGroup>
<Component Id="BigFile1">
<File Id="BigFile1_bin" Name="BigFile1.bin"/>
</Component>
</Fragment>
The installer is build in msbuild. The components are included in to the project the following way:
<Feature Id="ThirdPartyStuff">
<ComponentGroupRef Id="CoreStuff"/>
<?if $(var.Configuration) = "Full"?>
<ComponentGroupRef Id="ExtraStuff"/>
<?endif?>
</Feature>
In the end, as expected, I get LGHT0267 error:
error LGHT0267: Found orphaned Component 'BigFile1'. If this is a Product, every Component must have at least one parent Feature. To include a Component in a Module, you must include it directly as a Component element of the Module element or indirectly via ComponentRef, ComponentGroup, or ComponentGroupRef elements.
Have anyone come up with workaround on how to selectively use components provided in wixlib? I could include ExtraStuff as separate Feature for user, but the goal here is to shrink the installer. I could ask politely ThirdParty to provide two separate wixlib's, but I'd like to avoid it.
I don't think that wix has the ability to consume only part of a wixlib package. Think of wixlibs as merge modules (without viewable tables). You can't consume only half of a merge module, and you can't consume only half of a wixlib.
I'm afraid you'll have to ask the third party to break up their wixlib into two packages.
After a struggle I have got the workaround, nasty workaround:
Create dummy wixproject and include wixlib as you would normally do.
Add dummy project as your dependency for final project
In post-build event of dummy project set powershell script to run, which will:
De-compile dummy.msi with binaries output (switch -x) using dark.exe
Craft new.wxs file based on dummy.wxs with inclusion of tags to make the components conditional
Include new.wxs in the final project