Reference a heat generated wxs file from a merge module - wix

I want to create a trivial merge module that contains all the files of a directory called "build" and installs them to the program files folder. I will use heat to generate a wxs file with all these files, and I want this to be separated from the wxs file I edit manually for the merge module. How do I reference the heat generated file from my other merge module wxs file?
I generate my heat wxs file like this:
heat dir build -cg heatComponent -gg -var var.buildFolder -dr ProgramFilesFolder -srd -out heatComponent.wxs
I know how to create an msi file of this:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Name='product' Id='9f6edf70-539a-11e4-916c-0800200c9a66' UpgradeCode='bb651370-539a-11e4-916c-0800200c9a66'
Language='1033' Codepage='1252' Version='1.0.0' Manufacturer='Test'>
<Package Id='*' Description="A product" InstallerVersion='301' Languages='1033' Compressed='yes' SummaryCodepage='1252' Platform='x64'/>
<Media Id="1" Cabinet="product.cab" EmbedCab="yes" />
<Directory Id='TARGETDIR' Name='SourceDir'>
<Directory Id='ProgramFilesFolder'/>
</Directory>
<Feature Id="Files" Title="Main Feature" Level="1">
<ComponentGroupRef Id="heatComponent"/>
</Feature>
</Product>
</Wix>
But how do I do reference the ComponentGroup when I want to output a merge module? If I change the Product element to a Module element it complaints about the Feature element. If I remove that it works, but I do not get any files in my msm.

Based on the heat command you posted, try making your module definition (module1.wxs) look something like this:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Module Id="Mod1" Language="0" Version="1.0.0">
<Package Id="YOUR-GUID" Manufacturer="Acme" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder" />
</Directory>
<ComponentGroupRef Id="heatComponent"/>
</Module>
</Wix>
Then you can call candle like so:
candle module1.wxs heatComponent.wxs -dbuildFolder="FOLDER-CONTAINING-FILES-HERE"
Followed by light like so:
light module.wixobj heatComponent.wixobj -o Module1.msm

Related

How to specify source location in wix

How do I make the sources specified in a heat generated file visible to the build?
I've got a project named Foo and a project named FooSetup. They have the same parent directory. To generate the list of files to install I ran in FooSetup:
heat dir "..\Foo\bin\Release" -cg "SomeGroupName" -ag -template:fragment -out heat.wxs
Now when I try to build the installer, I get:
The system cannot find the file 'SourceDir\Foo.dll'.
(that file does exist in the Release directory)
The path to Foo\bin\Release is specified in include paths in the FooSetup project properties.
What am I missing here - why is none of the listed files found?
WiX Learning Resources: A couple of links to resources on WiX:
Click-by-click WiX and Visual Studio
Long list of WiX links
WiX Preprocessor Variables: What is SourceDir? Rob Mensching (WiX creator) on SourceDir.
As explained here you can change SourceDir to a compiler variable:
Heat.exe: Something like this:
"%WIX%bin\heat.exe" dir . -sfrag -suid -ag -var MyReleasePath -out MySource.wxs
You will get something like this:
<!-- Extract -->
<Component Id="MyFile.exe" Guid="*">
<File Id="MyFile.exe" KeyPath="yes" Source="$(MyReleasePath)\MyFile.exe" />
</Component>
<!-- End of Extract -->
WiX Sample: Then you insert this into your source. Something like this:
<!-- START OF COMPILER VARIABLES: -->
<?define MyVersion = "1.0.0.0" ?>
<?define MyReleasePath = "C:\My Releases\Wix Testing\" ?>
<!-- END OF COMPILER VARIABLES: -->
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="WiX Testing" Language="1033" Version="$(var.MyVersion)"
Manufacturer="WiX Testing" UpgradeCode="PUT-GUID-HERE">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<!-- Enable line below for GUI in MSI -->
<!-- <UIRef Id="WixUI_Mondo" /> -->
<MediaTemplate EmbedCab="yes" />
<Feature Id="Main" Title="Main Feature" Level="1" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="WiX Testing">
<!-- Essential part follows: -->
<Component Feature="Main">
<File Source="$(var.MyReleasePath)MyFile.exe"></File>
</Component>
<!-- End of Essential part -->
</Directory>
</Directory>
</Directory>
</Product>
</Wix>
Batch File Compile: Visual Studio takes care of most of the build issues once you have defined the variables. If you want to compile "manually", here is a quick sample:
"%WIX%bin\candle.exe" MySource.wxs -ext WixUIExtension >> Build.log
"%WIX%bin\light.exe" -out Test.msi MySource.wixobj -ext WixUIExtension >> Build.log
Links:
WiX sample for other issue at bottom

