How to copy downloaded file to publish directory with msbuild? - msbuild

I'd like to download and copy files to the publish directory with MSBuild. I've tried the following which seems pretty obvious:
<Target Name="DownloadContentFiles" BeforeTargets="BeforePublish">
<DownloadFile SourceUrl="$(LatestValidatorUrl)" DestinationFolder="$(MSBuildProjectDirectory)">
<Output TaskParameter="DownloadedFile" ItemName="Content" />
</DownloadFile>
</Target>
<ItemGroup>
<Content Include="org.hl7.fhir.validator.jar" CopyToPublishDirectory="PreserveNewest" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
However CopyToPublishDirectory is running before BeforeTargets="BeforePublish" runs, so it fails to find the file.
I've tried many other variations as well, but nothing is working.
How can I download a file and copy it to the publish directory before the Publish step runs?

Related

ASP.NET Core 6: copy external directory to the publish folder

How to copy the content of external directory to the publish folder when I do dotnet publish ?
I tried the following in the project config, but unfortunately this copies the content of documents-templates directory to the root of the publish directory, but I want the whole folder documents-templates to be copied with its contents.
Is there any way to set the destination folder name too ?
<ItemGroup>
<Content Include="D:\Workspace\OtherProject\documents-templates\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
I have tested in my local, and it works for me.
<ItemGroup>
<Parent Include="C:\Users\Admin\Desktop\Testimages\*.*" />
<EmbeddedResource Include="#(Parent)">
<Link>Resources\%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>

NuGet Package Packing - Is it possible to copy files to a custom directory?

I'm trying to package a few files into a NuGet package, but the issue is that all of the files are sent to the "content" folder within the NuGet package by default when packaged. Normally this is okay, but for the JSON files I have in "ABCJsons" I'd like them to be sent to "content/NewFolderName".
In my example below, the first block is my AbcToolTester, which has all of its project files files being successfully sent to the content directory in the NuGet package. The second block, is where I attempted to copy all the json files with ABCLibrary (ABCLibrary has subfolders where the actual Jsons are located) to the destination folder "ABCJsons". I thought this would do the trick, but unfortunately the ABCJson files just get sent to the content folder along with all the other files.
<ItemGroup>
<Content Include="..\AbcToolTester\bin\Debug\netcoreapp3.1\**" Exclude="..\AbcToolTester\bin\Debug\netcoreapp3.1\*.pdb">
<IncludeInPackage>true</IncludeInPackage>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<ItemGroup>
<Target Name="CopyABCLibrary" AfterTargets="AfterBuild">
<ItemGroup>
<ABCJsonsInclude="..\..\tests\ABCLibrary\**\*.*"/>
</ItemGroup>
<Copy SourceFiles="#(ABCJsons)" DestinationFolder="$(TargetDir)\ABCJsons" SkipUnchangedFiles="true" />
</Target>
It's hard to tell if the NuGet package you are creating is actually dependent on AbcToolTester project because there are easier ways to package that. That's another question though.
For your actual issue, you can simplify the copying process while also telling it where to pack the files. Replace your CopyABCLibrary target with this:
<ItemGroup>
<Content Include="..\..\tests\ABCLibrary\**\*.*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Pack>true</Pack>
<PackagePath>ABCJsons\%(RecursiveDir)</PackagePath>
<!-- This line hides the items from showing in the solution explorer -->
<Visible>false</Visible>
</Content>
</ItemGroup>
This will put all those files into the root of the nuget package into the ABCJsons folder and preserve the directory structure. Change the path accordingly to put it somewhere else.

How to create a custom task with a dependency for incremental build?

