2008-10-07 15 views
53

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

Group Property

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

+0

Я думаю, что метаданные FullPath применяются только к объектам , а не к свойствам . – lesscode 2008-10-07 02:53:47

+0

Я думаю, что вы правы, любой знает, как добраться от Имущества до полного/абсолютного пути? – 2008-10-07 02:55:14

+1

Вы могли бы «любопытно» добраться туда, используя $ (ProjectDir) $ (Source_Dir), , но у вас было бы лишнее '..' – lesscode 2008-10-07 02:57:29

ответ

86

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

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

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

(консолидируются с Aaron's answer, а также последней части Sayed's 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) зарезервирован свойство всегда каталог скрипта, который содержит эту ссылку.

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

6

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

Dude, Я узнал больше о том, как построить MS-задачу из этой части выше, чем когда-либо в документации MSBuild. Спасибо! :-) – evilhomer 2008-11-06 16:34:04

5

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

<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, и вы должны быть настроены.

+0

+1 Это хорошо работает, и я (как и другие) приземлился здесь, чтобы найти способ канонизировать ItemGroup (в значительной степени предполагая, что пакет и копия в новую ItemGroup были необходимы) - синтаксис, который вы показываете, делает это без этой путаницы , IOW Я забыл о `FullPath` [Хорошо известные метаданные] (http://msdn.microsoft.com/en-us/library/ms164313.aspx) – 2012-04-11 14:45:09

4

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

MSBuild 4.0 добавлен Property Functions, который позволяет вам вызвать статические функции в некоторых системных DLL-системах .net. Очень хорошая вещь о свойствах функций заключается в том, что они будут оценивать сторону цели.

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

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

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