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

Как я могу заставить 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)'" />

Выход

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

Я думаю, что метаданные FullPath применяются только к элементам <ItemGroup>, а не к свойствам <PropertyGroup>.

lesscode 07.10.2008 06:53

Я думаю, что вы правы, кто-нибудь знает способ перейти от Property к полному / абсолютному пути?

Eric Schoonover 07.10.2008 06:55

Вы могли бы "вроде" попасть туда, используя $ (ProjectDir) $ (Source_Dir), но у вас были бы лишние '..'

lesscode 07.10.2008 06:57
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
57
3
35 064
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

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

Чувак, я узнал больше о том, как создать задачу MS из этого фрагмента кода выше, чем когда-либо в документации MSBuild. Спасибо! :-)

evilhomer 06.11.2008 19:34

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

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

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

+1 Это прекрасно работает, и я (как и другие) приземлился здесь в поисках способа канонизировать ItemGroup (в значительной степени предполагая, что пакет и копирование в новую ItemGroup были необходимы) - синтаксис, который вы показываете, делает это без этой путаницы. IOW я забыл про FullPathХорошо известные метаданные

Ruben Bartelink 11.04.2012 18:45

Если вам нужно преобразовать свойства в элементы, у вас есть два варианта. С 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>
Ответ принят как подходящий

В MSBuild 4.0, проще всего так:

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

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

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


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

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

Зарезервированное свойство $ (MSBuildProjectDirectory) всегда является каталогом сценария, содержащего эту ссылку.

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

Будьте осторожны с [System.IO.Path]::GetFullPath. Я столкнулся с ошибкой построения в Visual Studio, потому что текущий рабочий каталог в msbuild был C:\Windows\System32. GetFullPath разрешается относительно рабочего каталога, а не каталога проекта.

Chris Chilvers 22.12.2015 20:19

@ChrisChilvers Это прискорбно. В прошлый раз, когда я тестировал это (правда, очень давно), это относилось к файлу, содержащему код.

Roman Starkov 25.12.2015 00:01

Он также работает для обратной трассировки путей в стиле ..\..\your\path. Также обратите внимание, что макрос $(MSBuildThisFileDirectory) уже включает в себя завершающую косую черту, поэтому вы должны указать your\path без ведущей косой черты, то есть $(MSBuildThisFileDirectory)your\path. Один из случаев, когда это имеет значение, - это когда вы используете его для OutDir для Microsoft Unit Testing Framework Test, когда вы пытаетесь запустить тесты, он не сможет оценить `\\` в конкатенированном пути, чтобы найти построенную dll.

Adam Yaxley 30.06.2016 05:05

@AdamYaxley GetFullPath автоматически сворачивает двойную обратную косую черту, поэтому он будет работать, даже если у вас есть эта дополнительная обратная косая черта. Ваша проблема должна быть связана с чем-то другим.

Roman Starkov 30.06.2016 19:51

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

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

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

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

+1 Ой, чувак. Отлично! Именно то, что я искал. Спасибо.

Asaf 25.07.2011 17:08

Он также оценивает путь относительно (насколько я понимаю) файла проекта, в котором определено свойство, что очень удобно, если вы хотите включить это свойство в другие файлы. Для меня это было идеальное решение.

Jean Hominal 23.04.2012 16:39

@JeanHominal Если вы используете <Import>, он все еще относительно места, куда он импортирован, что очень жаль. Тем не менее, это единственный подход, который также работает за пределами целей, что дает мне +1. См. этот ответ, чтобы узнать, как обойти проблему <Import>.

Roman Starkov 02.09.2012 18:59

Да, я ошибся, когда сказал, что сделал - все относительные пути всегда относятся к пути «выполняемого проекта» (проекта, который в настоящее время выполняется MSBuild); однако вы можете использовать $(MSBuildThisFileDirectory), чтобы получить полный путь к каталогу исполняемого в данный момент файла.

Jean Hominal 03.09.2012 02:36

Именно то, что мне нужно. Спасибо!

Cameron Chapman 13.02.2015 20:39

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