What is the value of MSBuildThisFileDirectory? - visual-studio

If I have a project structure like this:
\MySolution
\MyProject
ReadMe.md
\build
MyProject.targets
What would the value of $(MSBuildThisFileDirectory) be when used in the MyProject.targets file?
Assuming my solution folder is in the root of C: drive, would it be?..
c:\MySolution\MyProject\build\
In the MyProject.targets file, how would I reference the ReadMe.md file using the $(MSBuildThisFileDirectory)?
Additional information:
MyProject.targets looks like:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)\xxx\ReadMe.md">
<Link>FrameworkTests.feature</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CustomToolNamespace></CustomToolNamespace>
</None>
</ItemGroup>
</Project>

What is the value of MSBuildThisFileDirectory?
It depends on your MyProject.targets. According to the literal meaning of this variable, you could to know ThisFileDirectory means "This File Directory".
Since you have use this argument in the file MyProject.targets, the path should be related to the location of the "this file" MyProject.targets. So the value of this argument should be the directory of this file MyProject.targets.
After install the nuget, the file MyProject.targets should be added to the path:
c:\MySolution\packages\MyProject.1.0.0<YouPackagefolder>\build
You can use a target to output that value in your project file, to accomplish this, unload your project. Then at the very end of the project, just before the end-tag </project>, place below scripts:
<Target Name="TestValue" AfterTargets="build">
<Message Text="#(none)">
</Message>
</Target>

Related

msbuild task that works from publish profile to remove specific file

Have 3 json files in my project. For a specific publish profile, using a FileSystem publish and I'm trying to find a way to have a specific file NOT be published to the target folder. This is for a .net core console app.
This is my publish profile, but the file Im trying to restrict from being published is still published to the target folder.
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PublishProtocol>FileSystem</PublishProtocol>
<Configuration>Debug</Configuration>
<Platform>Any CPU</Platform>
<TargetFramework>netcoreapp3.0</TargetFramework>
<PublishDir>D:\projects\test_publish</PublishDir>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<SelfContained>false</SelfContained>
<DeleteExistingFiles>false</DeleteExistingFiles>
<ExcludeFilesFromDeployment>appsettings.Test.json</ExcludeFilesFromDeployment>
</PropertyGroup>
</Project>
Note: project file includes these files so they will be in the build output. Might this prevent the appsettings.Test.json from being deleted and hence still get copied over to the publish dir?
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="appsettings.Local.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="appsettings.Test.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
The work-around solution I have come up with is similar to another project I have. It involves taping into the build system and add some extra bits into the csproj file.
So the csproj file would now look like this. It eliminates the file you dont need, and you only need to add a corresponding build config entry and this uses the VS build system to determine which of these json file(s) get output.
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="appsettings.Local.json" Condition=" '$(Configuration)' == 'Debug' " >
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="appsettings.Test.json" Condition=" '$(Configuration)' == 'Test' " >
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
This is my publish profile, but the file Im trying to restrict from
being published is still published to the target folder.
I test it in my local machine and reproduce same issue. Also I find if I use this element in web application like asp.net, it always works. So I assume this element is not supported for publishing .net core console application.
What role does that file play in your project?
1.If your application don't need it in build output directory and publish directory, you can set the Copy to Output Directory to Do not copy.
And then clean your publish folder and publish again to check if it helps.
2.And if you have specific reason that you need the file in build, but need to exclude it from publish folder, trying adding this script into your xx.csproj(Delete Task):
<Target Name="CustomTarget" AfterTargets="_PublishNoBuildAlternative">
<Delete Files="$(PublishDir)\appsettings.Test.json"/>
<!--<Delete Files="$(PublishDir)\appsettings.xxx.json"/>-->
</Target>
You can add MSbuild Conditions like Condition="$(Configuration)=='xxx'" to the targets to make it more flexible.

Adding umbraco folders to build with MsBuild

If I use msbuild to build my project, all the folders not included in my solution are not deployed. Is there a way of deploying the umbraco and umbraco_client folders using msbuild?
I have tried using Targets like:
https://gist.github.com/aaronpowell/6695293
How can we include the files created by ajaxmin in the msdeploy package created by MSBuild
https://blog.samstephens.co.nz/2010/10/18/msbuild-including-extra-files-multiple-builds/
But hey are not being copied to the output folder. Am I missing anything?
You can use a msbuild target(run after the build ends) in which it calls the msbuild copy task to copy necessary files or folders to output folder. Use AfterTargets="build" to let the target run after the build.
A target script which works in my machine looks like this:
<Target Name="Copyumbraco" AfterTargets="build">
<ItemGroup>
<UmbracoFiles Include="$(ProjectDir)**\umbraco\**\*" />
<Umbraco_ClientFiles Include="$(ProjectDir)**\umbraco_client\**\*" />
</ItemGroup>
<Copy SourceFiles="#(UmbracoFiles)" DestinationFolder="$(OutputPath)\%(RecursiveDir)"/>
<Copy SourceFiles="#(Umbraco_ClientFiles)" DestinationFolder="$(OutputPath)\%(RecursiveDir)"/>
</Target>
Using $(ProjectDir) property to define the path, so Msbuild can find those two folders if they are in project folder as you mentioned in comment.
The \%(RecursiveDir) set the msbuild copy task to copy the files to destination path with original folder structure. If what you want to just copy all files to Output folder, you don't need to set it, then the script should be:
<Target Name="Copyumbraco" AfterTargets="build">
<ItemGroup>
<UmbracoFiles Include="$(ProjectDir)**\umbraco\**\*" />
<Umbraco_ClientFiles Include="$(ProjectDir)**\umbraco_client\**\*" />
</ItemGroup>
<Copy SourceFiles="#(UmbracoFiles)" DestinationFolder="$(OutputPath)"/>
<Copy SourceFiles="#(Umbraco_ClientFiles)" DestinationFolder="$(OutputPath)"/>
</Target>
Add the target script into the your project's project file(xx.csproj), make sure you place the script in the format below, then it can work when you use msbuild to build the project.
<Project Sdk="Microsoft.NET.Sdk.Web">
...
<Target Name="Copyumbraco" AfterTargets="build">
...
</Target>
</Project>
In addition:
For normal projects like console app, class library, the $(OutputPath) represents the output path. But for web site project, we can use $(WebProjectOutputDir) , hint from Mario!

