WiX installer conditional compilation? - windows

I have two builds of my main executable: standard and premium. For simplicity of development they are built from a single solution in Visual Studio by changing a special #define variable.
Now I'm curious if it's possible to do the same with the WiX installer for this project?
I basically need to control the inclusion of only one of the following xml nodes:
1: For standard version MSI:
<Product Name='Foobar 1.0 - Standard'
Id='8E9CF27F-B92F-4CB3-BBA0-0AAE5376D5EB'
UpgradeCode='20A89269-D206-490D-9134-349594662619'
Language='1033'
Codepage='1252'
Version='1.0.0'
Manufacturer='Acme Ltd.'>
and later:
<Component Id='MainExecutable' Guid='E1FE2BBE-C72D-4F27-A66D-78417F597D7A'>
<File Id='FoobarEXE' Name='FoobarAppStandardl10.exe' DiskId='1' Source='FoobarApplStandard10.exe' KeyPath='yes'>
2: For premium version MSI:
<Product Name='Foobar 1.0 - Premium'
Id='8E9CF27F-B92F-4CB3-BBA0-0AAE5376D5EC'
UpgradeCode='20A89269-D206-490D-9134-34959466261A'
Language='1033'
Codepage='1252'
Version='1.0.0'
Manufacturer='Acme Ltd.'>
and then:
<Component Id='MainExecutable' Guid='E1FE2BBE-C72D-4F27-A66D-78417F597D7B'>
<File Id='FoobarEXE' Name='FoobarAppPremiuml10.exe' DiskId='1' Source='FoobarApplPremium10.exe' KeyPath='yes'>
PS. I can obviously make 2 WiX projects... I'm seeking a way to do it in one.

I found it. Here it is for whoever else is interested.

In my case, i need to pass the symbol compilation to the project that will compile. I solved recompiling and passing the symbols.
For this, edit the wix project e.g. "xx.wixproj", and at the end of the file insert:
<Target Name="MyName" AfterTargets="AfterResolveReferences">
<MSBuild Projects="Path\xx.csproj" Properties="Configuration=$(Configuration);Platform=$(Platform);DefineConstants=$(DefineConstants)%3bMYSYMBOL;OutputPath=$(OutputPath)" />
</Target>
Unfortunately, this solution in vs 2017 (with .netstandard dlls) and WiX 4, not run.

Related

How to read content of text file in Wix Toolset Bootstrapper

I am using the WiX toolset to build an installer, I want to read the version from a text file. The text file is located in mybootstrapper like below:
below is the code where i want to read the content of text file
<Bundle IconSourceFile='product.ico'
Name="Retail Grip"
Version="Version.txt" <!-- i know this is not correct -->
Manufacturer="Company Name"
UpgradeCode="PUT-GUID-HERE">
Oh, it is a WiX bundle - and that's "Wax"? I hear it is a WiX tool of sorts? I am not sure exactly how it works (screenshot down the page in that link). Maybe there are restrictions on the use of compiler variables when using it?
I wrote the below before I saw that Wax file and I thought you had a normal WiX source and not a bundle source. Either way, let me add what I wrote and see if it helps. Similarities.
Also: Neil Sleightholm's WiX Burn Template (towards top). Give that link a spin first please.
In a regular WiX file you could use a pre-processor variable: $(var.CurrentVersion) (compiler variable). Something like this:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?define UpgradeCode="PUT-GUID-HERE"?>
<?define CurrentVersion="1.0.0.0"?>
<Product Id="*" Name="Sample" Language="1033" Version="$(var.CurrentVersion)"
Manufacturer="Someone" UpgradeCode="$(var.UpgradeCode)">
<...>
You can put the variables in its own "include file": Variables.wxi.
<Include>
<?define UpgradeCode="PUT-GUID-HERE"?>
<?define CurrentVersion="1.0.0.0"?>
</Include>
Larger sample here for this approach (do have a quick skim of this one).
And then include the file in your main WiX source:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?include Variables.wxi ?>
<Product Id="*" Name="Sample" Language="1033" Version="$(var.CurrentVersion)"
Manufacturer="Someone" UpgradeCode="$(var.UpgradeCode)">
<...>
There are also localization variables: WiX (Windows Installer Xml), Create universal variables - link time variable resolution (light.exe), as opposed to the compile time resolution of pre-processor variables (candle.exe). Some context.
Some Relevant Links:
Localization Variables in use: Wix toolset license agreement multi-languages issue
How to make Win64 attribute as a variable in wixlib?
https://helgeklein.com/blog/2014/09/real-world-example-wix-msi-application-installer/
With WiX Include files, you can keep simple values separate from the bulk of the WiX markup. With WiX preprocessing, you can define named substitution values used in attributes or text nodes or conditional compilation, and then refer to them as $(var.name).
-- Version.wxi --
<?xml version="1.0" encoding="utf-8"?>
<Include>
<?define Version="1.2.3" ?>
</Include>
-- Bundle.wxs --
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?include "Version.wxi" ?>
<Bundle
Version="$(var.Version)"
…
It is sometimes convenient to generate include files in a source project in anticipation of them being used downstream, or generate them as the first steps of a WiX project.
I see you are using Visual Studio for your WiX Bootstrapper project. A Visual Studio project is a specialized MSBuild project (as are most types of Visual Studio projects). That means you can put general MSBuild things into the project file. You can open the .wixproj file as an XML file in an XML editor (such as Visual Studio).
MSBuild allows you define new tasks either from an external DLL or inline, using a .NET language. In this case, a few lines of C# will do fine to define the task. Then you would invoke it before the main build tasks. Like many build systems that use MSBuild, WiX ensures the target BeforeBuild is executed before it gets to work. So, you just have to define BeforeBuild.
The task is named CreateVersionWxi.
<UsingTask
TaskName="CreateVersionWxi"
TaskFactory="CodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll">
<ParameterGroup />
<Task>
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Using Namespace="System.Xml.Linq" />
<Code Type="Fragment" Language="cs"><![CDATA[
var version = File.ReadAllText("version.txt");
var wxi =
new XDocument(
new XComment("*** GENERATED FILE. DO NOT EDIT ***"),
new XElement("Include",
new XProcessingInstruction("define", "Version='" + version + "'")));
wxi.Save("version.wxi");
]]></Code>
</Task>
</UsingTask>
<Target Name="BeforeBuild">
<CreateVersionWxi />
</Target>
Finally, if you add version.txt to your project with its Build Action, say, as Content, the project will be seen as needing to be rebuilt whenever version.txt changes. That will help if you have the WiX project open in Visual Studio while you are externally changing version.txt.
You don't need to add Version.wxi to your project but doing so increases its visibility to future maintainers.
Tip: Some Visual Studio users are more familiar with the Build Events on the project pages. To clue them in, you could enter this as a pre-build event command line: REM See the BeforeBuild target in the .wixproj file

