Como posso obter MSBUILD para avaliar e imprimir o caminho completo quando dado um caminho relativo?

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

Pergunta

Como posso obter MSBuild para avaliar e imprimir em uma tarefa <Message /> um caminho absoluto dado um caminho relativo?

Property Group

<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)'" />

saída

Copiar '' para 'c: \ Program Files (x86) \ Programas \'

Foi útil?

Solução

Em MSBuild 4.0 , a maneira mais fácil é o seguinte:

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

Este método funciona mesmo se o script é <Import>ed em outro script; o caminho é relativo para o arquivo que contém o código acima.

(consolidadas a partir resposta de Aaron, bem como a última parte do o Sayed resposta )


Em MSBuild 3.5 , você pode usar o ConvertToAbsolutePath tarefa:

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

saída 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\".

Um pouco prolixo, se você me perguntar, mas funciona. Isso vai ser relativo ao arquivo de projeto "original", por isso, se colocado dentro de um arquivo que fica <Import>ed, isso não vai ser relativo a esse arquivo.


Em MSBuild 2.0 , há uma abordagem que não resolver "..". Isto, contudo, se comportam como um caminho absoluto:

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

O $ (MSBuildProjectDirectory) reservados propriedade é sempre o diretório do script que contém esta referência.

Isso também vai ser relativo ao arquivo de projeto "original", por isso, se colocado dentro de um arquivo que fica <Import>ed, isso não vai ser relativo a esse arquivo.

Outras dicas

MSBuild 4,0 adicionados funções de propriedade que lhe permitem pôr em estática funções em algumas das DLLs do sistema .net. A coisa realmente agradável sobre funções de propriedade é que eles vão avaliar para fora do lado de um alvo.

Para avaliar um caminho completo que você pode usar Sistema. IO.Path.GetFullPath ao definir uma propriedade como assim:

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

A sintaxe é um pouco feio, mas muito poderosa.

Wayne é correto que bem conhecido metadados não se aplica a propriedades - apenas para itens. Usando propriedades como "MSBuildProjectDirectory" vai funcionar, mas eu não estou ciente de um construído em forma de resolver o caminho completo.

Outra opção é escrever uma tarefa simples, costume que terá um caminho relativo e cuspir o caminho totalmente resolvido. Seria algo parecido com isto:

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

E suas linhas MSBuild seria algo parecido com:

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

Você está tentando acessar uma propriedade de metadados item através de uma propriedade, o que não é possível. O que você quer fazer é algo como isto:

<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 irá gerar saída como:

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

(O script foi executado a partir de pasta Meus Documentos, então .. \ Desktop é o caminho relativo correto para chegar ao meu desktop.)

No seu caso, substitua a ".. \ Desktop" com "...... \ Public \ Server" no item diretório_origem e você deve estar tudo pronto.

Se você precisa converter Propriedades para os itens que você tem duas opções. Com msbuild 2, você pode usar o CreateItem tarefa

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

e com MSBuild 3,5 você pode ter ItemGroups dentro de um Task

  <Target Name='Build'>
    <ItemGroup>
      <SRCDIR2 Include='$(Source_Dir)' />
    </ItemGroup>
    <Message Text="%(SRCDIR2.FullPath)" />
    <Message Text="%(SRCDIR.FullPath)" />
  </Target>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top