📜 ⬆️ ⬇️

Automatically add files to the WiX installer

Good afternoon, colleagues. In my article, I want to highlight the problem that a developer may encounter if he wants to write his installer using WiX technology.
I think that many programmers are faced with the task of writing an installer for their software product. So I suffered the same fate. It was decided to use WiX. It was necessary to make an automatic installer build on the build server. Projects from which the files for installation are taken may vary, and therefore you cannot strictly indicate the list of files to be added to the installer.



The project is written under MS Visual Studio 2010. Those who do not write their project on it, but use it only for writing the installer, this article will also be interesting, since in this case it does not matter under what development environment you work.
With WiX, the bundled utility comes with heat.exe, which serves as a tool for automatically collecting files from folders or projects (there are a few more options available). Console application, with commands which you can find here.
At the initial study of the question, the option of automatically collecting files from the output folders of the projects seemed to be the best and most convenient option. To do this, you just need to add a link to the project, from which you need to pick up the output and make small changes with the project file (an advantage for those developing on VS). But in the process of studying this possibility, it turned out that the heat.exe utility does not collect anything from the output except the * .exe project file and configuration files. The long search for the causes of this problem led to the fact that, as it turned out, such a mistake has already been known since March 2010, but it has not yet been eliminated.
So the most convenient option was dropped, and the task remained the same - files should be added automatically, the process of exploring other solutions began. Looking ahead, I can say that, of course, a solution was found!
The heat.exe utility has the ability to add files not only from projects, as mentioned above, but also the ability to collect them from a folder that you can specify to it. This option I began to explore. It turned out that heat.exe already adds all the files from the folder, and not as from a project, only selective ones. It was already a small victory. But every cloud has a silver lining.
When you run the utility heat.exe, you can specify which types of files to collect from the folder. I was interested in 2 categories - “Binaries” and “Content”. The first category is responsible for the * .dll and * .exe files, and the second is for the configuration files. In practice, it turned out that the utility doesn’t care if I give these parameters or not. She, as if nothing had happened, continued to collect everything that is in the folder. This option could not suit me.
Let's a little distract from the utility itself and talk about what I wanted to get in the end. I need to get a file in which there will be a description of the files in the right format. The file is an xml document that stores the file ID and paths to it. The identifier is a GUID. Do not use an automated tool and hand such a file - not the most pleasant task.
Utility heat.exe just generates such a file. But in my case, any garbage falls into it. However, since this is an xml document, I can apply an XSLT transformation to it. It is enough to remove the description of unnecessary files from the resulting file. And to my delight, heat.exe can accept, as a parameter, such a file.
As a result, I wrote a file with transformations and transferred it to heat.exe. And here I am already the happy owner of the file I need. It remains only to write the correct start line of heat.exe in the Pre-Build Event of the installer project and add the generated file to the project. The fruits of long work were crowned with success and the desired goal was achieved. The installer is built automatically without the intervention of a living organism.
All the same, we are reading this article not for the sake of an author's word, but we want to understand how to turn this entire set of letters into a working project.
')
Let's create a new installer project and name it “AutoAddingFilesInstaller”. Let's add a new file to our project, which we will call “Output”. one.

image
Figure 1 Contents of the project file

In this file we will add the description of groups of files. In my project, I split the files into 2 groups, the same that heat.exe uses:


What will our file look like? Let's look at it.

