72

In my MSBuild script I need to pass the full directory as a parameter. How can I get it?

Example: I am running the script from C:\dev, and I want a relative path, temp, so I am after C:\dev\temp.

Note: I don't know from which folder the script will be run.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Grzenio
  • 35,875
  • 47
  • 158
  • 240
  • Will your temp folder always be a sub folder of the location from which this script is to be run? – brunch Jan 21 '10 at 17:21

3 Answers3

108

Igor is pretty close. MSBuildProjectDirectory is the property that will give you the full path to the project file which was invoked on the command line. So if you have the following scripts:

  • C:\temp\MyProj.proj
  • C:\shared\shared.targets

And MyProj.proj imports shared.targets and this is the one passed to msbuild.exe then the value for MSBuildProjectDirectory will always be C:\temp even if you are referencing that inside of shared.targets. If your shared.targets requires path knowledge then those should be declared in known properties. For example C# project files define the value for OutputPath and the shared file Microsoft.Common.targets uses that property.

Edit: MSBuild 4

If you are using MSBuild 4, you can also use these properties for this type of value.

  • MSBuildThisFile
  • MSBuildThisFileDirectory
  • MSBuildThisFileDirectoryNoRoot
  • MSBuildThisFileExtension
  • MSBuildThisFileFullPath
  • MSBuildThisFileName

See http://sedodream.com/2010/03/11/MSBuild40ReservedProperties.aspx.

Josiah Nunemaker
  • 781
  • 10
  • 20
Sayed Ibrahim Hashimi
  • 43,864
  • 17
  • 144
  • 178
  • 4
    +1 note that those new MSBuild 4 reserved properties are not listed in the list of macros in Visual Studio 2010 edit dialog even though they are supported – Amro Jun 19 '13 at 19:51
59

Here are three targets that are helpful.

WhereAmI is the one I use when trying to figure out my current directory of course.

The others are informative as well (some are beyond the scope of the question).

<Target Name="WhereAmI">
    <Message Text=" Here I Am  " />
    <Exec Command="dir ." />
    <Message Text=" " />
</Target>



<Target Name="ShowReservedProperties" AfterTargets="BeforeBuild">
    <Message Text=" MSBuildProjectDirectory  = $(MSBuildProjectDirectory)" Importance="high" />
    <Message Text=" MSBuildProjectFile  = $(MSBuildProjectFile)" Importance="high" />
    <Message Text=" MSBuildProjectExtension  = $(MSBuildProjectExtension)" Importance="high" />
    <Message Text=" MSBuildProjectFullPath  = $(MSBuildProjectFullPath)" Importance="high" />
    <Message Text=" MSBuildProjectName  = $(MSBuildProjectName)" Importance="high" />
    <Message Text=" MSBuildBinPath  = $(MSBuildBinPath)" Importance="high" />
    <Message Text=" MSBuildProjectDefaultTargets  = $(MSBuildProjectDefaultTargets)" Importance="high" />
    <Message Text=" MSBuildExtensionsPath  = $(MSBuildExtensionsPath)" Importance="high" />
    <Message Text=" MSBuildStartupDirectory  = $(MSBuildStartupDirectory)" Importance="high"/>
</Target>


  <Target Name="ShowOtherProperties">
    <Message Text="  " />
    <Message Text="  " />
    <Message Text=" Environment (SET) Variables*       " />
    <Message Text=" ---------------------------        " />
    <Message Text=" COMPUTERNAME = *$(COMPUTERNAME)*   " />
    <Message Text=" USERDNSDOMAIN = *$(USERDNSDOMAIN)* " />
    <Message Text=" USERDOMAIN = *$(USERDOMAIN)*       " />
    <Message Text=" USERNAME = *$(USERNAME)*           " />
</Target>

If you're using an "external MSBuild file" and need to pass a filename or path to it (because external MSBuild files do not like relative files if they are not in the same directory as the calling .msbuild file)....here is a convenient (3.5 and up I believe) Task.

    <ConvertToAbsolutePath Paths="..\"> <!-- Some relative path here -->
      <Output TaskParameter="AbsolutePaths" PropertyName="MyAbsolutionPathProperty"/>
    </ConvertToAbsolutePath>
    <Message Text="'MyAbsolutionPathProperty' = '$(MyAbsolutionPathProperty)'" />
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
granadaCoder
  • 26,328
  • 10
  • 113
  • 146
  • Why use `dir .` instead of `cd`? – binki Apr 10 '14 at 21:04
  • dir '.' reports the directory. cd is change_directory and will move me out of the folder. I guess you could do "cd ." but I don't see what that gives you over "dir '.'".... – granadaCoder Apr 10 '14 at 21:28
  • 1
    `dir .` prints out so much more than the working directory. `dir '.'` prints out an error message in addition to the CWD because no such file exists. [`CD`](http://ss64.com/nt/cd.html) with no arguments displays the current path without altering it. I am assuming we’re talking about cmd here, not what would happen if you ran your script through `xbuild` ;-). – binki Apr 10 '14 at 21:34
  • dir '.' doesn't report an error for me. It lists the directory and files/folders. I don't know about xbuild. – granadaCoder Apr 10 '14 at 21:42
  • http://imgur.com/fTudXkB , just sayin’ :-p. Works without the quotes but displays the directory listing instead of just your current directory (which is exactly and only what `CD` (with no arguments) prints out). Sorry, I’m nitpicking. But, for example, in `AppData\Local\Temp`, the output of `dir .` is quite unhelpful if you just want to know where you are because there are so many files in there… – binki Apr 11 '14 at 05:47
  • 'dir .' printed my root (c:\). Strange. 'cd' printed out dir of exec'ing batch file. – James John McGuire 'Jahmic' Jun 13 '16 at 14:07
13

MSBuild has reserved property called MSBuildProjectDirectory, which is to the absolute path of the directory where you project or script file is located, C:\Dev in your case. Therefore "$(MSBuildProjectDirectory)\temp" is exactly what you're looking for.

Igor Korkhov
  • 8,283
  • 1
  • 26
  • 31