How to get the path of the current msbuild file

msbuild

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)'" />

Best Answer

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.

MSBuild v. 4.0 and above

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