I want to create an installer (msi) for my application. I want to add a folder that contains lot of files. So I use heat to create the wxs file for the folder. The wxs file created looks like this :
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<DirectoryRef Id="INSTALLDIR">
<Directory Id="dirD443000E4EC0AE53948090C1CD372519" Name="www">
<Component Id="cmp258C40B6C01189153117075B9889DA7C" Guid="{23189859-29AE-46E6-A940-0B2307344910}">
<File Id="fil0DE52257C6EF99D33B0974915A17454E" KeyPath="yes" Source="$(var.WwwPath)\3rdpartylicenses.txt" />
</Component>
<Component Id="cmp85367E8DB342884A004620F1E4153AE4" Guid="{00EBB07A-6178-4072-B47C-2D9130CB96A7}">
<File Id="filB62696889B5411543CB3DFD6E2A1270D" KeyPath="yes" Source="$(var.WwwPath)\color.c7a33805ffda0d32bd2a.png" />
</Component>
...
...
When I run my command light, I get a lot of error like this one (one per file):
error LGHT0204 : ICE80: This 32BitComponent cmp258C40B6C01189153117075B9889DA7C uses 64BitDirectory dirD443000E4EC0AE53948090C1CD372519
But the msi created seems to work as expected. But I would like to understand and remove that error if I could.
Any idea ?
Thanks
I've tried adding componnents atrributes Win64='yes' like in #Brian's comment, but it removed during build.
This answer helped me solve this issue.
Related
WiX 3.11.1 on Windows 10 Pro Version 1703 64-bit. NOT using Visual Studio. Using simple text files as follows.
Here is a test case of the situation I am finding.
myapp.wxs is this:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:netfx="http://schemas.microsoft.com/wix/NetFxExtension">
<Product Id="*"
Name="MyApp"
Language="1033"
Version="1.0.0.0"
Manufacturer="Me"
UpgradeCode="PUT-GUID-HERE">
<Package InstallerVersion="301"
Compressed="yes"
InstallScope="perMachine"
Manufacturer="Me"
Description="My App"
Keywords=".NET,Installer,MSI" />
<MediaTemplate EmbedCab="yes" />
<UIRef Id="WixUI_Minimal" />
<UIRef Id="WixUI_ErrorProgressText" />
<!-- ****************************************** -->
<WixVariable Id="WixUIDialogBmp"
Value="[CMP_Refresh_file]" />
<!-- ****************************************** -->
<Feature Id="MyFeature"
Title="MyApp Feature"
Description="Installs MyApp"
Level="1">
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="TestFolder" Name="TESTfolder" />
</Directory>
<Component Id="CMP_Refresh_file" Guid="*" Directory="TESTfolder">
<File Id="FILE_RefreshPNG" Source= "Refresh.png" KeyPath="yes" />
</Component>
</Fragment>
</Wix>
myapp.bat is:
"C:\Program Files (x86)\WiX Toolset v3.11\bin\candle.exe" myapp.wxs
"C:\Program Files (x86)\WiX Toolset v3.11\bin\light.exe" myapp.wixobj -ext WixUIExtension -ext WixUtilExtension
#pause
When I run the .bat file, it cannot find the CMP_Refresh_file (error LGHT0103 : The system cannot find the file). The folder TESTfolder is a direct sub-folder of the folder in which the .wxs file exists.
Substituting the full file path solves the issue. BUT that is not what I want as I will have a multitude of files and folders. (Also, if I put the file in the same folder as the .wxs file, of course, it finds it.)
I suspect it is purely a syntactic issue caused by my ignorance. In any case, I have tried endless variations of syntax for the Value of WixUIDialogBmp without joy (except the full name).
Help to resolve very much appreciated. Thanks!
Looking at your WiX code I can see that you are getting confused between the MSI destination and the source folder paths. The Directory tag is to create a folder on the machine where you run the MSI (where you want to deploy your application) - it has nothing to do with the source folders from where you package your files.
Replace your filepath with:
<File Id="FILE_RefreshPNG" Source= "\TESTfolder\Refresh.png" KeyPath="yes"/>
As you can see, the file -> source attribute path should be written with reference to your WXS file path.
If you are planning to deploy the refresh.png underneath the testfolder on the client machines then you got to move to closing </Directory> tag right after your <File> tag
Try <WixVariable Id="WixUIDialogBmp" Value="[#CMP_Refresh_file]" /> which references the installed path. See Formatted Strings for more info.
Came across this while trying to figure out a different issue with source file resolution. Isaiah4110's answer is misleading. The <Directory> structure can specify both the destination on the target machine and where to find the source files as long as the directory structure is the same. You just have to nest your <Component> elements within the corresponding directory elements and specify the Name attribute rather than Source.
In this case, the following should work:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="TestFolder" Name="TESTfolder">
<Component Id="CMP_Refresh_file" Guid="*">
<File Id="FILE_RefreshPNG" Name="Refresh.png" KeyPath="yes" />
</Component>
</Directory>
</Directory>
This works because the Source of a <File> defaults to the source path of the <Component>'s parent <Directory> element (if there is one) plus the Name. See: File element reference and How to specify source files. Unfortunately this logic does not seem to work when placing the <Component> outside of the <Directory> structure as the example in the question does.
I use auto-guids in my <Product> but can't figure out how to use them with <Module>. I only get this error:
The component X has a key file with path 'TARGETDIR\company...'.
Since this path is not rooted in one of the standard directories (like
ProgramFiles Folder), the component does not meet the criteria for
having an automatically generated guid.
Above, company is the value mapped to !(loc.ProductManufacturerFolderName).
The only problem is that's not true. My directories are rooted in ProgramFiles just like my product is and my product works fine:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFiles64Folder">
<Directory Id="MODULEINSTALLLOCATION" Name="!(loc.ProductManufacturerFolderName)">
<Directory Id="Data" Name="Data">
All my component declarations look roughly like this:
<Component Id="DocumentationParty_Business_TestCases_v1xlsx.component" Guid="{YOURGUID-1234-1234-84B3-C595A63428AD}" MultiInstance="yes">
<File Source="../../Development/Integration/SSIS/Documentation/Party_Business_Test Cases_v1.xlsx" KeyPath="yes" Id="DocumentationParty_Business_TestCases_v1xlsx.file" />
</Component>
Breaking it is easy, you only have to change the GUID to * and the above error results. This is broken:
<Component Id="DocumentationParty_Business_TestCases_v1xlsx.component" Guid="*" MultiInstance="yes">
<File Source="../../Development/ClaimsIntegration/SSIS/Documentation/Party_Business_Test Cases_v1.xlsx" KeyPath="yes" Id="DocumentationParty_Business_TestCases_v1xlsx.file" />
</Component>
I have a .wxs file for each directory to which components will be installed. All my component-holding .wxs files have the following structure:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<ComponentGroup Id="DatabasePolicy_Files">
<ComponentRef Id="DatabasePolicyCreateDatabasecmdtemplate.component" />
</ComponentGroup>
<DirectoryRef Id="DataPolicy">
<Component Id="DatabasePolicyCreateDatabasecmdtemplate.component" Guid="*" MultiInstance="yes">
<File Source="../../Development/Database/Policy/CreateDatabase.cmd.template" KeyPath="yes" Id="DatabasePolicyCreateDatabasecmdtemplate.file" />
</Component>
</DirectoryRef>
</Fragment>
</Wix>
Each <ComponentGroup> is included in my master .wxs file through a <ComponentGroupRef>. This works in all my MSI projects and breaks only now that I've started working with merge modules. Also, I've tried commenting out all components except for which matches the above definition and it still breaks on the same error.
What is the problem?
I've had this similar issue myself and based on your error message it's probably the same.
Try adding a ComponentGuidGenerationSeed, that should solve your issue. The ComponentGuidGenerationSeed acts on all subfolders as well so a single one at the top-level is sufficient for all folders.
Example:
<Directory Id="DOCUMENTATIONFOLDER" Name="Documentation" ComponentGuidGenerationSeed="a9f690d3-22b3-488f-bdac-bb665c25933c"/>
http://wixtoolset.org/documentation/manual/v3/xsd/wix/directory.html
The Component Guid Generation Seed is a guid that must be used when a
Component with the generate guid directive ("*") is not rooted in a
standard Windows Installer directory (for example, ProgramFilesFolder
or CommonFilesFolder).
I am running the following command:
heat.exe dir bin\Release -sfrag -sreg -var var.sourcebin -dr myappfolder -cg myapp_comp_group
This generates a nice wxs file that looks a bit like this:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<ComponentGroup Id="myapp_comp_group">
<ComponentRef Id="cmpE519314043C2FFE1104E067D33CBC652" />
<ComponentRef Id="cmp0431CFEC47E793CE59C185A8BDD9D865" />
</ComponentGroup>
</Fragment>
<Fragment>
<DirectoryRef Id="myappfolder">
<Directory Id="dir4ADCEBD4F8C9DC384017088D96B7A1C3" Name="somebinfolder">
<Component Id="cmpE519314043C2FFE1104E067D33CBC652" Guid="EB84C1A8-7BF5-4967-878D-8DAD9DFFA0A6">
<File Id="filD8C8D39058B0FF5C9608B1F99B0CD5BA" KeyPath="yes" Source="$(var.sourcebin)\app.config" />
</Component>
</Directory>
</DirectoryRef>
</Fragment>
</Wix>
I am using this by heat generated wxs file in my project, but I get an error, because the $(var.sourcebin) has not been set.
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?define sourcebin="C:\svn\myapp\bin\Release"?>
<!-- leaving some stuff out of course -->
<Module>
<ComponentGroupRef Id="myapp_comp_group"/>
</Module>
</Wix>
error CNDL0150: Undefined preprocessor variable '$(var.sourcebin)'.
How do I define this variable so it is picked up by the heat generated file? I don't want to change the heat generated file manually, because it is re-generated every time.
Open project Properties, Choose Build tab and add preprocessor variable as needed.
sourcebin="C:\svn\myapp\bin\Release";
In the define section use:
<?define sourcebin = $(var.sourcebin)?>
Heat command you can leave as it is.
This will be the same when you will need to pass variables from msbuild (Wixproj file) to other files in your project(wxs,wxi...). Common use when using TFS.
I've got a Wix project made up of several fragments. One of those fragments has the database components, another has a component that manipulates xml files.
When I include the XmlFile element to manipulate a file, the databases defined by the SqlDatabase do not get created. If I comment out the XmlFile, then the databases do get created.
Here are the two wix files with fragments that are being used:
Database:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:sql="http://schemas.microsoft.com/wix/SqlExtension">
<Fragment>
<DirectoryRef Id="TARGETDIR">
<Component Id="Database1Creation" Guid="GUID_HERE">
<sql:SqlDatabase Id="Database1"
Server="[DATABASE_SERVER]" Database="[DATABASE_NAME]"
CreateOnInstall="yes" ConfirmOverwrite="no"
DropOnUninstall="yes">
</sql:SqlDatabase>
</Component>
</DirectoryRef>
</Fragment>
</Wix>
Xml Manipulation:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:sql="http://schemas.microsoft.com/wix/SqlExtension"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLDIR" Name="MyDirectory">
<Component Id="ServiceExecutables" Guid="GUID_HERE">
<File Id="File1" Name="File1.xml" Source="Source/File1.xml" />
<util:XmlFile Id="UpdateFile1" File="[INSTALLDIR]File1.xml" Action="setValue" ElementPath="//SomeContainer/SomeElement" Value="[SOME_VALUE]" />
</Component>
</Directory>
</Directory>
</Directory>
</Fragment>
</Wix>
There are other things that are also installed, but they don't appear to have any influence on the issue (I've removed everything else and tested the install).
When looking at the install logs when using XmlFile and when not, they are almost exact copies of each other, except that the SqlDatabase calls would be completely missing, and the XmlFile calls would be in their place.
Is there a known bug here? Or am I doing something I shouldn't be? This isn't a killer for our app, since I can move the things I'm putting in the xml file into the registry, but I'd rather not do that.
I am using Wix 3.5.
Good news, build 1616 fixes this. Update Wix ASAP.
So, I am trying to create a merge module where I have multiple wxs files. I thought that everything was OK since the build of my project succeeded. Later, I realized that the path used in Source attribute for one of the secondary wxs files was completely wrong but the compiler didn't give the following error:
The system cannot find the file '..\..\release_area\WrongPath\Component2.dll'.
In the secondary wxs file, I added a DirectoryRef element referencing the folder AssemblyFolder in the main wxs file to create the reference between the two files.
Main wxs file:
<Module Id="MyModule" Language="1033" Version="1.0.0.0">
<Package InstallerVersion="200" Platform="x86"/>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="AssemblyFolder">
<Component Id="Component1.dll">
<File Id="Component1.dll" Name="Component1.dll"
KeyPath="yes" Assembly=".net"
Source="..\..\release_area\Comp\Component1.dll" />
</Component>
</Directory>
</Directory>
</Module>
Secondary wxs file:
<Fragment>
<DirectoryRef Id="AssemblyFolder">
<Component Id="Component2.dll">
<File Id="Component2.dll" Name="Component2.dll"
KeyPath="yes" Assembly=".net"
Source="..\..\release_area\WrongPath\Component2.dll" />
</Component>
</DirectoryRef>
</Fragment>
Just to clarify: To test, I copied my <Component Id="Component2.dll"> directly in the main wxs and I got the error: The system cannot find the file '..\..\release_area\WrongPath\Component2.dll'.
So, my guess is that the reference between the secondary wxs file and the main wxs file is completely wrong and that's why the compiler doesn't validate the file path but I cannot figure out what is the problem.
The issue isn't in the compiler (candle.exe). Candle.exe creates the separate "sections" (Module and Fragment are both "sections"). It is the linker (light.exe) that is responsible for pulling it all together. Light.exe starts at the "entry section" (Product, Module or Patch) and follows the references down from there. Since you don't have a reference from your Main.wxs to your Secondary.wxs, the stuff in the Secondary.wxs is never pulled in. To resolve this just add:
<ComponentRef Id="Component2.dll"/>
somewhere under your Module element (I usually put them at the end). If you get lots of Components then ComponentGroup and ComponentGroupRef becomes useful.