<? xml version ="1.0" encoding ="UTF-8" ? > < Wix xmlns ="http://schemas.microsoft.com/wix/2006/wi" > < Fragment > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="BinariesDir" ComponentGuidGenerationSeed ="DBA8384E-CE1B-41af-B573-4203FB8A6A3B" > < Directory Id ="Output.Binaries" /> </ Directory > </ DirectoryRef > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="ContentDir" ComponentGuidGenerationSeed ="35A3DCB8-4F85-4e3f-AC83-C51B78C04B94" Name ="NewConfigurationFiles" > < Directory Id ="Output.Content" /> </ Directory > </ DirectoryRef > < ComponentGroup Id ="OutputGroup" > < ComponentGroupRef Id ="Output.Binaries" /> < ComponentGroupRef Id ="Output.Content" /> </ ComponentGroup > </ Fragment > </ Wix > * This source code was highlighted with Source Code Highlighter .
  1. <? xml version ="1.0" encoding ="UTF-8" ? > < Wix xmlns ="http://schemas.microsoft.com/wix/2006/wi" > < Fragment > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="BinariesDir" ComponentGuidGenerationSeed ="DBA8384E-CE1B-41af-B573-4203FB8A6A3B" > < Directory Id ="Output.Binaries" /> </ Directory > </ DirectoryRef > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="ContentDir" ComponentGuidGenerationSeed ="35A3DCB8-4F85-4e3f-AC83-C51B78C04B94" Name ="NewConfigurationFiles" > < Directory Id ="Output.Content" /> </ Directory > </ DirectoryRef > < ComponentGroup Id ="OutputGroup" > < ComponentGroupRef Id ="Output.Binaries" /> < ComponentGroupRef Id ="Output.Content" /> </ ComponentGroup > </ Fragment > </ Wix > * This source code was highlighted with Source Code Highlighter .
  2. <? xml version ="1.0" encoding ="UTF-8" ? > < Wix xmlns ="http://schemas.microsoft.com/wix/2006/wi" > < Fragment > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="BinariesDir" ComponentGuidGenerationSeed ="DBA8384E-CE1B-41af-B573-4203FB8A6A3B" > < Directory Id ="Output.Binaries" /> </ Directory > </ DirectoryRef > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="ContentDir" ComponentGuidGenerationSeed ="35A3DCB8-4F85-4e3f-AC83-C51B78C04B94" Name ="NewConfigurationFiles" > < Directory Id ="Output.Content" /> </ Directory > </ DirectoryRef > < ComponentGroup Id ="OutputGroup" > < ComponentGroupRef Id ="Output.Binaries" /> < ComponentGroupRef Id ="Output.Content" /> </ ComponentGroup > </ Fragment > </ Wix > * This source code was highlighted with Source Code Highlighter .
  3. <? xml version ="1.0" encoding ="UTF-8" ? > < Wix xmlns ="http://schemas.microsoft.com/wix/2006/wi" > < Fragment > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="BinariesDir" ComponentGuidGenerationSeed ="DBA8384E-CE1B-41af-B573-4203FB8A6A3B" > < Directory Id ="Output.Binaries" /> </ Directory > </ DirectoryRef > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="ContentDir" ComponentGuidGenerationSeed ="35A3DCB8-4F85-4e3f-AC83-C51B78C04B94" Name ="NewConfigurationFiles" > < Directory Id ="Output.Content" /> </ Directory > </ DirectoryRef > < ComponentGroup Id ="OutputGroup" > < ComponentGroupRef Id ="Output.Binaries" /> < ComponentGroupRef Id ="Output.Content" /> </ ComponentGroup > </ Fragment > </ Wix > * This source code was highlighted with Source Code Highlighter .
  4. <? xml version ="1.0" encoding ="UTF-8" ? > < Wix xmlns ="http://schemas.microsoft.com/wix/2006/wi" > < Fragment > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="BinariesDir" ComponentGuidGenerationSeed ="DBA8384E-CE1B-41af-B573-4203FB8A6A3B" > < Directory Id ="Output.Binaries" /> </ Directory > </ DirectoryRef > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="ContentDir" ComponentGuidGenerationSeed ="35A3DCB8-4F85-4e3f-AC83-C51B78C04B94" Name ="NewConfigurationFiles" > < Directory Id ="Output.Content" /> </ Directory > </ DirectoryRef > < ComponentGroup Id ="OutputGroup" > < ComponentGroupRef Id ="Output.Binaries" /> < ComponentGroupRef Id ="Output.Content" /> </ ComponentGroup > </ Fragment > </ Wix > * This source code was highlighted with Source Code Highlighter .
  5. <? xml version ="1.0" encoding ="UTF-8" ? > < Wix xmlns ="http://schemas.microsoft.com/wix/2006/wi" > < Fragment > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="BinariesDir" ComponentGuidGenerationSeed ="DBA8384E-CE1B-41af-B573-4203FB8A6A3B" > < Directory Id ="Output.Binaries" /> </ Directory > </ DirectoryRef > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="ContentDir" ComponentGuidGenerationSeed ="35A3DCB8-4F85-4e3f-AC83-C51B78C04B94" Name ="NewConfigurationFiles" > < Directory Id ="Output.Content" /> </ Directory > </ DirectoryRef > < ComponentGroup Id ="OutputGroup" > < ComponentGroupRef Id ="Output.Binaries" /> < ComponentGroupRef Id ="Output.Content" /> </ ComponentGroup > </ Fragment > </ Wix > * This source code was highlighted with Source Code Highlighter .
  6. <? xml version ="1.0" encoding ="UTF-8" ? > < Wix xmlns ="http://schemas.microsoft.com/wix/2006/wi" > < Fragment > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="BinariesDir" ComponentGuidGenerationSeed ="DBA8384E-CE1B-41af-B573-4203FB8A6A3B" > < Directory Id ="Output.Binaries" /> </ Directory > </ DirectoryRef > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="ContentDir" ComponentGuidGenerationSeed ="35A3DCB8-4F85-4e3f-AC83-C51B78C04B94" Name ="NewConfigurationFiles" > < Directory Id ="Output.Content" /> </ Directory > </ DirectoryRef > < ComponentGroup Id ="OutputGroup" > < ComponentGroupRef Id ="Output.Binaries" /> < ComponentGroupRef Id ="Output.Content" /> </ ComponentGroup > </ Fragment > </ Wix > * This source code was highlighted with Source Code Highlighter .
  7. <? xml version ="1.0" encoding ="UTF-8" ? > < Wix xmlns ="http://schemas.microsoft.com/wix/2006/wi" > < Fragment > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="BinariesDir" ComponentGuidGenerationSeed ="DBA8384E-CE1B-41af-B573-4203FB8A6A3B" > < Directory Id ="Output.Binaries" /> </ Directory > </ DirectoryRef > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="ContentDir" ComponentGuidGenerationSeed ="35A3DCB8-4F85-4e3f-AC83-C51B78C04B94" Name ="NewConfigurationFiles" > < Directory Id ="Output.Content" /> </ Directory > </ DirectoryRef > < ComponentGroup Id ="OutputGroup" > < ComponentGroupRef Id ="Output.Binaries" /> < ComponentGroupRef Id ="Output.Content" /> </ ComponentGroup > </ Fragment > </ Wix > * This source code was highlighted with Source Code Highlighter .
  8. <? xml version ="1.0" encoding ="UTF-8" ? > < Wix xmlns ="http://schemas.microsoft.com/wix/2006/wi" > < Fragment > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="BinariesDir" ComponentGuidGenerationSeed ="DBA8384E-CE1B-41af-B573-4203FB8A6A3B" > < Directory Id ="Output.Binaries" /> </ Directory > </ DirectoryRef > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="ContentDir" ComponentGuidGenerationSeed ="35A3DCB8-4F85-4e3f-AC83-C51B78C04B94" Name ="NewConfigurationFiles" > < Directory Id ="Output.Content" /> </ Directory > </ DirectoryRef > < ComponentGroup Id ="OutputGroup" > < ComponentGroupRef Id ="Output.Binaries" /> < ComponentGroupRef Id ="Output.Content" /> </ ComponentGroup > </ Fragment > </ Wix > * This source code was highlighted with Source Code Highlighter .
  9. <? xml version ="1.0" encoding ="UTF-8" ? > < Wix xmlns ="http://schemas.microsoft.com/wix/2006/wi" > < Fragment > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="BinariesDir" ComponentGuidGenerationSeed ="DBA8384E-CE1B-41af-B573-4203FB8A6A3B" > < Directory Id ="Output.Binaries" /> </ Directory > </ DirectoryRef > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="ContentDir" ComponentGuidGenerationSeed ="35A3DCB8-4F85-4e3f-AC83-C51B78C04B94" Name ="NewConfigurationFiles" > < Directory Id ="Output.Content" /> </ Directory > </ DirectoryRef > < ComponentGroup Id ="OutputGroup" > < ComponentGroupRef Id ="Output.Binaries" /> < ComponentGroupRef Id ="Output.Content" /> </ ComponentGroup > </ Fragment > </ Wix > * This source code was highlighted with Source Code Highlighter .
  10. <? xml version ="1.0" encoding ="UTF-8" ? > < Wix xmlns ="http://schemas.microsoft.com/wix/2006/wi" > < Fragment > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="BinariesDir" ComponentGuidGenerationSeed ="DBA8384E-CE1B-41af-B573-4203FB8A6A3B" > < Directory Id ="Output.Binaries" /> </ Directory > </ DirectoryRef > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="ContentDir" ComponentGuidGenerationSeed ="35A3DCB8-4F85-4e3f-AC83-C51B78C04B94" Name ="NewConfigurationFiles" > < Directory Id ="Output.Content" /> </ Directory > </ DirectoryRef > < ComponentGroup Id ="OutputGroup" > < ComponentGroupRef Id ="Output.Binaries" /> < ComponentGroupRef Id ="Output.Content" /> </ ComponentGroup > </ Fragment > </ Wix > * This source code was highlighted with Source Code Highlighter .
  11. <? xml version ="1.0" encoding ="UTF-8" ? > < Wix xmlns ="http://schemas.microsoft.com/wix/2006/wi" > < Fragment > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="BinariesDir" ComponentGuidGenerationSeed ="DBA8384E-CE1B-41af-B573-4203FB8A6A3B" > < Directory Id ="Output.Binaries" /> </ Directory > </ DirectoryRef > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="ContentDir" ComponentGuidGenerationSeed ="35A3DCB8-4F85-4e3f-AC83-C51B78C04B94" Name ="NewConfigurationFiles" > < Directory Id ="Output.Content" /> </ Directory > </ DirectoryRef > < ComponentGroup Id ="OutputGroup" > < ComponentGroupRef Id ="Output.Binaries" /> < ComponentGroupRef Id ="Output.Content" /> </ ComponentGroup > </ Fragment > </ Wix > * This source code was highlighted with Source Code Highlighter .
  12. <? xml version ="1.0" encoding ="UTF-8" ? > < Wix xmlns ="http://schemas.microsoft.com/wix/2006/wi" > < Fragment > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="BinariesDir" ComponentGuidGenerationSeed ="DBA8384E-CE1B-41af-B573-4203FB8A6A3B" > < Directory Id ="Output.Binaries" /> </ Directory > </ DirectoryRef > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="ContentDir" ComponentGuidGenerationSeed ="35A3DCB8-4F85-4e3f-AC83-C51B78C04B94" Name ="NewConfigurationFiles" > < Directory Id ="Output.Content" /> </ Directory > </ DirectoryRef > < ComponentGroup Id ="OutputGroup" > < ComponentGroupRef Id ="Output.Binaries" /> < ComponentGroupRef Id ="Output.Content" /> </ ComponentGroup > </ Fragment > </ Wix > * This source code was highlighted with Source Code Highlighter .
  13. <? xml version ="1.0" encoding ="UTF-8" ? > < Wix xmlns ="http://schemas.microsoft.com/wix/2006/wi" > < Fragment > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="BinariesDir" ComponentGuidGenerationSeed ="DBA8384E-CE1B-41af-B573-4203FB8A6A3B" > < Directory Id ="Output.Binaries" /> </ Directory > </ DirectoryRef > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="ContentDir" ComponentGuidGenerationSeed ="35A3DCB8-4F85-4e3f-AC83-C51B78C04B94" Name ="NewConfigurationFiles" > < Directory Id ="Output.Content" /> </ Directory > </ DirectoryRef > < ComponentGroup Id ="OutputGroup" > < ComponentGroupRef Id ="Output.Binaries" /> < ComponentGroupRef Id ="Output.Content" /> </ ComponentGroup > </ Fragment > </ Wix > * This source code was highlighted with Source Code Highlighter .
  14. <? xml version ="1.0" encoding ="UTF-8" ? > < Wix xmlns ="http://schemas.microsoft.com/wix/2006/wi" > < Fragment > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="BinariesDir" ComponentGuidGenerationSeed ="DBA8384E-CE1B-41af-B573-4203FB8A6A3B" > < Directory Id ="Output.Binaries" /> </ Directory > </ DirectoryRef > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="ContentDir" ComponentGuidGenerationSeed ="35A3DCB8-4F85-4e3f-AC83-C51B78C04B94" Name ="NewConfigurationFiles" > < Directory Id ="Output.Content" /> </ Directory > </ DirectoryRef > < ComponentGroup Id ="OutputGroup" > < ComponentGroupRef Id ="Output.Binaries" /> < ComponentGroupRef Id ="Output.Content" /> </ ComponentGroup > </ Fragment > </ Wix > * This source code was highlighted with Source Code Highlighter .
  15. <? xml version ="1.0" encoding ="UTF-8" ? > < Wix xmlns ="http://schemas.microsoft.com/wix/2006/wi" > < Fragment > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="BinariesDir" ComponentGuidGenerationSeed ="DBA8384E-CE1B-41af-B573-4203FB8A6A3B" > < Directory Id ="Output.Binaries" /> </ Directory > </ DirectoryRef > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="ContentDir" ComponentGuidGenerationSeed ="35A3DCB8-4F85-4e3f-AC83-C51B78C04B94" Name ="NewConfigurationFiles" > < Directory Id ="Output.Content" /> </ Directory > </ DirectoryRef > < ComponentGroup Id ="OutputGroup" > < ComponentGroupRef Id ="Output.Binaries" /> < ComponentGroupRef Id ="Output.Content" /> </ ComponentGroup > </ Fragment > </ Wix > * This source code was highlighted with Source Code Highlighter .
  16. <? xml version ="1.0" encoding ="UTF-8" ? > < Wix xmlns ="http://schemas.microsoft.com/wix/2006/wi" > < Fragment > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="BinariesDir" ComponentGuidGenerationSeed ="DBA8384E-CE1B-41af-B573-4203FB8A6A3B" > < Directory Id ="Output.Binaries" /> </ Directory > </ DirectoryRef > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="ContentDir" ComponentGuidGenerationSeed ="35A3DCB8-4F85-4e3f-AC83-C51B78C04B94" Name ="NewConfigurationFiles" > < Directory Id ="Output.Content" /> </ Directory > </ DirectoryRef > < ComponentGroup Id ="OutputGroup" > < ComponentGroupRef Id ="Output.Binaries" /> < ComponentGroupRef Id ="Output.Content" /> </ ComponentGroup > </ Fragment > </ Wix > * This source code was highlighted with Source Code Highlighter .
  17. <? xml version ="1.0" encoding ="UTF-8" ? > < Wix xmlns ="http://schemas.microsoft.com/wix/2006/wi" > < Fragment > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="BinariesDir" ComponentGuidGenerationSeed ="DBA8384E-CE1B-41af-B573-4203FB8A6A3B" > < Directory Id ="Output.Binaries" /> </ Directory > </ DirectoryRef > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="ContentDir" ComponentGuidGenerationSeed ="35A3DCB8-4F85-4e3f-AC83-C51B78C04B94" Name ="NewConfigurationFiles" > < Directory Id ="Output.Content" /> </ Directory > </ DirectoryRef > < ComponentGroup Id ="OutputGroup" > < ComponentGroupRef Id ="Output.Binaries" /> < ComponentGroupRef Id ="Output.Content" /> </ ComponentGroup > </ Fragment > </ Wix > * This source code was highlighted with Source Code Highlighter .
  18. <? xml version ="1.0" encoding ="UTF-8" ? > < Wix xmlns ="http://schemas.microsoft.com/wix/2006/wi" > < Fragment > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="BinariesDir" ComponentGuidGenerationSeed ="DBA8384E-CE1B-41af-B573-4203FB8A6A3B" > < Directory Id ="Output.Binaries" /> </ Directory > </ DirectoryRef > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="ContentDir" ComponentGuidGenerationSeed ="35A3DCB8-4F85-4e3f-AC83-C51B78C04B94" Name ="NewConfigurationFiles" > < Directory Id ="Output.Content" /> </ Directory > </ DirectoryRef > < ComponentGroup Id ="OutputGroup" > < ComponentGroupRef Id ="Output.Binaries" /> < ComponentGroupRef Id ="Output.Content" /> </ ComponentGroup > </ Fragment > </ Wix > * This source code was highlighted with Source Code Highlighter .
  19. <? xml version ="1.0" encoding ="UTF-8" ? > < Wix xmlns ="http://schemas.microsoft.com/wix/2006/wi" > < Fragment > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="BinariesDir" ComponentGuidGenerationSeed ="DBA8384E-CE1B-41af-B573-4203FB8A6A3B" > < Directory Id ="Output.Binaries" /> </ Directory > </ DirectoryRef > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="ContentDir" ComponentGuidGenerationSeed ="35A3DCB8-4F85-4e3f-AC83-C51B78C04B94" Name ="NewConfigurationFiles" > < Directory Id ="Output.Content" /> </ Directory > </ DirectoryRef > < ComponentGroup Id ="OutputGroup" > < ComponentGroupRef Id ="Output.Binaries" /> < ComponentGroupRef Id ="Output.Content" /> </ ComponentGroup > </ Fragment > </ Wix > * This source code was highlighted with Source Code Highlighter .
