如何在MSBuild脚本中获取当前目录?

73
在我的MSBuild脚本中,我需要将完整的目录作为参数传递。我该如何获取它?
例如:我正在从 C:\dev 运行脚本,我想要一个相对路径 temp,因此我需要 C:\dev\temp
注意:我不知道脚本将从哪个文件夹运行。

你的临时文件夹是否总是位于运行此脚本的位置的子文件夹中? - brunch
3个回答

110

Igor说得很接近了。 MSBuildProjectDirectory是该属性将为您提供在命令行上调用的项目文件的完整路径。因此,如果您有以下脚本:

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

并且MyProj.proj导入shared.targets,并且这是传递给msbuild.exe的文件,则MSBuildProjectDirectory的值始终为C:\ temp ,即使您在其中引用了 shared.targets。 如果shared.targets需要路径知识,则应在已知属性中声明这些属性。例如,C#项目文件定义OutputPath的值,并且共享文件Microsoft.Common.targets使用该属性。

编辑:MSBuild 4

如果您正在使用MSBuild 4,则还可以使用这些属性来获取此类型的值。

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

请参见http://sedodream.com/2010/03/11/MSBuild40ReservedProperties.aspx


4
请注意,那些新的MSBuild 4保留属性虽然被支持,但它们并未列在Visual Studio 2010编辑对话框中的宏列表中。 - Amro

60

以下是三个有帮助的目标。

WhereAmI 是我在试图确定当前目录时使用的一个。

其他目标也很有信息价值(有些超出问题范围)。

<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>

如果你正在使用“外部MSBuild文件”并需要向其中传递文件名或路径(因为如果它们不在调用的.msbuild文件所在目录中,外部MSBuild文件就不喜欢相对文件)...这里有一个便捷的(我认为是3.5及更高版本)任务。

    <ConvertToAbsolutePath Paths="..\"> <!-- Some relative path here -->
      <Output TaskParameter="AbsolutePaths" PropertyName="MyAbsolutionPathProperty"/>
    </ConvertToAbsolutePath>
    <Message Text="'MyAbsolutionPathProperty' = '$(MyAbsolutionPathProperty)'" />

为什么使用 dir . 而不是 cd - binki
dir '.' 显示目录。 cd 是改变目录并将我移出文件夹。 我想你可以做“cd .”,但我不知道它能比“dir '.'”给你更多什么... - granadaCoder
1
“dir .” 打印出的内容比工作目录要多得多。“dir '.'” 除了当前工作目录之外,还会打印出一个错误信息,因为没有这样的文件。CD 如果没有参数,则显示当前路径而不更改它。我假设我们在谈论 cmd,而不是如果您通过 xbuild 运行脚本会发生什么;-)。 - binki
dir '.' 对我来说没有报错。它列出了目录和文件/文件夹。我不知道 xbuild。 - granadaCoder
http://imgur.com/fTudXkB,只是说一下 :-p。不加引号可以工作,但会显示目录列表,而不仅仅是您当前的目录(这正是CD(没有参数)打印的内容)。抱歉,我在挑剔。但是,例如,在AppData\Local\Temp中,如果您只想知道自己在哪里,那么dir .的输出非常无用,因为其中有很多文件... - binki
"dir ." 打印了我的根目录(c:\)。很奇怪。"cd" 打印出了执行批处理文件的目录。 - James John McGuire 'Jahmic'

13

MSBuild有一个保留属性叫做MSBuildProjectDirectory,它指的是项目或脚本文件所在目录的绝对路径,在你的情况下是C:\Dev。因此,"$(MSBuildProjectDirectory)\temp"就是你要找的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接