urls una rutas ruta relativos relativas relativa qué entre ejemplo diferencia acceso absolutos absolutas absoluta msbuild relative-path absolute-path

rutas - ¿Cómo puedo obtener MSBUILD para evaluar e imprimir la ruta completa cuando se le da una ruta relativa?



url relativos y absolutos (5)

¿Cómo puedo hacer que MSBuild evalúe e imprima en una tarea <Message /> una ruta absoluta dada una ruta relativa?

Grupo de propiedades

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

Tarea

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

Salida

Copiando '''' a ''c: / Archivos de programa (x86) / Programa /'


Está intentando acceder a una propiedad de metadatos de elementos a través de una propiedad, que no es posible. Lo que quieres hacer es algo como esto:

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

Que generará salida como:

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

(El script se ejecutó desde mi carpeta Documentos, así que .. / Desktop es la ruta relativa correcta para acceder a mi escritorio).

En su caso, reemplace ".. / Desktop" con "...... / Public / Server" en el elemento Source_Dir y debería estar todo listo.


MSBuild 4.0 agregó funciones de propiedad que le permiten llamar a funciones estáticas en algunos de los dlls del sistema .net. Algo realmente bueno acerca de las funciones de propiedad es que evaluarán el lado de un objetivo.

Para evaluar una ruta completa, puede usar System.IO.Path.GetFullPath al definir una propiedad como esta:

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

La sintaxis es un poco fea pero muy poderosa.


Si necesita convertir Propiedades en Elementos, tiene dos opciones. Con msbuild 2, puede usar la tarea CreateItem

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

y con MSBuild 3.5 puede tener ItemGroups dentro de una Tarea

<Target Name=''Build''> <ItemGroup> <SRCDIR2 Include=''$(Source_Dir)'' /> </ItemGroup> <Message Text="%(SRCDIR2.FullPath)" /> <Message Text="%(SRCDIR.FullPath)" /> </Target>


Wayne tiene razón en que los metadatos bien conocidos no se aplican a las propiedades, solo a los elementos. Usar propiedades como "MSBuildProjectDirectory" funcionará, pero no conozco un camino integrado para resolver la ruta completa.

Otra opción es escribir una tarea simple y personalizada que tomará una ruta relativa y escupirá la ruta totalmente resuelta. Se vería algo como esto:

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

Y sus líneas de MSBuild se verían más o menos así:

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


En MSBuild 4.0 , la manera más fácil es la siguiente:

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

Este método funciona incluso si el script está <Import> ed en otro script; la ruta es relativa al archivo que contiene el código anterior.

(consolidado a partir de la respuesta de Aaron, así como de la última parte de la respuesta de Sayed )

En MSBuild 3.5 , puede usar la tarea 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>

Salida relevante:

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

Un poco largo si me preguntas, pero funciona. Esto será relativo al archivo de proyecto "original", por lo que si se coloca dentro de un archivo que obtiene <Import> ed, esto no será relativo a ese archivo.

En MSBuild 2.0 , hay un enfoque que no resuelve "...". Sin embargo, se comporta como una ruta absoluta:

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

La propiedad reservada $ (MSBuildProjectDirectory) es siempre el directorio de la secuencia de comandos que contiene esta referencia.

Esto también será relativo al archivo de proyecto "original", por lo que si se coloca dentro de un archivo que obtiene <Import> ed, esto no será relativo a ese archivo.