如何通过Directory.Build.props将多项目文件复制到输出目录?
问题
我有一个包含多个类库项目和一个控制台项目的.NET解决方案,每个类库的.csproj文件旁都有一个存放文件的Inputs目录。原本在每个类库项目中通过以下配置实现将文件复制到控制台项目输出目录,运行正常:
<ItemGroup> <None Update="Inputs\*"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> </ItemGroup>
现在尝试将该功能提取到Directory.Build.props中,配置如下:
<ItemGroup Condition="$(MSBuildProjectName.StartsWith('AoC')) AND !$(MSBuildProjectName.EndsWith('Test'))" > <None Update="$(MSBuildProjectDirectory)\Inputs\*"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> </ItemGroup>
但最终没有任何文件被复制到输出目录(类库和控制台项目的输出目录都没有),还出现以下现象:
- 若
bin\Debug\net8.0目录下有原配置生成的Inputs目录及文件,仅保留Directory.Build.props中的通用配置时,这些文件会被删除; - 其他文件未被修改(即未被删除);
- 若不存在
Inputs目录,该目录也不会被创建。
另外在Directory.Build.props中添加了如下目标,能够正确输出包含Input文件夹的项目路径:
<Target Name="PrintDirs" BeforeTargets="Build" Condition="$(MSBuildProjectName.StartsWith('AoC')) AND !$(MSBuildProjectName.EndsWith('Test'))"> <Message Importance="High" Text="||---> $(MSBuildProjectDirectory)" /> </Target>
执行dotnet build后的输出如下:
<..>\AoCMultiYear> dotnet build Versión de MSBuild 17.8.3+195e7f5a3 para .NET Determinando los proyectos que se van a restaurar... Todos los proyectos están actualizados para la restauración. Common -> <..>\AoCMultiYear\src\Common\bin\Debug\net8.0\Common.dll AoC2020 -> <..>\AoCMultiYear\src\AoC2020\bin\Debug\net8.0\AoC2020.dll AoC2021 -> <..>\AoCMultiYear\src\AoC2021\bin\Debug\net8.0\AoC2021.dll ||---> <..>\AoCMultiYear\src\AoC2020 ||---> <..>\AoCMultiYear\src\AoC2021 AoC2020.Test -> <..>\AoCMultiYear\tests\AoC2020.Test\bin\Debug\net8.0\AoC2020.Test.dll AoC2022 -> <..>\AoCMultiYear\src\AoC2022\bin\Debug\net8.0\AoC2022.dll ||---> <..>\AoCMultiYear\src\AoC2022 Runner -> <..>\AoCMultiYear\src\Runner\bin\Debug\net8.0\Runner.dll
请问我在MSBuild配置中遗漏了什么?
解决方案
问题核心在于路径格式错误和Update属性的使用逻辑:
Update属性的路径要求<None Update="..." />中的路径必须是相对于项目文件(.csproj)的相对路径,你使用了绝对路径$(MSBuildProjectDirectory)\Inputs\*,导致MSBuild无法匹配到项目中的实际文件项,配置完全失效。原有文件被删除的原因
虽然路径不匹配,MSBuild仍会处理这个无效的Update操作,间接标记原本存在的Inputs相关文件不再需要复制到输出目录,因此会清理掉之前生成的文件。正确的配置写法
将Directory.Build.props中的ItemGroup改为相对路径,保留条件判断即可:<ItemGroup Condition="$(MSBuildProjectName.StartsWith('AoC')) AND !$(MSBuildProjectName.EndsWith('Test'))"> <None Update="Inputs\*"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> <!-- 可选:若需要确保空的Inputs目录也被创建,添加以下配置 --> <None Update="Inputs\"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> </ItemGroup>额外说明
- 类库的
Inputs文件要复制到控制台项目输出目录,需确保控制台项目引用了对应类库,类库文件设置CopyToOutputDirectory后,会自动被依赖项目复制(MSBuild默认行为)。 - 空目录默认不会被复制,若需要创建空的
Inputs目录,必须单独添加对Inputs\目录的Update配置。
- 类库的
内容的提问来源于stack exchange,提问作者eduherminio
相关产品推荐
相关产品推荐

