2008-10-07 101 views
53

如何让MSBuild评估和打印<Message />任务中给定相对路径的绝对路径?如何在给定相对路径时让MSBUILD评估和打印完整路径?

地产集团

<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)的\程序\ '

+0

我认为FullPath元数据仅适用于项目,而不适用于属性。 – lesscode 2008-10-07 02:53:47

+0

我认为你是对的,任何人都知道从财产获得完整/绝对路径的方式? – 2008-10-07 02:55:14

+1

你可以通过使用$(ProjectDir)$(Source_Dir), ,但你会有多余的'..' – lesscode 2008-10-07 02:57:29

回答

86

在MSBuild的4.0,最简单的方法是以下:

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

此方法效果即使脚本是<Import>编入另一个脚本;该路径与包含上述代码的文件相关。


(从Aaron's answer以及为Sayed's answer最后一部分合并)在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> ed的文件中,则这不会与该文件有关。


在MSBuild的2.0,存在不解决的方法 “..”。但它确实表现得就像是一个绝对路径:

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

$(MSBuildProjectDirectory)保留属性始终包含此参考脚本的目录。

这也将相对于“原始”项目文件,因此如果放置在获取<Import> ed的文件中,则这不会与该文件有关。

6

韦恩是正确的,众所周知的元数据不适用于属性 - 只对项目。使用诸如“MSBuildProjectDirectory”之类的属性可以工作,但我不知道内置的解决完整路径的方法。

另一种选择是编写一个简单的自定义任务,它将采用相对路径并吐出完全解析的路径。这将是这个样子:

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

伙计, 我已经学会了更多关于如何从这段上面的代码,然后我有在MSBuild文档。 谢谢! :-) – evilhomer 2008-11-06 16:34:04

5

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

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

(剧本是从我的文档文件夹中运行,所以.. \ Desktop是正确的相对路径到达我的桌面。)

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

+0

+1这很好,我(像其他人)在这里登陆寻找一种方法来规范一个ItemGroup(几乎假设一个批次和复制到一个新的ItemGroup是必要的) - 你显示的语法没有这种混淆。 IOW我忘记了`FullPath` [众所周知的元数据](http://msdn.microsoft.com/en-us/library/ms164313.aspx) – 2012-04-11 14:45:09

4

如果您需要将属性转换为项目,您有两个选项。随着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> 
31

MSBuild 4.0增加了Property Functions它允许你调用某些.net系统dll的静态函数。关于属性函数的一个很好的事情就是他们会评估一个目标。

评价定义一个属性,像这样的时候,你可以使用System.IO.Path.GetFullPath完整路径:

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

的语法是有点难看,但功能非常强大。