Как я могу заставить MSBUILD вычислять и печатать полный путь при указании относительного пути?

StackOverflow https://stackoverflow.com/questions/176931

Вопрос

Как я могу заставить MSBuild оценивать и печатать в <Message /> задать абсолютный путь, учитывая относительный путь?

Группа свойств

<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 Файлы (x86)\Program\'

Это было полезно?

Решение

В MSBuild 4.0, самый простой способ заключается в следующем:

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

Этот метод работает, даже если сценарий <Import>отредактировано в другой сценарий;путь указан относительно файла, содержащего приведенный выше код.

(консолидированный из Ответ Аарона так же , как и последняя часть Ответ Сайеда)


В MSBuild 3.5, вы можете использовать Преобразовать в абсолютный путь задача:

<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, существует подход, который не разрешает "..".Однако он ведет себя точно так же, как абсолютный путь:

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

В $(каталог msbuildproject) зарезервированным свойством всегда является каталог скрипта, который содержит эту ссылку.

Это также будет относительно "исходного" файла проекта, поэтому при размещении внутри файла, который получает <Import>эд, это не будет иметь отношения к этому файлу.

Другие советы

Добавлен MSBuild 4.0 Функции собственности которые позволяют вам вызывать статические функции в некоторых системных библиотеках dll .net.Действительно приятной особенностью функций свойств является то, что они будут оценивать вне целевой функции.

Чтобы оценить полный путь, вы можете использовать System.IO.Path.Получить полный путь при определении свойства следующим образом:

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

Синтаксис немного уродливый, но очень мощный.

Уэйн прав в том, что хорошо известные метаданные не применяются к свойствам - только к элементам.Использование таких свойств, как "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>

Вы пытаетесь получить доступ к свойству метаданных элемента через свойство, что невозможно.То, что вы хотите сделать, это что-то вроде этого:

<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 - это правильный относительный путь для доступа к моему рабочему столу.)

В вашем случае замените "..\Desktop" на "......\Public\Server" в элементе Source_Dir, и все должно быть готово.

Если вам нужно преобразовать свойства в Элементы, у вас есть два варианта.С помощью msbuild 2 вы можете использовать Создать элемент задача

  <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>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top