Can I add a common reference path in an MSBuild target/project file?

I'm trying to write a custom project (targets?) file that is to be included in several projects.
For example, inside all of my .csproj and .vbproj files I have:
<Import Project="..\MyCustomTargets\custom.targets"/>
Inside that file I have a custom target (AfterBuild) which copies the compiled files to another location.
However, I'd like to add a reference path that each project can look to when trying to resolve references. Is this possible?
For example, I'd like to add something like this to my .targets file:
<AdditionalReferencePath>C:\LookHereForReferences</AdditionalReferencePath>
I've found a few links that describe a little about how to do this but I can't get it working.
I'd like to add a reference path that each project can look to when trying to resolve references. Is this possible?
You can set a Property Group in your .targets file:
<PropertyGroup>
<AdditionalReferencePath>C:\LookHereForReferences</AdditionalReferencePath>
</PropertyGroup>
After import this targets file in to the project file, you can look it by $(AdditionalReferencePath) when trying to resolve references:
<Import Project="Common.targets" />
<Target Name="Test" AfterTargets="Build">
<Message Text="$(AdditionalReferencePath)"></Message>
</Target>

Msbuild task to find specific filetype

How can we find a specific file type under a path? I have checked MSBuild Task Reference but couldn't figure out.
Looking for something as:
<FindUnderPath Path="$(OutDir)" Files="*.txt">
<Output TaskParameter="InPath" ItemName="AllTxtFiles"/>
</FindUnderPath>
But it fails sayings "MSB3541: Files has invalid value "*.txt""
P.S. I am a rookie at msbuild tasks!
If you just need list of all txt files in certain folder you can get it as simple as
<ItemGroup>
<AllTxtFiles Include="$(PathToFolder)\**\*.txt" />
</ItemGroup>
Double stars (**) means that folder should be searched recursively for file pattern
You could use an ItemGroup to specify such files and reference the ItemGroup in the Files parameter. Something like:
<ItemGroup>
<MyFiles Include="*.txt" />
</ItemGroup>
<FindUnderPath Path="$(OutDir)" Files="#(MyFiles)">
<Output TaskParameter="InPath" ItemName="AllTxtFiles" />
</FindUnderPath>
Source: http://msdn.microsoft.com/en-us/library/vstudio/ms164293(v=vs.120).aspx

msbuild include / copy from subdirectory to root directory - possible?

Can I include a file from a subdirectory, but have it placed in the root directory of the bulid instead of its original sub directory?
Example: We have multiple robots.txt files for different release configurations. The files are in the solution as \IncludeTest\Development\robots.txt and \IncludeTest\Production\robots.txt
I can dynamically grab them appropriately using something like:
<ItemGroup Condition=" '$(Configuration)' == 'Development' ">
<Content Include="IncludeTest\Development\robots.txt">
<SubType>Designer</SubType>
</Content>
</ItemGroup>
but when I do that, I maintain the \IncludeTest\Development\ (or \IncludeTest\Production) directory. Any way to just include it in the root directory, where robots.txt is supposed to be?
The above still did not work for me entirely, but I was able to find a work around based on how you set up the itemgroup:
Including the file in the solution as a link puts it in the root directory. And with your $(Configuration) hint, I was able to do this, and just include it dynamically as a link, rather than copy it over to the root.
<Content Include="..\Robots_Source\$(Configuration)\robots.txt">
<Link>robots.txt</Link>
</Content>
Not sure I got your question right, let me know whether this work as you expected:
<ItemGroup>
<Content Include = "IncludeTest\$(Configuration)\robots.txt">
<SubType>Designer</SubType>
</Content>
</ItemGroup>
Copy to root:
<Copy SourceFiles="#(Content)"
DestinationFiles="#(Content ->'..\%(RecursiveDir)%(Filename)%(Extension)')" />
EDIT: It could be problem when files are in nested directories, so try out:
<Copy SourceFiles="#(Content)"
DestinationFiles="#(Content ->'$(MSBuildProjectDirectory)..\%(RecursiveDir)%(Filename)%(Extension)')" />

Resources