Wix Include file (.wxi) throws exception - wix

I am a beginner in Wix and we are trying to migrate from Installshield to Wix. However I am stuck with an error which I am unable to resolve. I have done my share of research online before posting this message and I am hoping to get some help from you experts in case someone had a similar problem and would be kind enough to point out the silly mistake I am making here.
Here is my Wix include file: properties.wxi
<Include>
<?define Language="1033"?>
<?define Manufacturer="ABC Inc"?>
<?define Name="TRIAL-MSI"?>
<?define UpgradeCode="....GUID...."?>
<?define Version="09.00.0021"?>
<?define Comments="Contact: team#abc.com"?>
<?define Description="TRIAL Application"?>
</Include>
And I am calling it in my code as follows:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?include properties.wxi ?>
<Product Id="*"
Name="${var.Name}"
Language="${var.Language}"
Manufacturer="${var.Manufacturer}"
UpgradeCode="${var.UpgradeCode}"
Version="${var.Version}" >
<Package Comments="${var.Contact}"
Description="${var.Description}"
InstallerVersion="200"
Keywords="Installer,MSI,Database"
Languages="${var.Language}"
Manufacturer="${var.Manufacturer}"
Compressed="yes"
Platform="x86" />
I am compiling my script on the command line:
candle -arch x86 -I properties.wxi trial.wxs
I keep getting errors as follows:
error CNDL0048 : The document element name 'Include' is invalid. A Windows Installer XML source file must use 'Wix' as the document element name.Source trace:
And I guess because Candle did not accept the include file, it throws exception for:
error CNDL0008 : The Product/#Language attribute's value, '${var.Language}', is not a legal integer value.
Could someone please help me with this? Any help is greatly appreciated.

I had this error when migrating wxs files to wxi
Setting the files Build Action property in Visual studio from Compile to Content fixed it.