How can I copy an existing file to a MyDocuments directory in WiX?

TL:DR
How can I tell WiX to copy files from the installer to a specified directory within the user MyDocuments folder?
I'm trying to write a rudimentary installer using WiX.
I've figured out how to reference the projects and the executable, but I want the installer to write a few files to the MyDocuments directory of the user installing the program.
Why not AppData? Because most users don't know how to access the AppData directory and the program should allow the relatively easy access to the files in question, so that they can add or remove the files as they see fit, for good or for ill.
Additionally, if the user decides to remove those files, I would prefer for the program NOT to yell at them when on subsequent runs, as the program has internal checks to make sure the files exist before referencing them, and if they do not, references them internally.
What would I need to add to the following WiX script to tell it "Put MySetupInstallerDocument.txt in MyDocuments/MySetupProject/MySetupProjectFiles" where MySetupInstallerDocument.txt is located within the same folder as the .wxs file?
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product
Id="*" Name="MySetupInstaller" Language="1033" Version="1.0.0.0" Manufacturer=""
UpgradeCode="07a36861-41cf-40e4-a1b6-eb970bc305ff">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade
DowngradeErrorMessage="Bla bla bla" />
<MediaTemplate />
<Feature Id="ProductFeature" Title="MySetupInstaller" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="MySetupInstaller" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="ProductComponent">
<File Source="$(var.MySetupProject.TargetPath)" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>

How to set the variable -var defined in heat.exe to the wxs file?

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.

Converting an EXE file to XML

I have an executable package (.exe) of an application. How do convert this executable to an MSI package?
I am aware of converting a .msi into .wxs using the following.
dark.exe installer.msi
Here's a great little mini-tutorial. It's probably all you need:
http://www.codeproject.com/Tips/105638/A-quick-introduction-Create-an-MSI-installer-with
1) Create Wix XML file
EXAMPLE:
<?xml version="1.0"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
</Wix>
2) Build an MSI for your .exe
EXAMPLE:
candle example.wxs
light example.wixobj
3) Voila. If there's nothing more complicated than "install the .exe", you're done!
Take the .msi to a difference PC and test.
The above link also discusses other scenarios, if you need them. For example:
ANOTHER, MORE REALISTIC .WIX FILE:
<?xml version="1.0"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" UpgradeCode="12345678-1234-1234-1234-111111111111"
Name="Example Product Name" Version="0.0.1" Manufacturer="Example Company Name" Language="1033">
<Package InstallerVersion="200" Compressed="yes" Comments="Windows Installer Package"/>
<Media Id="1" Cabinet="product.cab" EmbedCab="yes"/>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLDIR" Name="Example">
<Component Id="ApplicationFiles" Guid="12345678-1234-1234-1234-222222222222">
<File Id="ApplicationFile1" Source="example.exe"/>
</Component>
</Directory>
</Directory>
</Directory>
<Feature Id="DefaultFeature" Level="1">
<ComponentRef Id="ApplicationFiles"/>
</Feature>
</Product>
</Wix>
Here is the "standard" tutorial, with much other information:
http://wix.tramontana.co.hu/
Bon soir (at least here in California ;))
'Hope that helps!
Use UniExtract to extract the MSIs from the EXE, then apply dark on the MSIs.

