Msbuild: How to copy all json file to new folder in Net Core ?

Created on 31 Jul 2018  路  6Comments  路  Source: dotnet/msbuild

Steps to reproduce

On windows I use this command :

<PropertyGroup>
    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
    <PreBuildEvent>IF NOT EXIST "$(TargetDir)DataFiles" MKDIR "$(TargetDir)DataFiles"</PreBuildEvent>
    <PostBuildEvent>FOR /R "$(SolutionDir)\Api.Tests\Scenarios" %25%25f IN (*.json) DO COPY "%25%25f" "$(TargetDir)DataFiles\" /Y</PostBuildEvent>

  </PropertyGroup>

On linux , I have this kind of error

Build FAILED.
[12:44:39][Step 1/1] 
[12:44:39][Step 1/1] /usr/share/dotnet/sdk/2.1.302/Microsoft.Common.CurrentVersion.targets(1331,5): error MSB3073: The command "IF NOT EXIST "DataFiles" MKDIR "DataFiles"" exited with code 127. [/opt/jetbrains/buildAgent/work/4fc9032bf5656724/Api.Tests/Api.Tests/IApi.Tests.csproj]
[12:44:39][Step 1/1]     0 Warning(s)
[12:44:39][Step 1/1]     1 Error(s)

Most helpful comment

Some more options: You could also do

  <ItemGroup>
    <ContentWithTargetPath Include="Scenarios/**/*.json" 
      TargetPath="DataFiles/%(Filename)%(Extension)"
      CopyToOutputDirectory="PreserveNewest" />
  </ItemGroup>

directly in the project file.

Another alternative would be to update the files you already have, presumably None items:

  <ItemGroup>
    <None Update="Scenarios/**/*.json" 
      LinkBase="DataFiles/"
      CopyToOutputDirectory="PreserveNewest" />
  </ItemGroup>

(if the files aren't in your project directory, use Include="../shared/Scenarios/**/*.json" instead)

which however will display the items beneath a DataFiles folder in VS' solution explorer and hide the source folder structure if you are using VS.

All 6 comments

PreBuildEvent and PostBuildEvent are executed using the operating system's shell--cmd.exe on Windows and /bin/sh on macOS and Linux. Since those shells have different syntax, you'll have to do something different to be cross-platform compatible.

Options:

  • Condition the definitions of the scripts based on the current platform (probably something like $(MSBuild::IsOSUnixLike())).
  • Promote the build logic to an MSBuild target that works on all platforms.

I strongly prefer the latter. It'd look something like

<Target Name="CopyScenarios">
  <ItemGroup>
    <Scenarios Include="$(SolutionDir)\Api.Tests\Scenarios\**\*.*" />
  </ItemGroup>

  <Copy SourceFiles="@(Scenarios)"
        DestinationFiles="@(Scenarios->'$(TargetDir)DataFiles\%(RecursiveDir)%(Filename)%(Extension)')"
        SkipUnchangedFiles="true" />
</Target>

it is helped. there are no errors
but Folder still not creates
I have investigated and notice that $(SolutionDir) --> Undefined/Api.Tests/Scenarios/

fixid by replace $(SolutionDir) to $(ProjectDir)

<Target Name="CopyScenarios" AfterTargets="Build">
    <ItemGroup>  
      <Scenarios Include="$(ProjectDir)/Scenarios/**/*.json" />
    </ItemGroup>
    <Copy SourceFiles="@(Scenarios)" DestinationFiles="@(Scenarios->'$(TargetDir)DataFiles/%(Filename)%(Extension)')" SkipUnchangedFiles="false" />
  </Target>

$(SolutionDir) is set only when building _in the context of a solution_, so it's generally set in Visual Studio and for command line builds like msbuild.exe path\to\a.sln but _isn't_ set in command line builds like msbuild.exe path\to\a.csproj.

Sounds like you found a property that works for you, but there are some other options that may help: https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-reserved-and-well-known-properties

Some more options: You could also do

  <ItemGroup>
    <ContentWithTargetPath Include="Scenarios/**/*.json" 
      TargetPath="DataFiles/%(Filename)%(Extension)"
      CopyToOutputDirectory="PreserveNewest" />
  </ItemGroup>

directly in the project file.

Another alternative would be to update the files you already have, presumably None items:

  <ItemGroup>
    <None Update="Scenarios/**/*.json" 
      LinkBase="DataFiles/"
      CopyToOutputDirectory="PreserveNewest" />
  </ItemGroup>

(if the files aren't in your project directory, use Include="../shared/Scenarios/**/*.json" instead)

which however will display the items beneath a DataFiles folder in VS' solution explorer and hide the source folder structure if you are using VS.

@dasMulli Thanks, your approach works moreover it works with publishing
In prev variant, I used two Targets for build and for publishing
Can you give a link for documentation where I can read about keywords like "ContentWithTargetPath" and so one?

Was this page helpful?
0 / 5 - 0 ratings