I'm writing an msbuild .targets file, and in it I want to use the zip task to zip up some files that I know the locations of relative to the .targets file.
This works ok when I execute the .target file directly. But, when I include the .targets file in an .proj file that's in another directory, the relative paths are resolved relative to the .proj file and not to the .targets file.
Is there a way I can specify relative paths that are relative to the file I've written them in?
I've seen this related question:
How to give relative path in msbuild file?
A workaround I've thought of is to do the following. I haven't tried it yet. Will it work, is there a better way?
my.proj
<Import Project="..\Somewhere\my.targets"/> <PropertyGroup> <MyTargetsYouAreHere>$(MSBuildProjectDirectory)\..\Somewhere</MyTargetsYouAreHere> </PropertyGroup>
my.targets
<Message Text="my.targets is here '$(MyTargetsYouAreHere)'" />
For example, the path to MSBuild.exe installed with Visual Studio 2019 Community is C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe You can also use the following PowerShell module to locate MSBuild: vssetup. powershell.
For example, bin\Debug. Specifies the path to the output directory, relative to the project directory, for example, bin\Debug.
The Microsoft Build Engine or more known as MSBuild, is a platform for building applications. Chances are that if you have ever used Visual Studio or compiled a . NET based project, you have used it knowingly or un-knowingly. Visual Studio uses MSBuild, but it doesn't depend on Visual Studio.
In the . NET Framework 3.5 and earlier, the default value of MSBuildExtensionsPath points to the path of the MSBuild subfolder under the \Program Files\ or \Program Files (x86) folder, depending on the bitness of the current process.
The way MSBuild works when processing files is to read all files and create one in memory representation of all those files. This all happens before any target is executed. Because of this when a target is executing it has no concept of what file it was contained in. Basically you will not be able to use relative paths inside of .targets files. The way to deal with this situation is to ensure that your outlying .proj files (or whatever extension you use) to declare a known property which your .targets file uses to resolve the full path to the shared files.
For instance
Sample.targets
<Project ...> <Target Name="ExecTool"> <Exec Command="$(YourToolPath)tool.exe" /> </Target> </Project>
Build.proj
<Project ...> <PropertyGroup> <YourToolPath>$(MSBuildProjectDirectory)\..\</YourToolPath> </PropertyGroup> <Import Project="..\..\..\Sample.targets"/> </Project>
In a related note, I discussed validating such "shared" properties on my blog a while back at Elements of Reusable MSBuild Scripts: Validation.
If you are using MSBuild 4.0 (or above), i.e. Visual Studio 2010/.NET 4.0, (which can target .NET 2.0/3.0/3.5) as well. Then you now have these properties which can be used for this specific purpose:
MSBuildThisFile
MSBuildThisFileDirectory
MSBuildThisFileDirectoryNoRoot
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With