<? xml version ="1.0" encoding ="UTF-8" ? > < Wix xmlns ="http://schemas.microsoft.com/wix/2006/wi" > < Fragment > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="BinariesDir" ComponentGuidGenerationSeed ="DBA8384E-CE1B-41af-B573-4203FB8A6A3B" > < Directory Id ="Output.Binaries" /> </ Directory > </ DirectoryRef > < DirectoryRef Id ="INSTALLLOCATION" > < Directory Id ="ContentDir" ComponentGuidGenerationSeed ="35A3DCB8-4F85-4e3f-AC83-C51B78C04B94" Name ="NewConfigurationFiles" > < Directory Id ="Output.Content" /> </ Directory > </ DirectoryRef > < ComponentGroup Id ="OutputGroup" > < ComponentGroupRef Id ="Output.Binaries" /> < ComponentGroupRef Id ="Output.Content" /> </ ComponentGroup > </ Fragment > </ Wix > * This source code was highlighted with Source Code Highlighter .


What is that? I created 2 directories (“BinariesDir”, “ContentDir”), which are located in the folder where the program is installed - “INSTALLLOCATION”. Thus, I created 2 links to which file directories will be added to the project.
Next we need to create a group of components, which will include all the selected file types. Let's call it "OutputGroup". It contains a link to our created directories. Thus, we say that we want to collect information from them.
Now we will create the file “OutputFiles”, in which the list of our files will be stored. This file will automatically fill in the heat.exe utility. For now, we will make this file almost empty. Add there only links to our created folders. This is how it should look like:

  1. <? xml version = "1.0" encoding = "utf-8" ? >
  2. < Wix xmlns = "http://schemas.microsoft.com/wix/2006/wi" >
  3. < Fragragment >
  4. < DirectoryRef Id = "Output.Content" >
  5. </ Directoryref >
  6. < DirectoryRef Id = "Output.Binaries" >
  7. </ Directoryref >
  8. </ Fragment >
  9. < Fragragment >
  10. < ComponentGroup Id = "Output.Content" >
  11. </ ComponentGroup >
  12. < ComponentGroup Id = "Output.Binaries" >
  13. </ ComponentGroup >
  14. </ Fragment >
  15. </ Wix >