I have a build step that parses a csv file and generates numerous .cs files, and I am trying to make a build target that will let me generated them incrementally/only when the source file has changed.
I have created a Target (in TechTreeGenerator.targets):
<Target Name="BuildTechTreeGenerator" BeforeTargets="BeforeBuild" Inputs="#(TechTree)" Outputs="$(ProjectDir)..\Mods\AutoGen\AutoGen.lastbuild">
<TechTreeGenerator SourceCsv="#(TechTree)" OutputFolder="$(ProjectDir)..\Mods\AutoGen" TemplateFolder="$(ProjectDir)..\TechTreeTemplates">
<Output TaskParameter="DestinationFiles" ItemName="CompileFiles"/>
</TechTreeGenerator>
<ItemGroup>
<CompileFiles>
<Link>%(Filename)%(Extension)</Link>
</CompileFiles>
</ItemGroup>
<ItemGroup>
<Compile Include="#(CompileFiles);" />
</ItemGroup>
</Target>
Where TechTreeGenerator is a code Task that runs the tool, and outputs a list of all files that are generated from the csv file (even if they haven't been re-generated). It also always outputs a "AutoGen.lastbuild" file to be compared with the csv file to tell if it needs to be rebuilt.
However, the lastbuild in the Outputs of the Target doesn't seem to have any affect. Deleting it doesn't rebuild the file.
Edit: I forgot to add in .csproj the project I'm referencing it as:
<Import Project="TechTreeGenerator.targets" />
<ItemGroup>
<TechTree Include="..\EcoTechTree.csv" />
</ItemGroup>
Forget about the .lastbuild file. Just put as the input the .csv file. And put as the output an itemgroup the .cs files you generate.
<Target Name="bla" Inputs="#(CSVFilePath)" Outputs="#(YourCSfiles)">

Copy to Publish Directory output of PreBuild Event

Inside my csproj I have a pre-build event where I run the build of Vue js project. It outputs to a "dist" folder, and that is loaded by an cshtml file.
In the csproj file I have a reference to the dist folder and I tell it to copy to publish directory:
<ItemGroup>
<Content Include="dist\**" CopyToPublishDirectory="Always" />
</ItemGroup>
On publish, MsBuild seems to be trying to copy the files in the dist folder that exist before the pre-build event starts. Is there an way to get MsBuild to copy the contents of the folder after the pre-build event?
In order to support all possible publish mechanisms that tooling (VS etc.) supports, I suggest setting it up similar to how the in-box angular template works:
<Target Name="PublishDistFiles" AfterTargets="ComputeFilesToPublish">
<ItemGroup>
<DistFiles Include="dist\**" />
<ResolvedFileToPublish Include="#(DistFiles->'%(FullPath)')" Exclude="#(ResolvedFileToPublish)">
<RelativePath>%(DistFiles.Identity)</RelativePath>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</ResolvedFileToPublish>
</ItemGroup>
</Target>
You can add a step to do it manually using the Copy task
<Target Name="MyCopyStep" AfterTargets="AfterPublish">
<ItemGroup>
<MyDistFiles Include="dist\**" />
</ItemGroup>
<Copy SourceFiles="#(MyDistFiles)" DestinationFiles="#(MyDistFiles->'$(PublishDir)\dist\%(RecursiveDir)%(Filename)%(Extension)')"/>
</Target>

Linked files location on .Net core in Debug vs Publish

I have a shared.{Environment}.json file that is added as linked files in several .Net core 2.1 projects. When project is build or published file gets copied to output directory, in case of release its fine but on debug it doesn't work as when project run it looks up for that file in project directory not in output directory.
Whats the proper way to solve this issue for both debug and publish?
For linked files, it will not exist under the project directory.
For a workaround, you could try to copy the file with task in csproj like below:
<ItemGroup>
<Content Include="..\MVCPro\shared.{Environment}.json">
<Link>shared.{Environment}.json</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Target Name="CopyLinkedContentFiles" BeforeTargets="Build">
<Copy SourceFiles="..\MVCPro\shared.{Environment}.json" DestinationFolder=".\" SkipUnchangedFiles="true" OverwriteReadOnlyFiles="true" />
</Target>