WIX 3.6 Installer - Visual Studio 2010 (HeatDirectory)
Asked Answered
M

4

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>
Mariellemariellen answered 18/5, 2012 at 13:52 Comment(5)
Can you post the full wxs file? Probably you did not enter a correct directory for Some.dll...Locker
@Wimmel, I've updated the original post with the complete wxs. Thanks!Mariellemariellen
@Wimmel, keep in mind I stated this same issue is occurring with example projects I downloaded from more than one source.Mariellemariellen
You refer to WcfService_Project, which should be another file as fragments. See for example here. In the linked question is used Source="PathToFile". That PathToFile should point to an existing file.Locker
@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.Mariellemariellen
M
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>
Mariellemariellen answered 2/8, 2012 at 17:48 Comment(5)
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?Collation
@Collation I've updated the answer, let me know if this doesn't answer your question.Mariellemariellen
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.Collation
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.Collation
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!Lemmy
C
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.

Cf answered 12/6, 2012 at 12:13 Comment(2)
thank you for the suggestion. When I get an opportunity I will try this and update the thread.Mariellemariellen
Though this was not the solution to my problem, it did however start me in a new direction. Please see the marked answer.Mariellemariellen
E
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.

Exercise answered 21/1, 2016 at 17:29 Comment(2)
Not a related answer.Brokerage
WIX is hard to understand I think my answer does answer the question.Exercise
L
-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.

Locker answered 19/5, 2012 at 8:48 Comment(4)
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.Mariellemariellen
@Mariellemariellen 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 to heat to specify what to use instead of SourceDir. Or use the -b option of light to specify where the files are stored.Locker
If I'm building this via Visual Studio 2010 WIX Setup Project where do I put this variable? Do you know of any examples?Mariellemariellen
@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: https://mcmap.net/q/104220/-wix-tricks-and-tipsFonzie

© 2022 - 2024 — McMap. All rights reserved.