Wix / Heat:访问.wixproj文件中的<projectreference>

时间:2015-11-02 14:06:30

标签: msbuild wix heat wix3.9

我在installer.wixproj中运行一个heat命令作为pre-build事件。 我希望我的dir - 参数(HarvestPath)成为我所包含项目参考的目标目录。

现在我的.wixproj文件里面有

<PropertyGroup>
  <HarvestPath Condition=" '$(HarvestPath)' == '' ">"@(ProjectReference.TargetDir)"</HarvestPath>
  <DefineConstants>HarvestPath=$(HarvestPath)</DefineConstants>
</PropertyGroup>

<ProjectReference Include="..\..\NAME.csproj">
  <Name>NAME</Name>
  <Project>SOME_GUID</Project>
  <Private>True</Private>
  <DoNotHarvest>True</DoNotHarvest>
  <RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
  <RefTargetDir>INSTALLFOLDER</RefTargetDir>
</ProjectReference>

如何访问项目参考的目标目录? "@(ProjectReference)"只为我提供了.csproj文件的完整路径,我无法找到相关文档。

2 个答案:

答案 0 :(得分:2)

好的,所以我找到了一个解决方法,以防有人感兴趣。 我只是使用了<VisualStateGroup>。它不是完全我的目标,但它有效。

答案 1 :(得分:0)

我发现了一种更强大的方法,虽然它有点复杂。我不得不这样做以支持使用更新的构建模板(GitTemplate.12.xaml)在TFS构建服务器上构建,因为:

  • 构建实际上并不写入项目中指定的OutputPath(例如bin \ Release \ AnyCPU),而是写入自己的构建输出文件夹。
  • 构建 写入IntermediateOutputPath(例如obj \ Release \ AnyCPU),但不会复制那些依赖程序,这是heat.exe需要的。

这可以通过查找项目输出的实际位置(_GatheredProjectReferencePaths)来实现,wix2010.targets通过MSBuild task方便地为我们获取。它将相关信息收集到项目集合(COMProjects)中,HeatCOMProjects目标循环遍历。

您需要将“ACME.Core”,“ACME.Data”等替换为您正在加热的代码项目的名称,并确保WiX项目引用它们。您还需要确保HeatFile命令具有正确的参数,尤其是DirectoryRefId,我认为需要指出DLL将在目标系统上安装的位置。

<!-- Find where the .dll and .tlb files of source projects were written to.
     Can't rely on relative paths like "$(ProjectDir)..\..\ACME\ACME.Core\bin\$(ConfigurationName)\AnyCPU\ACME.Core.dll"
     because some build templates don't actually write to OutputPath.  Can't rely on the intermediate output path either
     (obj\...) because Heat needs to be able to find dependencies of any DLLs given. -->
<Target Name="GetCOMProjects" DependsOnTargets="ResolveProjectReferences">
  <ItemGroup>
    <COMProjects Include="%(_GatheredProjectReferencePaths.Name)"
                 Condition="%(_GatheredProjectReferencePaths.Name) == 'ACME.Core' Or
                            %(_GatheredProjectReferencePaths.Name) == 'ACME.Data' ">
      <Name>%(_GatheredProjectReferencePaths.Name)</Name>
      <DLLPath>%(_GatheredProjectReferencePaths.FullPath)</DLLPath>
      <TLBPath>$([System.IO.Path]::GetDirectoryName(%(_GatheredProjectReferencePaths.FullPath)))\%(_GatheredProjectReferencePaths.Filename).tlb</TLBPath>
    </COMProjects>
  </ItemGroup>
</Target>

<!-- Loop through each COMProjects item -->
<Target Name="HeatCOMProjects"
        Inputs="%(COMProjects.DLLPath); %(COMProjects.TLBPath)"
        Outputs="$(ProjectDir)%(COMProjects.Name).REGASM.wxs; $(ProjectDir)%(COMProjects.Name).REGTLB.wxs">
  <HeatFile
    ToolPath="$(WixToolPath)"
    File="%(COMProjects.DLLPath)"
    OutputFile="$(ProjectDir)%(COMProjects.Name).REGASM.wxs"
    GenerateGuidsNow="true"
    NoLogo="true"
    ComponentGroupName="%(COMProjects.Name).REGASM"
    DirectoryRefId="INSTALLDIR"
    SuppressRootDirectory="true"
    PreprocessorVariable="var.%(COMProjects.Name).TargetDir"
  />
  <HeatFile
    ToolPath="$(WixToolPath)"
    File="%(COMProjects.TLBPath)"
    OutputFile="$(ProjectDir)%(COMProjects.Name).REGTLB.wxs"
    GenerateGuidsNow="true"
    NoLogo="true"
    ComponentGroupName="%(COMProjects.Name).REGTLB"
    DirectoryRefId="INSTALLDIR"
    SuppressRootDirectory="true"
    PreprocessorVariable="var.%(COMProjects.Name).TargetDir"
  />
</Target>

<!-- Run Heat after building dependencies, but before building this project. -->
<Target Name="AfterResolveReferences" DependsOnTargets="GetCOMProjects; HeatCOMProjects" />