当给定相对path时,如何让MSBUILD评估和打印完整path?

我怎样才能得到MSBuild评估和打印在一个<Message />任务给定一个相对path的绝对path?

物业集团

 <Source_Dir>..\..\..\Public\Server\</Source_Dir> <Program_Dir>c:\Program Files (x86)\Program\</Program_Dir> 

任务

 <Message Importance="low" Text="Copying '$(Source_Dir.FullPath)' to '$(Program_Dir)'" /> 

产量

将“'复制到'c:\ Program Files(x86)\ Program \'

在MSBuild 4.0中 ,最简单的方法如下:

 $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)\your\path')) 

即使脚本是<Import>编辑到另一个脚本,此方法仍然有效; 该path是相对于包含上述代码的文件。

(从亚伦的回答以及赛义德答案的最后一部分得到巩固)


在MSBuild 3.5中 ,您可以使用ConvertToAbsolutePath任务:

 <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Test" ToolsVersion="3.5"> <PropertyGroup> <Source_Dir>..\..\..\Public\Server\</Source_Dir> <Program_Dir>c:\Program Files (x86)\Program\</Program_Dir> </PropertyGroup> <Target Name="Test"> <ConvertToAbsolutePath Paths="$(Source_Dir)"> <Output TaskParameter="AbsolutePaths" PropertyName="Source_Dir_Abs"/> </ConvertToAbsolutePath> <Message Text='Copying "$(Source_Dir_Abs)" to "$(Program_Dir)".' /> </Target> </Project> 

相关产出:

 Project "P:\software\perforce1\main\XxxxxxXxxx\Xxxxx.proj" on node 0 (default targets). Copying "P:\software\Public\Server\" to "c:\Program Files (x86)\Program\". 

如果你问我,有点啰嗦,但是有用。 这将是相对于“原始”项目文件,所以如果放置在一个文件中获取<Import>编辑,这将不相对于该文件。


在MSBuild 2.0中 ,有一种方法不能解决“..”。 但是,它的行为就像一条绝对path:

 <PropertyGroup> <Source_Dir_Abs>$(MSBuildProjectDirectory)\$(Source_Dir)</Source_Dir_Abs> </PropertyGroup> 

$(MSBuildProjectDirectory)保留属性始终是包含此引用的脚本的目录。

这也将是相对于“原始”项目文件,所以如果放置在一个文件,获取<Import>编辑,这将不相对于该文件。

MSBuild 4.0添加了属性函数 ,它允许你调用一些.net系统DLL中的静态函数。 关于属性函数的一个非常好的事情是,他们将评估一个目标的一面。

为了评估一个完整的path,你可以在定义属性时使用System.IO.Path.GetFullPath :

 <PropertyGroup> <Source_Dir>$([System.IO.Path]::GetFullPath('..\..\..\Public\Server\'))</Source_Dir> </PropertyGroup> 

语法有点丑,但非常强大。

韦恩是正确的,众所周知的元数据不适用于属性 – 只适用于项目。 使用属性,如“MSBuildProjectDirectory”将工作,但我不知道内置的方式来解决完整的path。

另一个select是编写一个简单的自定义任务,它将采取一个相对path并吐出完全parsing的path。 它看起来像这样:

 public class ResolveRelativePath : Task { [Required] public string RelativePath { get; set; } [Output] public string FullPath { get; private set; } public override bool Execute() { try { DirectoryInfo dirInfo = new DirectoryInfo(RelativePath); FullPath = dirInfo.FullName; } catch (Exception ex) { Log.LogErrorFromException(ex); } return !Log.HasLoggedErrors; } } 

而你的MSBuild行看起来像这样:

 <PropertyGroup> <TaskAssembly>D:\BuildTasks\Build.Tasks.dll</TaskAssembly> <Source_Dir>..\..\..\Public\Server\</Source_Dir> <Program_Dir>c:\Program Files (x86)\Program\</Program_Dir> </PropertyGroup> <UsingTask AssemblyFile="$(TaskAssembly)" TaskName="ResolveRelativePath" /> <Target Name="Default"> <ResolveRelativePath RelativePath="$(Source_Dir)"> <Output TaskParameter="FullPath" PropertyName="_FullPath" /> </ResolveRelativePath> <Message Importance="low" Text="Copying '$(_FullPath)' to '$(Program_Dir)'" /> </Target> 

您正尝试通过属性访问项目元数据属性,这是不可能的。 你想要做的是这样的:

 <PropertyGroup> <Program_Dir>c:\Program Files (x86)\Program\</Program_Dir> </PropertyGroup> <ItemGroup> <Source_Dir Include="..\Desktop"/> </ItemGroup> <Target Name="BuildAll"> <Message Text="Copying '%(Source_Dir.FullPath)' to '$(Program_Dir)'" /> </Target> 

这将产生的输出为:

  Copying 'C:\Users\sdorman\Desktop' to 'c:\Program Files (x86)\Program\' 

(脚本从我的Documents文件夹运行,所以.. \ Desktop是到达我的桌面的正确的相对path。)

在你的情况下,用Source_Dir项目中的“…… \ Public \ Server”replace“.. \ Desktop”,你应该全部设置。

如果您需要将“属性”转换为“项目”,则有两个选项。 使用msbuild 2,您可以使用CreateItem任务

  <Target Name='Build'> <CreateItem Include='$(Source_Dir)'> <Output ItemName='SRCDIR' TaskParameter='Include' /> </CreateItem> 

和MSBuild 3.5你可以有一个任务内的ItemGroups

  <Target Name='Build'> <ItemGroup> <SRCDIR2 Include='$(Source_Dir)' /> </ItemGroup> <Message Text="%(SRCDIR2.FullPath)" /> <Message Text="%(SRCDIR.FullPath)" /> </Target>