我可以指定MSBuild <content>标记的输出路径吗?</content>

时间:2012-04-18 06:55:34

标签: .net visual-studio-2010 msbuild

是否可以为以下文件的输出指定不同的文件夹?

<Content Include="test.stl">
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

4 个答案:

答案 0 :(得分:11)

可以使用Link / None项目上的Content元数据指定其他输出文件夹:

<Content Include="test.stl">
  <Link>some\folder\%(Filename)%(Extension)</Link>
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

在include语句中使用通配符时,这也是保留目录层次结构的方法,即使对于来自项目目录外部的文件也是如此:

<Content Include="..\shared\**\*">
  <Link>some\folder\%(RecursiveDir)%(Filename)%(Extension)</Link>
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

在使用2.0.0+ SDK的基于SDK的项目(ASP.NET Core / .NET Core / .NET Standard项目的默认项目)中,使用LinkBase元数据可以实现相同的目标:

<Content Include="..\shared\**\*" LinkBase="some\folder" CopyToOutputDirectory="PreserveNewest" />

答案 1 :(得分:7)

您可以,但不能使用'内容'。这取决于项目任务,但你可以入侵的大多数内置的任务,都值得麻烦或副作用。

有一个基本的磨损路径来处理这个:)这也避免了令人讨厌的PostBuild cmd shell方式,如果你正在做.Net,并使用实际的构建过程。

我没有看到这样的任何其他答案,使用严格的MSBuild,我认为OP问题的核心是。这是核心概念,也是最短路径,baring查找具有“相对于outputpath”路径参数且没有副作用的项类型。

1)后期处理风格:

<ItemGroup>
  ...
  <MyTargets Include="test.stl"/>
  ...
</ItemGroup>

然后在底部(使用你想要的任何路径):

<PropertyGroup>
  <MyDeployDir>$(SolutionDir)$(Configuration)</MyDeployDir>
  <MyOtherDeployDir>$(SolutionDir)$(Configuration)\Templates</MyDeployDir>
</PropertGroup>

然后你的现有的 MS版本包括(不要添加它,在这里作为标记):

<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />

然后是'构建后':

<Target Name="AfterBuild">
  <Copy SourceFiles="@(MyTargets)" DestinationFolder="$(MyDeployDir)" SkipUnchangedFiles="true" />
  <Copy SourceFiles="@(MyOtherTargets)" DestinationFolder="$(MyOtherDeployDir)" SkipUnchangedFiles="true" />
  <Copy SourceFiles="@(MyTargets2)" DestinationFolder="$(MyDeployDir)\IHeardYourMomLikesGrapeNuts" SkipUnchangedFiles="true" />
</Target>

最基本的问题是项目项目默认情况下不执行任何操作,它们具有“内容”或“MyTarget”类型。它的那些类型会说明会发生什么。您可能能够找到具有所需内容的任务,类型或构建脚本包含,但就构建期间该文件将发生的情况而言,项目组中的项目没有任何内在因素。以上是专门建立的“任务”的力量之间的平衡,但没有遇到任何麻烦。

添加

 <ItemGroup>
    <MyOutFiles Include="xxx.xxx" />

一次到项目文件,它将出现在任何文件的BuildAction列表中,您可以在任何文件上设置,而无需手动编辑proj文件。


2)一步到位

在MSBuild的更高版本中,您可以在'AfterBuild'目标中嵌入'ItemGroup'并执行上述操作或执行其他花哨的操作而不触及文件的其余部分。这允许例如使用简单的Include抓取构建的结果并将其替换到其他位置。这一切都没有做RoboCopy任何事情或诉诸更复杂的构建目标函数处理。

<Target Name="AfterBuild">
  <ItemGroup>
    <MyOutFiles Include="$(OutDir)*.*" />
  </ItemGroup>
  <Copy SourceFiles="@(MyOutFiles)" DestinationFolder="$(SolutionDir)\Application" SkipUnchangedFiles="true" />

编辑(由于投票结果?,自删除以来的海报评论):

为消除歧义可能的方法并重申,此方法不使用MSBuild'函数'或替代任务,如'RoboCopy',而是为了显示更纯粹的MSBuild样式,使用核心功能,就像用于制作项目任务一样'内容'本身。

问题是我可以为以下文件指定'不同的文件夹',我可以为内容标记执行此操作吗?您可以使用MSBuild函数重新路由所有BuildAction,但是我不相信这是个问题。

你可以这样做是上面所示的一步,所以我不认为这更复杂,相信它更容易阅读。下面是简短形式,让他创建自己的BuildAction,无论如何都可以处理。所以不,你不能告诉'内容'为标记为'内容'的特定文件选择另一个文件夹,但你可以做另一个相当容易的构建操作。您还可以将元信息注入StlFiles标记,该标记指示您可以在标记本身上设置它的操作,或者让StlFiles在过程中像事情那样挂钩,但这更复杂。

<StlFiles Include="test.stl" />         
...
<Target Name="AfterBuild">
  <Copy SourceFiles="@(StlFiles)" DestinationFolder="$(SolutionDir)\Release\MyTypes" SkipUnchangedFiles="true" />

答案 2 :(得分:0)

无法另外指定输出文件夹AFAIK,但您可以在构建之前或之后复制文件。

答案 3 :(得分:0)

此功能未内置于“内容”项中。但是你可以通过在项目文件中添加目标来解决这个问题。

在您的项目中,您目前拥有:

<ItemGroup>
  <Content Include="test.stl">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </Content>
</ItemGroup>

假设您希望将一个特定文件复制到其他位置,请将其添加到结尾(在关闭“Project”标记之前):

<Target Name="CopyStl" AfterTargets="AfterBuild">
  <!-- One or the other of these Copy tasks should do what you want --> 
  <Copy Condition="'%(Identity)' == 'test.stl'" SourceFiles="@(Content)" SkipUnchangedFiles="true" DestinationFolder="$(OutputPath)\path\under\outputpath" />
  <Copy Condition="'%(Identity)' == 'test.stl'" SourceFiles="@(Content)" SkipUnchangedFiles="true" DestinationFolder="$(MSBuildProjectDirectory)\..\path\outside\project" />
</Target>

如果您想要添加更多文件以复制到同一文件夹,请尝试以下方法:

<Target Name="CopySomeFiles" AfterTargets="AfterBuild">
  <!-- One or the other of these Copy tasks should do what you want --> 
  <Copy Condition="'%(Identity)' == 'test.stl' AND '%(Identity)' == 'test2.stl'" SourceFiles="@(Content)" SkipUnchangedFiles="true" DestinationFolder="$(OutputPath)\path\under\outputpath" />
  <Copy Condition="'%(Identity)' == 'test.stl' AND '%(Identity)' == 'test2.stl'" SourceFiles="@(Content)" SkipUnchangedFiles="true" DestinationFolder="$(MSBuildProjectDirectory)\..\path\outside\project" />
</Target