patching using purely WIX

I am struggling with creating a patch purely using WIX and I was hoping if someone could guide me in the right direction.
I have a few hundred source files and I run heat against them to create a harvest file followed by creating a package using candle and light.
I need to change a few configuration files and I create a 2nd package with the changes.
Using Torch and pyro I create the .wixmst file and then when trying to create the msp file, pyro complains with the following error.
pyro.exe : error PYRO0252 : No valid transforms were provided to attach to the patch. Check to make sure the transforms you passed on the command line have a matching baseline authored in the patch. Also, make sure there are differences between your target and upgrade.
my question really is: what should patch.wxs contain?
Here is what my patch.wxs looks like:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Patch
AllowRemoval="yes"
Manufacturer="sample llc"
MoreInfoURL="sample.com"
DisplayName="Env Patch"
Description="Env Specfic Patch"
Classification="Update"
>
<Media Id="5000" Cabinet="RTM.cab">
<PatchBaseline Id="RTM" />
</Media>
<PatchFamilyRef Id="EnvPatchFamily" />
</Patch>
<Fragment>
<PatchFamily Id='EnvPatchFamily' Version='1.0.0.0' ProductCode="PUT-GUID-HERE" Supersede='yes' >
**********************************************
What component Ref should I put in here
heat creates a component group and I can't
put ComponentGroupRef in here
**********************************************
</PatchFamily>
</Fragment>
</Wix>
I am using Wix patching as described in this link:
http://wix.sourceforge.net/manual-wix3/wix_patching.htm
However, it doesn't consider source wix file created using heat.
Can someone tell me what am I doing wrong here?
Hitesh,
For me heat creates a component group like this:
<Fragment>
<ComponentGroup Id="MyFiles">
<ComponentRef Id="cmp2AA1A30564C621322ECB3CDD70B1C03C" />
<ComponentRef Id="cmp788C978F16E473D4FD85720B5B75C207" />
</ComponentGroup>
</Fragment>
heat command:
"%WIX%\bin\heat.exe" dir slndir\bin\Release -cg MyFiles -gg -scom -sreg -sfrag -srd -dr INSTALLDIR -out ..\Wix\MyFiles.wxs -var var.BinOutputPath -nologo -v -ke -t wixtransform.xsl
And in patch.wxs:
<Fragment>
<PatchFamily Id='ProductPatchFamily' Version='1.3.0.0' Supersede='yes'>
<ComponentRef Id="cmp2AA1A30564C621322ECB3CDD70B1C03C" />
<ComponentRef Id="cmp788C978F16E473D4FD85720B5B75C207" />
</PatchFamily>
</Fragment>
Take care: there is no ProductCode attribute in PatchFamily tag
I would also like to mention that PatchFamily elements are optional when building a patch, and are intended to allow fine grained control over exactly what will get patched. In most cases I find that I want to include all differences between 2 versions of an MSI when building a patch, in which case I omit the PatchFamily altogether. In your case, the resulting patch WXS would look like the following:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Patch
AllowRemoval="yes"
Manufacturer="sample llc"
MoreInfoURL="sample.com"
DisplayName="Env Patch"
Description="Env Specfic Patch"
Classification="Update"
>
<Media Id="5000" Cabinet="RTM.cab">
<PatchBaseline Id="RTM" />
</Media>
</Patch>
</Wix>
I hope this answer helps anyone with a similar question, that is not wanting to manually construct patch families, not wanting to manually includeComponentRef every time they need to build a patch.
I faced the same issue, the fix for this error is to add the GUID to the component and it should remain same for both the versions of msi.
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate />
<Feature Id="ProductFeature" Title="WixPatch" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="WixPatch" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER" >
<Component Id="File1" **Guid="3A64BE7A-BBEC-40AD-8319-45C602734146"**>
<File Source="D:\V2\File1.txt" Name="File1" KeyPath="yes" DiskId="1" Id="F1"/>
</Component>
</ComponentGroup>
</Fragment>