【问题标题】:Can I specify the output path for the MSBuild <Content> tag?我可以指定 MSBuild <Content> 标记的输出路径吗?
【发布时间】:2012-04-29 13:38:15
【问题描述】:

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

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

【问题讨论】:

  • 你知道怎么做了吗?
  • 此链接没有显示如何使用 Content 标签指定不同的文件夹,但它看起来像是一种解决方法,可以让你做你想做的事...stackoverflow.com/questions/7643615/…
  • 您能否举例说明您希望将文件复制到哪个文件夹?这是一个特定的内容文件、内容文件的子集还是全部?d 如果将文件复制到另一个文件夹除了而不是 复制到标准位置?

标签: .net visual-studio-2010 msbuild


【解决方案1】:

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

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

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

<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" />

【讨论】:

  • 完美运行,应该是接受的答案恕我直言。谢谢!
  • 是的。这行得通。尤其是在“ClickOnce”世界中!这在您努力消除所有耦合(dll/子项目相互了解)的解决方案中非常有用......但随后必须将其放回 ClickOnce。
  • 曾为 Visual Studio 2019 + Microsoft Visual Studio Installer Project 工作。谢谢。
【解决方案2】:

您可以,但不能使用“内容”。这取决于项目任务,但您可以破解大多数内置任务,不值得麻烦或副作用。

有一个基本的陈旧路径来处理这个问题:) 如果您正在使用 .Net,这也可以避免讨厌的 PostBuild cmd shell 方式,并使用实际的构建过程。

我没有看到任何其他类似的答案,我认为这是 OPs 问题的核心所在。这是核心概念,也是最短路径,除了找到具有“相对于输出路径”路径参数且没有副作用的项目类型。

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>

根本问题是项目项目默认情况下不做任何事情,它们的类型类似于“内容”或“我的目标”。它的那些类型说会发生什么。您可能能够找到包含所需内容的任务、类型或构建脚本,但就构建期间该文件将发生的情况而言,项目组中的项目没有任何内在特征。以上是特制“任务”的力量之间的平衡,但没有任何麻烦。

添加后

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

对项目文件进行一次,然后它将出现在任何文件的 BuildAction 列表中,您可以在其中对任何文件进行设置,而无需手动编辑项目文件。


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" />

【讨论】:

  • 答案没有错,有效。提供的链接显示了使用脚本函数的不同方式,我特别避免了这种方式,例如避免使用 RoboCopy 任务。提供的链接将所有内容投射到一个地方,这是一个文件。他要了一份文件。问题是:项目任务是否可以使用备用输出路径。答案是肯定的和否定的,“内容”不能,但其他任务可以,但这是一种让你可以控制的方法。
  • 我的第一条评论上面有一条评论,显然被删除了;只是说......所以上面的内容似乎不是随机的。这是我正在回复的反对意见,以及为什么编辑部分存在于答案中。现在缺少的评论措辞相当强硬,大意是“投票不赞成,因为这个答案不仅是错误的,而且使事情变得比它需要的简单得多”。
  • 他引用的链接是:stackoverflow.com/questions/7643615/…
【解决方案3】:

此功能未内置到内容项中。但是您可以通过在项目文件中添加目标来实现它。

在你的项目中,你目前有这个:

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

假设您希望将一个特定文件复制到不同的位置,请将其添加到末尾(在结束“项目”标记之前):

<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

【讨论】:

    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-01-11
      • 2014-01-24
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      • 2011-09-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多