除了使用构建后步骤或使用复制到输出目录之外,还有其他方法可以在构建过程中复制数百个文件

本文关键字:复制 构建 过程中 方法 其他 百个 文件 输出 | 更新日期: 2023-09-27 18:32:20

我有一个包含数百个资源的 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 的输出目录。
  • 想法 1 仅将 Special'' 输出到 DLL 的输出目录
  • 想法 2 根本没有输出任何内容。

更新 2

@Jimmy的想法几乎完美无缺。 干净的版本不会删除文件。

除了使用构建后步骤或使用复制到输出目录之外,还有其他方法可以在构建过程中复制数百个文件

如果"复制到输出目录"设置有效,您可以将以下内容放入项目文件中:

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

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

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

另一种选择是创建自己的 MSBuild 脚本(演练:从头开始创建 MSBuild 项目文件),这样您就可以使用功能更强大的复制任务。

生成后的命令行脚本换成确保 DLL 项目中表示 EXE 所需资源的所有项都具有CopyToOutputDirectory元数据属性的值PreserveNewest的方法。将以下内容复制到每个 DLL .csproj 文件的末尾,就在 </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他的回答中所述进行项目更改。