
Adding a file to a directory
Markup to copy files to the end user's computer is probably going to make up the bulk of your installer. That's because for each file you want to install, which may number in the hundreds, there will be a corresponding XML element in your .wxs
file to represent it. In this recipe, we'll cover the basics—installing a single text file to a directory that we'll create under Program Files
. All file-types, whether plain text or binary, will follow this same pattern.
Getting ready
To prepare for this recipe, perform the following steps:
- Create a setup project and call it
FileInstaller
. - Add a text file to the project and name it
Sample.txt
. Although we're adding the file directly to the setup project, in most cases the source files we use will be from other projects or folders. - Update the default directory structure to the following wherein a folder called
My Software
is added to theProgram Files
directory:<Fragment> <Directory Id="TARGETDIR" Name="SourceDir"> <Directory Id="ProgramFilesFolder"> <Directory Id="INSTALLFOLDER" Name="My Software" /> </Directory> </Directory> </Fragment>
How to do it…
Use ComponentGroup
to install a collection of files to a directory as shown in the following steps:
- By default,
Product.wxs
already contains aComponentGroup
that has aDirectory
attribute set toINSTALLFOLDER
. This is exactly the syntax we want and will install any childComponent
elements to theMy Software
folder:<Fragment> <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER"> </ComponentGroup> </Fragment>
- Add a
Component
element to theComponentGroup
with anId
of your choosing and generate a new GUID for theGuid
attribute:<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER"> <Component Id="cmpSampleTXT" Guid="{759CE9A8-F4DF-4DE7-B995-E5F0D926BE43}"> </Component> </ComponentGroup>
- Within that component, add a
File
element that points to ourSample.txt
file:<Component Id="cmpSampleTXT" Guid="{759CE9A8-F4DF-4DE7-B995-E5F0D926BE43}"> <File Source="Sample.txt" /> </Component>
- Although the setup project template already sets it up for you, make sure that the
Id
of theComponentGroup
is referenced by aComponentGroupRef
element inside of aFeature
element:<Feature Id="ProductFeature" Title="The Software" Level="1"> <ComponentGroupRef Id="ProductComponents" /> </Feature>
How it works…
ComponentGroup
is a container for a group of Component
elements. It's really handy when declaring where the components should be installed to since it comes with a Directory
attribute for specifying this. Any child Component
elements will go into that directory on the target computer. It points to the Id
of a Directory
element.
Each component is in turn a container for a single File
element and, through the use of its GUID, allows the file to be tracked from version to version. For example, if we need to patch the file in the future, we'll be able to match it by this identifier. The GUID uniquely identifies it among all other components that have been installed to the end user's system. The ID is used to differentiate the component within the MSI package. You can use any identifier you like, but as a convention, I prefix mine with cmp
.
The File
element points to our source file on disk with its Source
attribute. In this example, we used the relative path Sample.txt
, but we could have used an absolute path or a preprocessor variable. Note that we added the text file directly to our setup project, but in practice the files you reference do not need to be in the project. As long as the path to the file is correct, the WiX
linker will find it.
There's more…
If all the files in the ComponentGroup
can be found in the same directory on your development computer then you can save yourself some typing by setting the ComponentGroup
element's Source
attribute. In the following example, we use the Source
attribute to specify that all child components can be found in the SourceFiles
directory. For this to work, you must switch all File
elements in the group to use the Name
attribute, rather than the Source
attribute, to specify the name of the file. The code is as follows:
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER" Source="..\SourceFiles"> <Component Id="cmpSampleTXT" Guid="{759CE9A8-F4DF-4DE7-B995-E5F0D926BE43}"> <File Name="Sample.txt" /> </Component> </ComponentGroup>