It’s already happened to me several times that I developed a nice tool or program, and later I startet to create a small setup for it. I use Wix 3,5 for this, and create a Setup.wxs where I start to add my files in the right folder. The Setup builds perfectly now.
Later, when I have to do some changes in my code, I have mabe to add new third-party references to one of my projects. They have to be added to the Setup.wxs file too! When this scenario happens serveral times (and it will happen several times! ), the day will come where you will forget your setup. When debugging on your machine, everything will be Ok, but the customer who will install your setup and will immediately see an error like this:
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'file://C:\....\log4net.dll' or one of its dependencies. The system cannot find the file specified
To avoid this, and to avoid the time of bringing the setup to the same level as your projects, you can use the harvesting technique to let the system make your setup code.
The important thing for this is, that you have to keep your output directory as clean as possible! The way I wantet to have my setup is that all the files and subfolders in my “bin\Release” directory will be in the installation directory after installing the setup. This has the advantage that I can see immediately how the setup output will look like.
1) Create a global “bin\Release” directory that is the output for all your projects:
Change the output-directory for all your projects to a global “bin\Release” direcotry. I would suggest to not build .pdb files in Release mode for your assemblies (Set project-settings/Build/Advanced/Debug-Info to None). You can try to run your application now from this folder. If dlls are missing, you will see it quickly.
2) Create a Wix project and create all the directories you want in the setup-file
Create a WixProject with a Setup.wxs file where you define your install-directory as common. It could look like this:
<Directory Id="TARGETDIR" Name="SourceDir"> <Directory Id="ProgramFilesFolder" Name="PFiles"> <Directory Id="coolOrange" Name="coolOrange"> <Directory Id="INSTALLDIR" Name="myApplication"> ...
3) Add the Harvesting to your Wix-project:
This is now very easy. Go to the project-settings of your wix-project to “Build”. Define a preprocessor-variable for the directory you want to harvest (its the global bin\Release directory):
Now unload the Wix-project, and click “Edit …wixproj”. Now go to the end of your file and insert these rows:
<Target Name="BeforeBuild"> <HeatDirectory Directory="..\bin\Release" PreprocessorVariable="var.HarvestPath" OutputFile="HeatGeneratedFileList.wxs" ComponentGroupName="HeatGenerated" AutogenerateGuids="true" DirectoryRefId="INSTALLDIR" ToolPath="$(WixToolPath)" SuppressFragments="true" SuppressRegistry="true" SuppressRootDirectory="true" /> </Target>
This will call the heat.exe for you. Heat will look in your directory and will create a .wxs file with all the files and subfolders in it.
Now reload the wix-project and build it. The build will fail, but heat will be called and will create a file called:
Now include this wix-file into your wix-project and open your Setup.wxs file. Go to the section “feature” and insert the name of the component that you passed to the heat. It should look like this:
<Feature Id="Complete" Level="1"> <ComponentGroupRef Id="HeatGenerated"/> ... </Feature>
Now, because you have added the component to the setup, your build will run and create a nice Setup for your.
Dont care about renaming assemblies, or adding or removing some references in your projects. The setup will take the whole Release directory and harvest it for you. The installation directory will look exactly like your project output folder.
The system will do the work for you now!