Create Nuget package with framework target for win8 app and Visual Studio 2013

I'm trying to prepare a NuGet package for targeting x64 Win8 Store Apps. Requirements are to work on Visual Studio 2013 which supports so far (and to my knowledge) NuGet 2.8.6.
So I have a .nuspec file like this:
<files>
<file src="lib\netcore45\wwapi.dll" target="lib\netcore45\wwapi.dll" />
<file src="lib\netcore45\wwapi.winmd" target="lib\netcore45\wwapi.winmd" />
<file src="lib\portable-wpa81\wwapi.dll" target="lib\portable-wpa81\wwapi.dll" />
<file src="lib\portable-wpa81\wwapi.winmd" target="lib\portable-wpa81\wwapi.winmd" />
<file src="runtimes\win8-x64\native\wwapi.dll" target="runtimes\win8-x64\native\wwapi.dll" />
<file src="runtimes\win8-x64\native\wwapi.winmd" target="runtimes\win8-x64\native\wwapi.winmd" />
</files>
And I used References element like this:
<references>
<group targetFramework=".NETCore4.5">
<reference file="wwapi.winmd" />
</group>
<group targetFramework="portable-wpa81">
<reference file="wwapi.winmd" />
</group>
</references>
However the libraries located under runtimes folder do not get added to the x64-targeted project I'm using and therefore it doesn't build. Is there a way to achieve this using following configuration:
Visual Studio 2013;
Nuget 2.8.6;
NuGet Target Framework Monikers;
I'm aware of using PowerShell scripts or having different packages for x86 and x64 but I'm looking for a solution similar to the NuGet 3.0 and Win10 UAP.
Use the build folder to achieve automatic selection of x86/x64 versions of a library for W8. This is supported in VS2013, since was added in Nuget 2.5 (see Nuget 2.5 release notes: Automatic import of msbuild targets and props files)
Basically the solution consists in adding a file at build/.targets having the references to the correct dlls.
Here are some useful links with examples: link1 and link2

How to tweak / customize the Visual Studio / MS Build process to execute my new target after a successful build?

