在给定相对路径时,如何让MSBUILD计算并打印完整路径?

在给定相对路径时,如何让MSBUILD计算并打印完整路径?,msbuild,relative-path,absolute-path,Msbuild,Relative Path,Absolute Path,如何让MSBuild在任务中计算并打印给定相对路径的绝对路径 地产集团 <Source_Dir>..\..\..\Public\Server\</Source_Dir> <Program_Dir>c:\Program Files (x86)\Program\</Program_Dir> 。\..\..\Public\Server\ c:\Program Files(x86)\Program\ 任务 <Message Importance=

如何让MSBuild在
任务中计算并打印给定相对路径的绝对路径

地产集团

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

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

输出

正在将“”复制到c:\Program Files(x86)\Program\s


Wayne说的没错,众所周知的元数据不适用于属性——只适用于项。使用诸如“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;
    }
}
<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>
您的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>

D:\BuildTasks\Build.Tasks.dll
..\..\..\Public\Server\
c:\Program Files(x86)\Program\

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

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;
    }
}
<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>
(脚本是从“我的文档”文件夹运行的,因此..\Desktop是访问“我的桌面”的正确相对路径。)


在您的情况下,将“源目录”项目中的“.\Desktop”替换为“…..\Public\Server”,您应该已完成所有设置。

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

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

使用MSBuild 3.5,您可以在任务中包含项组

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


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

$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)\your\path'))
即使将脚本
插入到另一个脚本中,此方法仍然有效;路径是相对于包含上述代码的文件的

(合并自以及最后一部分)


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

如果你问我的话,我会说得有点冗长,但这是有效的。这将是相对于“原始”项目文件的,因此,如果将其放置在一个被
编辑的文件中,则它不会相对于该文件


在MSBuild 2.0中,有一种方法无法解析“.”。但是,它的行为与绝对路径一样:

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

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

这也将与“原始”项目文件相关,因此,如果将其放置在一个得到
编辑的文件中,则它不会与该文件相关。

添加了MSBuild 4.0,它允许您调用某些.net系统DLL中的静态函数。属性函数的一个非常好的方面是,它们将在目标之外进行求值

要在定义这样的属性时计算可以使用的完整路径,请执行以下操作:

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

$([System.IO.Path]::GetFullPath('..\..\..\Public\Server\'))

语法有点难看,但非常强大。

我认为完整路径元数据只适用于项,而不适用于属性。我想你是对的,有人知道从属性到完整/绝对路径的方法吗?你可以通过使用$(ProjectDir)$(Source\u Dir)“有点”达到目的,但你会有多余的',我从上面的那段代码中学到了更多关于如何构建MS任务的知识,这是我在MSBuild文档中所学到的。谢谢!:-)+1哦,伙计。这太棒了!正是我想要的。谢谢。它还会计算相对于(据我所见)定义属性的项目文件的路径,当您希望在其他文件中包含该属性时,这非常好。对我来说,这是一个完美的解决方案。@JeanHominal如果你使用
,它仍然是相对于它导入到的位置的,这是一个遗憾。尽管如此,这是唯一一种在目标之外也有效的方法,我认为这是一个+1。有关解决
问题的方法,请参阅。是的,当我说我所做的事情时,我弄错了-所有相对路径总是相对于“正在执行的项目”路径(MSBuild当前正在执行的项目);但是,您可以使用
$(MSBuildThisFileDirectory)
获取当前正在执行的文件目录的完整路径。这正是我所需要的。谢谢+1这很好地工作,我(和其他人一样)在这里找到了一种规范化项目组的方法(基本上假设需要批处理并复制到一个新的项目组)——您显示的语法可以做到这一点。我忘记了
FullPath
小心
[System.IO.Path]::GetFullPath
。我在Visual Studio中生成时遇到错误,因为msbuild中的当前工作目录是
C:\Windows\System32
GetFullPath
相对于工作目录而不是项目目录进行解析。@ChrisChilvers这很不幸。上次我测试它时(承认是很久以前),它是相对于包含代码的文件的。它也适用于回溯
。\..\your\path
样式路径。还请注意,
$(MSBuildThisFileDirectory)
宏已经包含一个尾随斜杠,因此必须指定
your\path
,而不带前导斜杠,即
$(MSBuildThisFileDirectory)your\path
。当您将它用于Microsoft单元测试框架的
OutDir
测试时,当您尝试运行测试时,它将无法计算连接路径中的“\\”以找到构建的dll。@AdamYaxley
GetFullPath
自动折叠双反斜杠,因此,即使你有额外的反斜杠,它也会起作用。你的问题一定是因为别的原因。
<PropertyGroup>
  <Source_Dir>$([System.IO.Path]::GetFullPath('..\..\..\Public\Server\'))</Source_Dir>
</PropertyGroup>