I'm working on a WIX 3.6 Installer for a web service. But I've run into an issue when attempting to use a HeatDirectory to harvest all of the necessary output and no matter what I try I get the following error for every harvested file:
The system cannot find the file 'SourceDir\Some.dll...'
The errors occur in WcfService.wxs; the weird part is that WcfService.wxs is automatically created by the heatdirectory section in my project file (below). How can it be blowing up saying it can't find these .dll's if it has to know where they are to create WcfService.wxs in the first place? These errors even occur when I download and build a WIX Example project (as-is) from any one of the tutorials I've read.
The goal: To automate as much of the .dll inclusion as possible (i.e. utilize harvesting to handle dependency projects, etc.)
I'm running Win 7 64bit and the project is .NET 4.
Product.wxs:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="CompleteInstall" Language="1033" Version="1.0.0.0" Manufacturer="Technologies" UpgradeCode="b2ae6aa5-263f-4f9a-a250-8599a7f2cb03">
<Package InstallerVersion="200" Compressed="yes" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFiles64Folder">
<Directory Id="CommonDir1" Name="Common Directory 1">
<Directory Id="CommonDir2" Name="Common Directory 2">
<Directory Id="INSTALLFOLDER" Name="Install Directory"/>
</Directory>
</Directory>
</Directory>
</Directory>
<Feature Id="ProductFeature" Title="CompleteInstall" Level="1">
<ComponentGroupRef Id="WcfService_Project" />
</Feature>
<Property Id="WIXUI_INSTALLDIR">INSTALLFOLDER</Property>
<UIRef Id="WixUI_InstallDir" />
</Product>
</Wix>
Project file:
<Target Name="BeforeBuild">
<MSBuild Projects="%(ProjectReference.FullPath)" Targets="Build" Properties="Configuration=$(Configuration);Platform=x86" Condition="'%(ProjectReference.ContentProject)'=='True'" />
<PropertyGroup>
<LinkerBaseInputPaths>%(ProjectReference.RootDir)%(ProjectReference.Directory)bin\$(Platform)\$(Configuration)\</LinkerBaseInputPaths>
</PropertyGroup>
<HeatDirectory OutputFile="%(ProjectReference.Filename)-temp.xml"
Directory="%(ProjectReference.RootDir)%(ProjectReference.Directory)bin\$(Platform)\$(Configuration)\"
DirectoryRefId="INSTALLFOLDER"
ComponentGroupName="%(ProjectReference.Filename)_Project"
SuppressCom="true"
SuppressFragments="true"
SuppressRegistry="true"
SuppressRootDirectory="true"
AutoGenerateGuids="false"
GenerateGuidsNow="true"
ToolPath="$(WixToolPath)"
Condition="'%(ProjectReference.ContentProject)'=='True'" />
<XslTransformation XmlInputPaths="%(ProjectReference.Filename)-temp.xml"
XslInputPath="XslTransform.xslt"
OutputPaths="%(ProjectReference.Filename).wxs"
Condition="'%(ProjectReference.ContentProject)'=='True'" />
</Target>
WcfService.wxs:
<?xml version="1.0" encoding="utf-8"?><Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<DirectoryRef Id="INSTALLFOLDER">
<Component Id="cmpE6EBA3D8D6D4DB0C93E73200C78DCC51" Guid="{C88B5CF9-8807-45DF-AA6F-732437B74BB6}">
<File Id="fil0118BBA61671E80581CA9C9AA6DD3E8D" KeyPath="yes" Source="SourceDir\Some.dll" />
</Component>
</DirectoryRef>
</Fragment>
<Fragment>
<ComponentGroup Id="WcfService_Project">
<ComponentRef Id="cmpE6EBA3D8D6D4DB0C93E73200C78DCC51" />
</ComponentGroup>
</Fragment>
</Wix>
The problem was the absence of the HeatDirectory PreprocessorVariable property. I fixed the issue with the following additions to my wixproj file:
<PropertyGroup>
<DefineConstants>BasePath=%(ProjectReference.RootDir)%(ProjectReference.Directory);</DefineConstants>
</PropertyGroup>
<HeatDirectory OutputFile="%(ProjectReference.Filename).wxs"
DirectoryRefId="INSTALLFOLDER"
Directory="%(ProjectReference.RootDir)%(ProjectReference.Directory)"
ComponentGroupName="%(ProjectReference.Filename)_Project"
SuppressCom="true"
SuppressFragments="true"
SuppressRegistry="true"
SuppressRootDirectory="true"
AutoGenerateGuids="false"
GenerateGuidsNow="true"
ToolPath="$(WixToolPath)"
Condition="'%(ProjectReference.ContentProject)'=='True'"
PreprocessorVariable="var.BasePath"/>
As you can see, I needed to first define a constant variable for local use. I set the variable equal to the root path of my WCF project. Secondly I used that variable as my PreprocessorVariable. Finally I'm able to dynamically/recursively harvest the files generated from MsBuild. Next step: exclude the unnecessary files. I will refer to this link.
See below my complete wixproj:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>3.5</ProductVersion>
<ProjectGuid>{4005592f-cc0e-41a3-8e64-33b2824e7fd9}</ProjectGuid>
<SchemaVersion>2.0</SchemaVersion>
<OutputName>MyWCF.WCF.Webservice</OutputName>
<OutputType>Package</OutputType>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="MyWCF.WcfService.wxs" />
<Compile Include="IISConfig.wxs" />
<Compile Include="InstallUi.wxs" />
<Compile Include="Product.wxs" />
<Compile Include="UIDialogs.wxs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MyWCF.WcfService\MyWCF.WcfService.csproj">
<Name>MyWCF.WcfService</Name>
<Project>{8e528b38-2826-4793-a66d-f6ff181e1139}</Project>
<Private>True</Private>
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
<ContentProject>True</ContentProject>
<DoNotHarvest>True</DoNotHarvest>
<PackageThisProject>True</PackageThisProject>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<WixExtension Include="WixIIsExtension">
<HintPath>$(WixExtDir)\WixIIsExtension.dll</HintPath>
<Name>WixIIsExtension</Name>
</WixExtension>
<WixExtension Include="WixUtilExtension">
<HintPath>$(WixExtDir)\WixUtilExtension.dll</HintPath>
<Name>WixUtilExtension</Name>
</WixExtension>
<WixExtension Include="WixUIExtension">
<HintPath>$(WixExtDir)\WixUIExtension.dll</HintPath>
<Name>WixUIExtension</Name>
</WixExtension>
<WixExtension Include="WixNetFxExtension">
<HintPath>$(WixExtDir)\WixNetFxExtension.dll</HintPath>
<Name>WixNetFxExtension</Name>
</WixExtension>
</ItemGroup>
<ItemGroup>
<Content Include="ConfigurationInitialize.wxi" />
</ItemGroup>
<Import Project="$(WixTargetsPath)" />
<PropertyGroup>
<PreBuildEvent />
</PropertyGroup>
<Target Name="BeforeBuild">
<MSBuild Projects="%(ProjectReference.FullPath)" Targets="Package" Properties="Configuration=$(Configuration);Platform=$(Platform)" Condition="'%(ProjectReference.PackageThisProject)'=='True'" />
<PropertyGroup>
<DefineConstants>BasePath=%(ProjectReference.RootDir)%(ProjectReference.Directory)obj\$(Platform)\$(Configuration)\Package\PackageTmp\</DefineConstants>
</PropertyGroup>
<HeatDirectory OutputFile="%(ProjectReference.Filename).wxs"
Directory="%(ProjectReference.RootDir)%(ProjectReference.Directory)obj\$(Platform)\$(Configuration)\Package\PackageTmp"
DirectoryRefId="INSTALLFOLDER"
ComponentGroupName="%(ProjectReference.Filename)_Project"
SuppressCom="true"
SuppressFragments="true"
SuppressRegistry="true"
SuppressRootDirectory="true"
AutoGenerateGuids="false"
GenerateGuidsNow="true"
ToolPath="$(WixToolPath)" Condition="'%(ProjectReference.PackageThisProject)'=='True'"
PreprocessorVariable="var.BasePath" />
</Target>
</Project>