除了使用后期构建步骤或使用“复制到输出目录”之外,还有另一种方法可以在构建期间复制数百个文件吗?

时间:2016-01-27 18:59:05

标签: c# visual-studio msbuild

我有一个C#DLL项目,其中包含数百个必须复制的资源,以便EXE项目查看它们。这些资源无法嵌入DLL中。

我知道如何创建一个后期构建步骤来复制文件。

MKDIR $(TargetDir)\Special
XCOPY /S /E /Y /C $(ProjectDir)\Special $(TargetDir)\Special

问题是此构建后步骤仅将文件复制到DLL的输出目录。它不会将输出复制到EXE的目录中。我需要EXE的输出目录中的所有这些。此外,解决方案中实际上有两个EXE项目,可能还有更多。

我似乎记得有一种方法可以告诉MSBuild(或Visual Studio)将这些数百个文件复制到引用DLL的最终输出目录中。

还有一个名为“复制到输出目录”的属性似乎有效。麻烦的是,有数百个文件,有几个人正在处理这个问题,如果有人弄乱了一个文件,系统就会崩溃。发现数百个单个文件中的这个小属性以错误的方式翻转将会很麻烦。

更新

我尝试了下面提到的想法,发现了一些事情......

创意1(@GuyVdN)

把它放在项目的某个地方

  <ItemGroup>
    <MySpecialFiles Include="Special\**\*" />
  </ItemGroup>

然后在结束</Project>标记之上:

<Target Name="AfterBuild">
    <MakeDir Directories="$(OutputPath)\Special" Condition="!Exists('$(OutputPath)\Special')" />
    <Copy SourceFiles="@(MySpecialFiles)" DestinationFiles="@(MySpecialFiles->'$(OutputPath)\Special\%(RecursiveDir)%(Filename)%(Extension)')" />
</Target>

创意2(@ user704808)

把它放在项目的某个地方

  <ItemGroup>
    <MySpecialFiles Include="Special\**\*" />
  </ItemGroup>

然后在结束</Project>标记之上:

  <Target Name="SetCopyToOutputDirectoryOnResourceItems" BeforeTargets="Build">
    <ItemGroup>
      <EmbeddedResource>
        <CopyToOutputDirectory>Always</CopyToOutputDirectory>
      </EmbeddedResource>
      <MySpecialFiles Condition="'%(MySpecialFiles.Extension)'=='.py'">
        <CopyToOutputDirectory>Always</CopyToOutputDirectory>
      </MySpecialFiles >
    </ItemGroup>
  </Target>

问题

  • 两者都没有将Special \文件夹复制到EXE的输出目录。
  • Idea 1仅将特殊\输出到DLL的输出目录
  • Idea 2根本没有输出任何内容。 : - (

更新2

@ Jimmy的想法几乎完美无缺。干净的构建没有删除文件。

3 个答案:

答案 0 :(得分:0)

使用每个exe项目的后期构建步骤而不是dll项目可能更容易。这样$(TargetDir)应该是正确的。对于源目录,您可以使用$(SolutionDir)并将资源的文件夹名称附加到其中。

另一种选择是创建自己的MSBuild脚本(Walkthrough: Creating an MSBuild Project File from Scratch),这样就可以使用功能更强大的Copy task

答案 1 :(得分:0)

如果“复制到输出目录”设置有效,您可以将类似的内容放入项目文件中:

<ItemGroup>
  <Content Include="StuffToCopy\**\*">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </Content>
</ItemGroup>

这将获取StuffToCopy下的每个文件(递归)并将其复制到输出目录。我使用这种方法遇到的唯一问题是,有时VS会将ItemGroup扩展到目录下的每个文件,因此请密切关注源代码控制的更改,你应该没问题。

答案 2 :(得分:0)

交换构建后命令行脚本以确保表示EXE所需资源的DLL项目中的所有项目都具有PreserveNewest元数据属性的值CopyToOutputDirectory。将以下内容复制到每个DLL .cs​​proj文件的末尾,就在</Project>之上。调整/添加/删除示例条件和项目类型(EmbeddedResourceSomeOtherItemType)。

<Target Name="SetCopyToOutputDirectoryOnResourceItems" BeforeTargets="Build">
    <ItemGroup>
      <EmbeddedResource>
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      </EmbeddedResource>
      <SomeOtherItemType Condition="'%(SomeOtherItemType.Extension)'=='.someextension'>
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      </SomeOtherItemType>
    </ItemGroup>
</Target>

由于此ItemGroup在Target中并且不添加新项目,因此不会导致Visual Studio更改项目@Jimmy在其答案中描述。