¿Cómo puedo hacer que MSBUILD evalúe e imprima la ruta completa cuando se me da una ruta relativa?

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

Pregunta

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

¿Fue útil?

Solución

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

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

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

(consolidado de Respuesta de Aaron , así como la última parte de La respuesta de Sayed )


En MSBuild 3.5 , puede usar el 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 a & Quot; original & Quot; archivo de proyecto, por lo que si se coloca dentro de un archivo que se <=> 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>

El $ (MSBuildProjectDirectory) reservado La propiedad siempre es el directorio del script que contiene esta referencia.

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

Otros consejos

MSBuild 4.0 agregó Funciones de propiedad que le permiten llamar a estática funciona en algunos de los dlls del sistema .net. Una cosa realmente buena acerca de las funciones de propiedad es que evaluarán fuera del objetivo.

Para evaluar una ruta completa, puede usar el Sistema. 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.

Wayne tiene razón en que los metadatos conocidos no se aplican a las propiedades, solo a los elementos. Usando propiedades como & Quot; MSBuildProjectDirectory & Quot; funcionará, pero no conozco una forma integrada de resolver la ruta completa.

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

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 MSBuild se verían 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>

Está intentando acceder a una propiedad de metadatos del elemento 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á resultados 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 llegar a mi escritorio).

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

Si necesita convertir Propiedades a 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 puedes tener ItemGroups dentro de una tarea

  <Target Name='Build'>
    <ItemGroup>
      <SRCDIR2 Include='$(Source_Dir)' />
    </ItemGroup>
    <Message Text="%(SRCDIR2.FullPath)" />
    <Message Text="%(SRCDIR.FullPath)" />
  </Target>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top