12

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>
Dmitrii Lobanov
  • 4,697
  • 1
  • 31
  • 47
alan
  • 6,105
  • 8
  • 36
  • 65
  • Can you post the full wxs file? Probably you did not enter a correct directory for Some.dll... – wimh May 18 '12 at 14:56
  • @Wimmel, I've updated the original post with the complete wxs. Thanks! – alan May 18 '12 at 15:37
  • @Wimmel, keep in mind I stated this same issue is occurring with example projects I downloaded from more than one source. – alan May 18 '12 at 15:54
  • 1
    You refer to `WcfService_Project`, which should be another file as fragments. See for example [here](http://stackoverflow.com/q/6511851/33499). In the linked question is used `Source="PathToFile"`. That `PathToFile` should point to an existing file. – wimh May 18 '12 at 19:42
  • @Wimmel, That's actually a reference to the wxs which results from the harvested heatdirectory. Please see my update above, I've added that wxs for you. Side note: I have also seen that example you provided prior to my posting. Thanks for your help thus far, I really appreciate it. – alan May 18 '12 at 20:28

4 Answers4

14

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>
laishiekai
  • 741
  • 8
  • 24
alan
  • 6,105
  • 8
  • 36
  • 65
  • I'm having the same issue but so far I do not see how this solves the problem. Is DefineConstants supposed to replace the original LinkerBaseInputPaths element? – jpierson Oct 22 '12 at 19:18
  • 1
    @jpierson I've updated the answer, let me know if this doesn't answer your question. – alan Oct 23 '12 at 13:54
  • Ok, Thanks to you I believe I have it all working now. I was missing the attribute PreprocessorVariable="var.BasePath" on your HeatDirectory element because of the formatting. Next I had to replace all of the SourceDir references in my other WIX project files with references to var.BasePath including in my XSLT transform. – jpierson Oct 23 '12 at 16:02
  • I will add that I'm still not sure why SourceDir no longer works in WIX 3.6 when it seemed to work fine following the tutorials in WIX 3.5. – jpierson Oct 23 '12 at 16:03
  • Brilliant thanks Alan! I've put the info on my blog and I'll get the original posts changed soon too. Thanks for the help! – Chris Surfleet Nov 09 '12 at 16:04
2

I was getting similar issue to yours when I moved from setting up a basic website with Wix to one of our production ones.

Assuming you were following example Paul Reynolds' example and this one Paraesthesia's example

If you look in the comments of the following page - http://blogs.planetsoftware.com.au/paul/archive/2011/02/20/creating-a-web-application-installer-with-wix-3.5-and-visual.aspx

The first comment mentions changing the beforebuild methods found in Paraesthesia's example.

        <Target Name="BeforeBuild"> 
    
    <MSBuild Projects="%(ProjectReference.FullPath)" Targets="Package" Properties="Configuration=$(Configuration);Platform=AnyCPU" Condition="'%(ProjectReference.WebProject)'=='True'" /> 
    <PropertyGroup> <DefineConstants Condition="'%(ProjectReference.WebProject)'=='True'"> %(ProjectReference.Name).PackageDir=%(ProjectReference.RootDir)%(ProjectReference.Directory)obj\$(Configuration)\Package\PackageTmp\ </DefineConstants> </PropertyGroup> <HeatDirectory OutputFile="%(ProjectReference.Filename).wxs" Directory="%(ProjectReference.RootDir)%(ProjectReference.Directory)obj\$(Configuration)\Package\PackageTmp\" DirectoryRefId="INSTALLDIR" ComponentGroupName="%(ProjectReference.Filename)_Project" AutogenerateGuids="true" SuppressCom="true" SuppressFragments="true" SuppressRegistry="true" SuppressRootDirectory="true" ToolPath="$(WixToolPath)" Condition="'%(ProjectReference.WebProject)'=='True'" Transforms="%(ProjectReference.Filename).xsl" PreprocessorVariable="var.%(ProjectReference.Name).PackageDir" /> 
</Target>

I had to remove the transform property and change the DirectoryRefId but so far so good.

Hope that helps point you in the right direction.

juanvan
  • 587
  • 6
  • 18
Lareau
  • 1,952
  • 1
  • 25
  • 44
  • thank you for the suggestion. When I get an opportunity I will try this and update the thread. – alan Jun 15 '12 at 21:54
  • Though this was not the solution to my problem, it did however start me in a new direction. Please see the marked answer. – alan Aug 02 '12 at 17:41
0

Update: If you put

<PropertyGroup>
<DefineConstants Condition="'%(ProjectReference.WebProject)'=='True'">
%(ProjectReference.Name).PackageDir=%(ProjectReference.RootDir)
%(ProjectReference.Directory)obj\$(Configuration)\Package\PackageTmp\
</DefineConstants>

and add:

PreprocessorVariable="var.%(ProjectReference.Name).PackageDir"

See the comment towards the bottom. I don't do a transform, so I left that out. to the HeatDirectory it should work with out having to have the proj file at the bottom.

This is probably going to lower my reputation, but what I find interesting is http://www.paraesthesia.com site, is I had working for one project, but when trying another it wasn't working.
After looking at the output it seemed to take the proper project for Heat and Candle, but the Light seemed to take one at random. After comparing the two projects, I noticed the working project had the project to harvest as the last project listed. When I moved the project in the .wixproj file to the last reference, it worked.
I'm using 3.5.2519 at this time. I know it is an old one but we have projects that require the Harvest to True and actually Harvest in Visual Studio.

-1

So your WcfService.wxs includes:

<File Id="fil0118BBA61671E80581CA9C9AA6DD3E8D" KeyPath="yes" Source="SourceDir\Some.dll" />

This refers to SourceDir\Some.dll. This file must exist at the pc where you compile your project. You probably need to change the path.

wimh
  • 14,481
  • 5
  • 42
  • 89
  • From what I understand SourceDir is a keyword for the path at which the source .dll's exist. WcfService.wxs is in fact the product of the harvested heatdirectory (WcfService.wxs is automatically created). The question is how to fix it. I've updated my original post clarify. – alan May 21 '12 at 13:39
  • 1
    @alan if you run heat every time during build, I think you will get problems during updates because a new guid is generated every time. You can add a [parameter -var](http://stackoverflow.com/a/8590298/33499) to heat to specify what to use instead of SourceDir. Or use the [-b option](http://stackoverflow.com/a/6920979/33499) of light to specify where the files are stored. – wimh May 21 '12 at 15:34
  • If I'm building this via Visual Studio 2010 WIX Setup Project where do I put this variable? Do you know of any examples? – alan May 21 '12 at 19:24
  • 1
    @Wimmel you can create a config.wxi file to store your variables then reference that file in your setup project. You can see some examples on using a config file here: http://stackoverflow.com/questions/471424/wix-tricks-and-tips – BryanJ May 23 '12 at 18:37