* This source code was highlighted with Source Code Highlighter .


Now we need to add the description of our OutputGroup to the Fitch, so that the installer would know to add it to himself. To do this, go to the file "Main" and find in it the tag "Feature". In it, we put a record of our group. As a result, it looks like this:

  1. < Feature Id = "ProductFeature" Title = "AutoAddingFilesInstaller" Level = "1" >
  2. < ComponentGroupRef Id = "OutputGroup" />
  3. < ComponentGroupRef Id = "Product.Generated" />
  4. </ Feature >
* This source code was highlighted with Source Code Highlighter .


Making sure that everything is written correctly (perhaps even copy-paste'no), we try to assemble our project. Everything should go without error.
All the infrastructure we have successfully created. Now let's go directly to the heat.exe utility. Go to the properties of our project and go to the tab «Build Events». On this tab there will be a window “Pre-build Event Command Line”. Since we need to get information about our files before building the project, we will add the utility call to this window.
Let's start forming the call string. First add "% WIX% \ bin \ heat.exe" . Thus, we will have a path to the utility. Now add the “dir” parameter. This will mean that we want to collect information from the folder.
A little formality. Go to the folder of our project and create a new folder “source” there. In it we put the files that we want to process. You can specify a folder in which you will have the output of your project or a folder where the necessary files from several projects will be collected. We will do this now only for the sake of a test, in order to make sure that our project is working. This is how our test folder looks like from the inside. Figure 2.

image
Figure 2 Contents of the folder from which the files will be taken

And so, now our line looks like this: "% WIX% \ bin \ heat.exe" dir $ (ProjectDir) source " . Now add to this line the file into which the information about the files will be generated. We have already created such a file - this is “OutputFiles”.
As a result, we see that our line has acquired the following form: "% WIX% \ bin \ heat.exe" dir "$ (ProjectDir) source" -o "$ (ProjectDir) OutputFiles.wxs" -gg –sfrag

When studying the possibilities of heat.exe, we have already found out that it cannot filter the types of files that are in the folder. But we can use xslt transform. The file “Wix.xslt” was written, which does the conversion of the file generated by heat.exe. This file looks like this:

  1. <? xml version = "1.0" encoding = "utf-8" ? >
  2. < xsl: stylesheet version = "1.0" xmlns: xsl = "http://www.w3.org/1999/XSL/Transform"
  3. xmlns: wix = "http://schemas.microsoft.com/wix/2006/wi"
  4. xmlns = "http://schemas.microsoft.com/wix/2006/wi"
  5. exclude-result-prefixes = "wix"
  6. >
  7. < xsl: output method = "xml" indent = "yes" />
  8. < xsl: template match = "wix: Wix" >
  9. <! - Choose * .config except vshost and App.config ->
  10. < xsl: variable name = "content" select = "wix: Fragment / wix: DirectoryRef / wix: Directory / wix: Component [substring (wix: File / @ Source, string-length (wix: File / @ Source) - 5 ) = 'config' and not (contains (wix: File / @ Source, 'vshost')) and not (substring (wix: File / @ Source, string-length (wix: File / @ Source) - 9) = ' App.config ')] " />
  11. <! - Choose * .exe & * .dll except vshost ->
  12. < xsl: variable name = "binaries" select = "wix: Fragment / wix: DirectoryRef / wix: Directory / wix: Component [substring (wix: File / @ Source, string-length (wix: File / @ Source) - 2 ) = 'dll' or substring (wix: File / @ Source, string-length (wix: File / @ Source) - 2) = 'exe' and not (contains (wix: File / @ Source, 'vshost')) ] " />
  13. < Wix >
  14. < Fragragment >
  15. < DirectoryRef Id = "Output.Content" >
  16. < xsl: apply-templates select = "$ content" />
  17. </ Directoryref >
  18. < DirectoryRef Id = "Output.Binaries" >
  19. < xsl: apply-templates select = "$ binaries" />
  20. </ Directoryref >
  21. </ Fragment >
  22. < Fragragment >
  23. < ComponentGroup Id = "Output.Content" >
  24. < xsl: for-each select = "$ content" >
  25. < ComponentRef Id = "{@ Id}" />
  26. </ xsl: for-each >
  27. </ ComponentGroup >
  28. < ComponentGroup Id = "Output.Binaries" >
  29. < xsl: for-each select = "$ binaries" >
  30. < ComponentRef Id = "{@ Id}" />
  31. </ xsl: for-each >
  32. </ ComponentGroup >
  33. </ Fragment >
  34. </ Wix >
  35. </ xsl: template >
  36. < xsl: template match = "wix: Component" >
  37. < Component Id = "{@ Id}" Guid = "{@ Guid}" >
  38. < File Id = "{wix: File / @ Id}" Source = "{concat ('.. \ .. \ source', substring (wix: File / @ Source, 10))}} /
  39. </ Component >
  40. </ xsl: template >
  41. </ xsl: stylesheet >
* This source code was highlighted with Source Code Highlighter .


This file contains the name of the groups, as well as the path to the “source” folder. If you want to use for your own purposes, then you need to change only these fields.
As a result of all these actions in the window “Pre-build Event Command Line” we should have a record:
"% WIX% \ bin \ heat.exe" dir "$ (ProjectDir) source" -t "$ (ProjectDir) Wix.xslt" -o "$ (ProjectDir) OutputFiles.wxs" -gg –sfrag .

After that, we can build our project and see that the “OutputFiles” file has changed.
Now it looks like this:

  1. <? xml version = "1.0" encoding = "utf-8" ? >
  2. < Wix xmlns = "http://schemas.microsoft.com/wix/2006/wi" >
  3. < Fragragment >
  4. < DirectoryRef Id = "Output.Content" >
  5. < Component Id = "cmpD86120B7C4146F9A886C539A986173D0" Guid = "{1B979A9E-BB11-48FD-B5B6-96FB50A94837}" >
  6. < File Id = "fil1A7C67BC02C177948357049406DE080B" Source = ".. \ .. \ source \ ExampleConfigurationFile.config" />
  7. </ Component >
  8. </ Directoryref >
  9. < DirectoryRef Id = "Output.Binaries" >
  10. < Component Id = "cmp8DD829F42DCE2122C6CC695CE5584A8E" Guid = "{7578DAA3-70C9-4565-A755-91EC145DF679}" >
  11. < File Id = "filE6BF179915D90D217649A4511F1C7745" Source = ".. \ .. \ source \ ExampleDll.dll" />
  12. </ Component >
  13. < Component Id = "cmp6594B36D2CD42159E7EB3F6B4AAE8285" Guid = "{AB0630AA-7EB5-4A8C-8DD3-A4C23742D954}" >
  14. < File Id = "fil008A960D6DBFFE7FBE45D2B2AF6AFA3B" Source = ".. \ .. \ source \ ExampleExe.exe" />
  15. </ Component >
  16. </ Directoryref >
  17. </ Fragment >
  18. < Fragragment >
  19. < ComponentGroup Id = "Output.Content" >
  20. < ComponentRef Id = "cmpD86120B7C4146F9A886C539A986173D0" />
  21. </ ComponentGroup >
  22. < ComponentGroup Id = "Output.Binaries" >
  23. < ComponentRef Id = "cmp8DD829F42DCE2122C6CC695CE5584A8E" />
  24. < ComponentRef Id = "cmp6594B36D2CD42159E7EB3F6B4AAE8285" />
  25. </ ComponentGroup >
  26. </ Fragment >
  27. </ Wix >
* This source code was highlighted with Source Code Highlighter .


If we open the received installation file “AutoAddingFilesInstaller.msi” with the help of Orca, we will see that in the “File” section we have records of our 3 files. 3

image
Figure 3 Installer File Contents

At this point I want to complete my article. I hope that it will be able to help with the development of the installer and make its creation as automated as possible.

Source: https://habr.com/ru/post/122038/


All Articles