The -I flag to candle is used to specify a directory to search for include files:
usage: candle.exe [-?] [-nologo] [-out outputFile] sourceFile
[sourceFile ...] [#responseFile]
-I add to include search path
The Wix preprocessor will automatically look in the directory of the current source file for include files so there is no reason to specify the include file on the command line. Your command line should only include the Wix source files:
candle -arch x86 trial.wxs
UPDATE:
Wix variables are inserted using $(var.VARIABLENAME). You have all of your variables surrounded with curly braces instead of parentheses.

Related

WIX Toolset Bundle get parent directory of path returned from ComponentSearch

I am attempting to have my WIX bundle use the previous install directory if an earlier version is already installed. The previous versions did not create a registry entry for the install location. As such I tried to use a ComponentSearch (Util Extension) to find the main executable. The install directory is the parent directory of the directory containing the executable. The ComponentSearch gives me the directory C:\InstallDirectory\DirectoryContainingEXE. How can I get C:\InstallDirectory?
<?xml version="1.0" encoding="utf-8"?>
<Include xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"
xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
<Fragment>
<util:ComponentSearch Id="ExeComponentSearch" Guid="{COMPONENT GUID}" Result="directory" Variable="InstallFolder"/>
</Fragment>
</Include>
I found a solution. The obvious solution is to use a file whose parent is the C:\InstallDirectory. Since I don't have any files in the C:|InstallDirectory that would not work. What I did have is a component that sets permissions on the C:\InstallDirectory. I used that component to get the directory. This would probably work with other types of components that do not contain a file. Maybe a registry that is the key path of the component?
<util:ComponentSearch Id="InstallDirectoryPermissionsSearch" Guid="{COMPONENT GUID}" Result="directory" Variable="InstallFolder"/>

How to resolve BootstrapperApplicationRef in Wix Toolset 3.11?

I get error messages related to my BootstrapperApplicationRef which I do not understand as these come from examples based on the well known wix book and also this example. Maybe it is because I use version 3.11 of the toolset (the book is based on 3.6)? My installer needs to install some software to download.
Here is my wxs:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Bundle Name="Awesome Software"
Version="1.0.0.0"
Manufacturer="Awesome Company"
UpgradeCode="c352f5c7-1dbe-416c-820d-685b058270d5">
<BootstrapperApplicationRef
Id="WixStandardBootstrapperApplication.RtfLicense" />
<Chain>
<ExePackage Id="DymoLabelSoftware"
SourceFile="DLS8Setup.8.5.1.exe"
DownloadUrl="http://download.dymo.com/dymo/Software/Win/DLS8Setup.8.5.1.exe" />
</Chain>
</Bundle>
</Wix>
Compiling results in the following error message:
Unresolved reference to symbol
'WixBootstrapperApplication:WixStandardBootstrapperApplication.RtfLicense'
Changing this element as described here, results in the following message:
Unresolved reference to symbol
'WixBootstrapperApplication:WixNetFxExtension'
Removing the BootstrapperApplicationRef results in another error message:
Unresolved reference to symbol
'WixBootstrapperApplication:WixNetFxExtension'
I can understand that something is unresolved but the found examples to resolve it simply do not work. How can I fix this? How to resolve this reference without getting an error message?
Update 1
I tried to make this work with a bootstrapper project instead. That partially solved my problem.
I just get another error message.
The system cannot find the file 'DLS8Setup.8.5.1.exe'.
This is really strange. The compiler should not try to find it at compile time. It is something to be downloaded at runtime.
I tried making this work by adding a dummy DLS8Setup.8.5.1.exe.
However, when looking up my result in my bin\Debug folder, I get an application that, when double clicking, does not show a user interface. This approach does not really solve my problems, it changes my problem.
It just want to have an installer that shows some user interface when starting and does execute a download. That's all.
Update 2
Using the other example to download just give other errors too.
So here's working sample based on your updates:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Bundle Name="DLS8SetupBootstrapper" Version="1.0.0.0" Manufacturer="me" UpgradeCode="ada71964-11c8-4877-9544-f72fe65579c0">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense" />
<Chain>
<ExePackage Id="DymoLabelSoftware"
Name="DLS8Setup.8.5.1.exe"
Compressed="no"
DownloadUrl="http://download.dymo.com/dymo/Software/Win/DLS8Setup.8.5.1.exe">
<RemotePayload Description="MyRemoteApp" ProductName="DLS8Setup.8.5.1.exe" Size="119087088" Version="8.5.1.0" Hash="204ecb5296290527418693f3a464b59a8801808f"/>
</ExePackage>
</Chain>
</Bundle>
</Wix>
Note that you need to know size in bytes and sha1 hash of your file. Also "Name" is important attribute.
To check hash I used this resource
Haven't found how to get size online so here's C# sample:
var sizeInBytes = new FileInfo("D:\\DLS8Setup.8.5.1.exe").Length;
So just update that variables for your file and you'll get your installer.
P.S. It will show that DLS8Setup installer GUI. If you need do it silent it will depend on every installer. As I get you want to use your own, not that one from example, so I can't do anything without your file.

How can I use an update condition to set variables in Wix?

We are using Wix V3.11 to build an msi setup for our C#-Application. We have a 32 Bit and an 64 Bit build for each version:
The preallocated installation path for the 32 Bit build is: 'C:\Program Files (x86)'.
The preallocated installation path for the 64 Bit setup is: 'C:\Program Files'.
We use the following declaration to set the paths:
<?define bitness = $(var.Platform) ?>
<?if $(var.Platform) = "x86" ?>
<?define ProgramFilesPath = ProgramFilesFolder?>
<?define Win64 = no?>
<?else?>
<?define ProgramFilesPath = ProgramFiles64Folder?>
<?define Win64 = yes?>
<?endif?>
Using the variable here:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="$(var.ProgramFilesPath)" Name="$(var.ProgramFilesPath)">
[... more folder ...]
</Directory>
</Directory>
The Problem: When the consumer changes the path for the first installation to e.g. 'C:/MyFolder' and executes an updade, then the msi setup moves the software to 'C:\Program Files (x86)' or 'C:\Program Files'.
Question: How can I keep the custom installation path 'C:/MyFolder' of the first installation on an update? Perhaps is there any 'update' condition I can use? My imagination:
<?define bitness = $(var.Platform) ?>
<?if UPDATE ?> <!-- here -->
<?if $(var.Platform) = "x86" ?>
<?define ProgramFilesPath = ProgramFilesFolder?>
<?define Win64 = no?>
<?else?>
<?define ProgramFilesPath = ProgramFiles64Folder?>
<?define Win64 = yes?>
<?endif?>
<?endif?>
Let's assume that by "update" you mean a major upgrade because it would be extremely strange if a patch or minor update moved all the files from one location to another.
If you are using the usual WiX property name, then the directory chosen by the user will be INSTALLFOLDER, although it's not clear if you are using that or TARGETDIR. Basically you can store the user's final choice in a registry item (or use the WiX "remember property" pattern). On a major upgrade you can retrieve that property and set your INSTALLFOLDER value to that directory on condition that WIX_UPGRADE_DETECTED is set (the default property id used in the major upgrade element). Presumably you will also suppress the browse dialog that allows the user to choose the folder.
Having said that:
It's not clear why you don't want the user to install the major upgrade to a new location if they want to, if the app continues to work.
Those default folders aren't really preallocated - they are just the standard defaults. They are the recommended locations so it might be better to disallow changing them because of the opportunities for unexpected behavior. For example, attempting to install the 32-bit MSI to the native program files folder on an x64 system will result in redirection to the program files (x86) location, which may surprise the user.

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.

RemotePayload: The system cannot find the file '' with type ''

Moving to WiX 3.6, I'm trying to make use of burn features to ease potential download/install of required pieces, such as a specific VC++ runtime.
I started small with just some "test.wxs", see below, which is OK for candle.exe:
$ candle test.wxs
Windows Installer Xml Compiler version 3.6.3303.0
Copyright (C) Outercurve Foundation. All rights reserved.
test.wxs
But light.exe chokes on it:
$ light test.wixobj -ext WixBalExtension
Windows Installer Xml Linker version 3.6.3303.0
Copyright (C) Outercurve Foundation. All rights reserved.
light.exe : error LGHT0103 : The system cannot find the file '' with type ''.
Could someone help with this (rather cryptic) error message?
It seems related to RemotePayload, since a modified version with local file works correctly. However, I'd like to save on package size and leave the downloading on the target machine if so needed.
Full content of "test.wxs" was:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Bundle Version="1.0.0.0"
UpgradeCode="e349236d-6638-48c5-8d8b-db47682b9aeb">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense" />
<Chain>
<!-- C++ Runtime -->
<ExePackage Name="vcredist_x64.exe"
DownloadUrl="http://www.microsoft.com/en-us/download/confirmation.aspx?id=2092" >
<RemotePayload CertificatePublicKey="F321408E7C51F8544B98E517D76A8334052E26E8"
CertificateThumbprint="D57FAC60F1A8D34877AEB350E83F46F6EFC9E5F1"
Description="Microsoft Visual C++ 2008 Redistributable Setup"
Hash="13674C43652B941DAFD2049989AFCE63CB7C517B"
ProductName="Microsoft Visual C++ 2008 Redistributable"
Size="4961800"
Version="9.0.30729.17" />
</ExePackage>
</Chain>
</Bundle>
</Wix>
Partial answer to my own question:
The error message disappears if I add the attribute Compressed="no" to the ExePackage element.
Documentation about "Compressed" attribute says: "Whether the package payload should be embedded in a container or left as an external payload" and its value can be "yes", "no", or "default".
Using "yes" or "default" triggers the error message. Using "no" doesn't.
I had the same trouble with another package (the .NET framework) and Wix 3.7. I used the Wix source code to find the appropriate package names and registry keys to test, and then pasted the relevant bits into my installer. Then, I intentionally set 'Compressed="yes"' because I wanted to embed the file in my installer instead of having it downloaded.
There was a report similar to yours posted in this mailing list thread:
Benjamin Mayrargue: If an ExePackage has a DownloadUrl and Compressed is set to yes, light failed with error LGHT0103: The system cannot find the file '' with type ''.
Markus Wehrle: Ok, I see. If you want to have the ExePackage compressed into your bootstrapper.exe (compressed="yes") you need to specify it using "Source" attribute. Cause it will be compressed into your boostrapper during compile time, you must not declare a DownloadUrl. If you specifiy compressed="no" your ExePackage gets downloaded from the DownloadUrl during the installation of your boostrapper.
Rob Mensching: More specifically, you cannot use RemotePayload element and Compressed='yes' on the ExePackage element together. That doesn't make sense and the bug here is that the compiler didn't give you an error message here saying that.
So yes, you've correctly identified the same fix to the problem.
The Compressed attribute, by the way, specifies 'Whether the package payload should be embedded in a container or left as an external payload.' That external payload can either be a RemotePayload or another file on the disk, but the typical setup is a single bootloader with all the resources embedded into it.
Using yes for the Compression attribute will allow your application and the VC++ runtime to be installed even if the user has a slow or nonexistent Internet connection. Remove the DownloadUrl and RemotePayload from your installer, and replace them with just Compressed="yes" like this:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Bundle Version="1.0.0.0"
UpgradeCode="e349236d-6638-48c5-8d8b-db47682b9aeb">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense" />
<Chain>
<!-- C++ Runtime -->
<ExePackage Name="vcredist_x64.exe"
Compressed="yes">
</ExePackage>
</Chain>
</Bundle>
</Wix>
Then download the vcredist_x64.exe file (yourself, once) and place it adjacent to your test.wxs file. Adjust 'Name' if you want it in a different location. Note that this will increase the size of your resulting bootstrapper by about the size of vcredist_x64.exe, so it's not a good idea if your users will be downloading your installer.
In my case the error was thrown because the filename/directory path was over 255 characters. The file exist yet the compiler is stating that the file doesn't exist.