Как я могу заставить MSBUILD оценивать и печатать полный путь при предоставлении относительного пути?
Как я могу заставить MSBuild оценивать и печатать в задаче <Message />
абсолютный путь, заданный относительным путем?
Группа свойств
<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)'" />
Выход
Копирование '' в 'c:\Program Files (x86)\Program \'
Ответы
Ответ 1
В MSBuild 4.0 самый простой способ:
$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)\your\path'))
Этот метод работает, даже если script <Import>
ed в другой script; путь относится к файлу, содержащему указанный выше код.
(консолидировано из ответа Аарона, а также последняя часть Sayed 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) зарезервированное свойство всегда является каталогом script, который содержит эту ссылку.
Это также будет относиться к "оригинальному" файлу проекта, поэтому, если он помещен внутри файла, который получает <Import>
ed, это не относится к этому файлу.
Ответ 2
MSBuild 4.0 добавила Функции свойств, которые позволяют вам вызывать статические функции в некоторых системных dll.net. Очень хорошая вещь о свойствах функций заключается в том, что они будут оценивать сторону цели.
Чтобы определить полный путь, вы можете использовать System.IO.Path.GetFullPath при определении такого свойства:
<PropertyGroup>
<Source_Dir>$([System.IO.Path]::GetFullPath('..\..\..\Public\Server\'))</Source_Dir>
</PropertyGroup>
Синтаксис немного уродливый, но очень мощный.
Ответ 3
Уэйн прав, что известные метаданные не относятся к свойствам - только к элементам. Использование таких свойств, как "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
Вы пытаетесь получить доступ к свойству метаданных элемента через свойство, что невозможно. То, что вы хотите сделать, выглядит примерно так:
<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\'
(script был запущен из моей папки "Документы", поэтому..\Рабочий стол - это правильный относительный путь для доступа к моему рабочему столу.)
В вашем случае замените "..\Desktop" на "......\Public\Server" в элементе Source_Dir, и все должно быть установлено.
Ответ 5
Если вам нужно преобразовать свойства в элементы, у вас есть два варианта. С помощью 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>