当给定相对路径时,如何让 MSBUILD 评估并打印完整路径?

发布于 2024-07-07 08:07:56 字数 522 浏览 13 评论 0原文

如何让 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)\Program\”

How can I get MSBuild to evaluate and print in a <Message /> task an absolute path given a relative path?

Property Group

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

Task

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

Output

Copying '' to 'c:\Program Files (x86)\Program\'

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

¢好甜 2024-07-14 08:07:57

如果您需要将属性转换为项目,您有两种选择。 在 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>

If you need to convert Properties to Items you have two options. With msbuild 2, you can use the CreateItem task

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

and with MSBuild 3.5 you can have ItemGroups inside of a Task

  <Target Name='Build'>
    <ItemGroup>
      <SRCDIR2 Include='$(Source_Dir)' />
    </ItemGroup>
    <Message Text="%(SRCDIR2.FullPath)" />
    <Message Text="%(SRCDIR.FullPath)" />
  </Target>
女中豪杰 2024-07-14 08:07:56

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

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

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

(综合Aaron的回答以及Sayed 的回答


在 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\".

如果你问我的话,有点啰嗦,但它有效。 这将相对于“原始”项目文件,因此如果放置在经过 编辑的文件内,则这不会相对于该文件。


在 MSBuild 2.0 中,有一种方法无法解析“..”。 然而,它的行为就像绝对路径一样:

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

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

这也将相对于“原始”项目文件,因此如果放置在经过 编辑的文件内,则这不会相对于该文件。

In MSBuild 4.0, the easiest way is the following:

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

This method works even if the script is <Import>ed into another script; the path is relative to the file containing the above code.

(consolidated from Aaron's answer as well as the last part of Sayed's answer)


In MSBuild 3.5, you can use the ConvertToAbsolutePath task:

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

Relevant output:

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

A little long-winded if you ask me, but it works. This will be relative to the "original" project file, so if placed inside a file that gets <Import>ed, this won't be relative to that file.


In MSBuild 2.0, there is an approach which doesn't resolve "..". It does however behave just like an absolute path:

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

The $(MSBuildProjectDirectory) reserved property is always the directory of the script that contains this reference.

This will also be relative to the "original" project file, so if placed inside a file that gets <Import>ed, this won't be relative to that file.

微凉徒眸意 2024-07-14 08:07:56

MSBuild 4.0 添加了属性函数,允许您在某些情况下调用静态函数.net 系统 dll。 属性函数的一个非常好的事情是它们将在目标之外进行计算。

要评估完整路径,您可以使用 System.IO.Path .GetFullPath 在定义属性时,如下所示:

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

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

MSBuild 4.0 added Property Functions which allow you to call into static functions in some of the .net system dlls. A really nice thing about Property Functions is that they will evaluate out side of a target.

To evaluate a full path you can use System.IO.Path.GetFullPath when defining a property like so:

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

The syntax is a little ugly but very powerful.

白衬杉格子梦 2024-07-14 08:07:56

韦恩是正确的,众所周知的元数据不适用于属性 - 仅适用于项目。 使用“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>

Wayne is correct that well-known metadata does not apply to properties - only to items. Using properties such as "MSBuildProjectDirectory" will work, but I'm not aware of a built in way to resolve the full path.

Another option is to write a simple, custom task that will take a relative path and spit out the fully-resolved path. It would look something like this:

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

And your MSBuild lines would look something like:

<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>
泪意 2024-07-14 08:07:56

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

<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 项中包含“..\Desktop”和“......\Public\Server”,您应该已全部设置完毕。

You are trying to access an item metadata property through a property, which isn't possible. What you want to do is something like this:

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

Which will generate output as:

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

(The script was run from my Documents folder, so ..\Desktop is the correct relative path to get to my desktop.)

In your case, replace the "..\Desktop" with "......\Public\Server" in the Source_Dir item and you should be all set.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文