I've created a custom task to get me a three-part version number of my assembly that was built in MSBuild.
I've created a custom <Target Name="GetVersion"> for this, and it works nicely - the three-part version number(1.5.2) is stored into a ThreePartBuildNumber property in MSBuild.
But how do I tell MSBuild inside Visual Studio 2010 to call this target once it's compiled my assembly, and before creating my WiX Setup project (where I'd like to set the WiX install script's Product/#Version to this three-part version number automatically)?
How can I "plug" this new target into the usual VS 2010 build process?
Update:
OK, I've managed to get this into the *.wixproj file which is also a MSBuild file, really. In the <Target Name="BeforeBuild">, I can successfully determine the three-part version number, and it's stored inside a MSBuild property called ThreePartVersionNumber.
But how on earth can I now access this properly filled MSBuild property in my WiX setup? I tried setting <Product Version="$(var.ThreePartVersionNumber) ...>, but that doesn't work - it doesn't seem to find the variable.... neither works with the sys. or env. prefixes, either....
So how do I make this MSBuild property that has the information I need "visible" to the WiX installer script/XML ?!?!?!? I can't seem to see the forest for all those angle brackets .....
Use the /verbosity:d switch to get a full view of all the targets that were performed and their rough reason for being called (dependent-on). Identify the exact thing you want to be before or after or dependent upon. Besides using the depends attributes on your Target, there are also various properties that are used to collect dependencies for various purposes. You can identify these by using /preprocess and then looking up the Targets that catch your eye from the previous step.
I've found that specific answers often don't work, as the build situation is different for my language or the exact inclusion order matters or other minor things; so this is how I've found the real triggers in my case.
What I've done in the end:
inside my WiX setup project, in the myproject.wixproj MSBuild file, I've added a new custom task like this:
<UsingTask TaskName="GetThreePartVersion" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<AssemblyPath ParameterType="System.String" Required="true" />
<ThreePartVersion ParameterType="System.String" Output="true" />
</ParameterGroup>
<Task>
<Using Namespace="System.Diagnostics" />
<Code Type="Fragment" Language="cs">
<![CDATA[
Log.LogMessage("Getting version details of assembly at: " + this.AssemblyPath, MessageImportance.High);
Version v = Version.Parse(FileVersionInfo.GetVersionInfo(this.AssemblyPath).FileVersion);
this.ThreePartVersion = v.ToString(3);
]]>
</Code>
</Task>
</UsingTask>
and then in the BeforeBuild target, I added these lines to call this task and define a WiX constant with the results:
<Target Name="BeforeBuild">
<GetThreePartVersion AssemblyPath="$(SolutionDir)Plugin\$(OutputPath)Swisscom.Vidia.Plugin.dll">
<Output TaskParameter="ThreePartVersion" PropertyName="ThreePartVersionNumber" />
</GetThreePartVersion>
<PropertyGroup>
<DefineConstants>ThreePartBuildVersion=$(ThreePartVersionNumber)</DefineConstants>
</PropertyGroup>
<Message Text="Three-part version: $(ThreePartVersionNumber)" />
</Target>
and now in my WiX project.wxs file, I can reference that constant that's been defined, and use it for the <Product Version="..." ... /> attribute:
<Product Id="*" Name="MyProject" Language="1033"
Version="$(var.ThreePartBuildVersion)" ......>
It took a bit of twiddling and a lot of trial & mostly error until I finally got it right - but this is the way it works for me now. Hope this might help some other soul some day....

how to include a folders containing images to product.wxs file in wix project

I am new to WiX, I am facing a problem in adding a folder which contains necessary images and icons to wix project, I am able to include required dlls and files using
<Component Id='HelperLibrary'>
<File Id='HelperDLL' Name='Helper.dll' />
</Component>
Any help will be appreciated.
As you are working with a .NET project, adding of DLLs to the WIX installer from the project output folder of the referred project can be done as following by using the TargetDir item:
<Component Guid="*" Directory="BinFolder">
<File Id="BinFolder.Helper.dll" Source="$(var.ProjectToPackage.TargetDir)Helper.dll"/>
</Component>
Similar way, you can add other files from the project whihch doesn't come under the project output can be added as following using the ProjectDir item from the referred project:
<Component Guid="*" Directory="ImageFolder">
<File Id="ImageFolder.Icon.jpg" Source="$(var.ProjectToPackage.ProjectDir)Icons\Icon.jpg" />
</Component>
Note: Here it is expecting that your WIX project is having reference to the project to be packaged and the project reference is named as ProjectToPackage in this example above.

LGHT0132 Adding Json.Net to GAC with Wix

I'm building a Wix installer that is adding json.net to the GAC (I know... GAC bad, but orders are orders). During the build I get this error:
error LGHT0132: The assembly file 'path\Newtonsoft.Json.dll' appears
to be invalid. Please ensure this is a valid assembly file and that
the user has the appropriate access rights to this file. More
information: HRESULT: 0x8013101b
The json.net I'm using is for .NET 4. If I use json.net for .NET 2 it builds fine, no problems at all.
My registration is as simple as this:
<Component Id="newtonsoft.json.gac.comp" Directory="GAC">
<File Id="newtonsoft.json.gac.file" KeyPath="yes" Assembly=".net" Source="path\Newtonsoft.Json.dll" />
</Component>
I'm using Wix 3.5. Any ideas would be appreciated.
I just tested this against WiX v3.8 and it works fine for me. I'm not aware of any changes in that part of the WiX toolset since v3.5 RTM'd. Error 0x8013101b means "This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded". That almost certainly means that the WiX toolset is running on CLR2 and cannot read the CLR4 assemblies.
Your light.exe.config file should look like the following:
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" />
<supportedRuntime version="v2.0.50727" />
</startup>
</configuration>
Order is important. Try removing the v2.0.50727 line. That will force the WiX toolset to only run on CLR4. If that fails, you'll want to investigate your environment.

Resources