Come posso ottenere MSBUILD per valutare e stampare il percorso completo quando viene dato un percorso relativo?

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

Domanda

Come posso ottenere MSBuild per valutare e stampare in un'attività <Message /> un percorso assoluto dato un percorso relativo?

Gruppo di proprietà

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

attività

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

Output

  

Copia '' in 'c: \ Programmi (x86) \ Program \'

È stato utile?

Soluzione

In MSBuild 4.0 , il modo più semplice è il seguente:

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

Questo metodo funziona anche se lo script è <Import> inserito in un altro script; il percorso è relativo al file contenente il codice sopra.

(consolidato da la risposta di Aaron e dall'ultima parte di Risposta di Sayed )


In MSBuild 3.5 , puoi utilizzare attività 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>

Output pertinente:

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 po 'prolisso se me lo chiedi, ma funziona. Questo sarà relativo al & Quot; originale & Quot; file di progetto, quindi se inserito in un file che viene <=> ed, questo non sarà relativo a quel file.


In MSBuild 2.0 , esiste un approccio che non risolve " .. " ;. Tuttavia si comporta proprio come un percorso assoluto:

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

Il $ (MSBuildProjectDirectory) riservato La proprietà è sempre la directory dello script che contiene questo riferimento.

Questo sarà anche relativo al " originale " file di progetto, quindi se inserito in un file che viene <=> ed, questo non sarà relativo a quel file.

Altri suggerimenti

MSBuild 4.0 ha aggiunto Funzioni proprietà che ti consentono di chiamare in modalità statica funziona in alcune delle dll di sistema .net. Una cosa davvero bella delle funzioni di proprietà è che valuteranno il lato di un obiettivo.

Per valutare un percorso completo è possibile utilizzare il sistema . IO.Path.GetFullPath quando si definisce una proprietà in questo modo:

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

La sintassi è un po 'brutta ma molto potente.

Wayne ha ragione che i metadati noti non si applicano alle proprietà, ma solo agli oggetti. Utilizzo di proprietà come & Quot; MSBuildProjectDirectory & Quot; funzionerà, ma non sono a conoscenza di un modo integrato per risolvere il percorso completo.

Un'altra opzione è scrivere un'attività semplice e personalizzata che prenderà un percorso relativo e sputerà il percorso completamente risolto. Sarebbe simile a questo:

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 le tue linee di MSBuild sarebbero simili a:

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

Stai tentando di accedere a una proprietà dei metadati dell'elemento tramite una proprietà, il che non è possibile. Quello che vuoi fare è qualcosa del genere:

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

Che genererà output come:

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

(Lo script è stato eseguito dalla mia cartella Documenti, quindi .. \ Desktop è il percorso relativo corretto per accedere al mio desktop.)

Nel tuo caso, sostituisci il " .. \ Desktop " con " ...... \ Public \ Server " nell'elemento Source_Dir e dovresti essere tutto pronto.

Se devi convertire le Proprietà in Articoli hai due opzioni. Con msbuild 2, puoi utilizzare l'attività CreateItem

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

e con MSBuild 3.5 puoi avere ItemGroups all'interno di un'attività

  <Target Name='Build'>
    <ItemGroup>
      <SRCDIR2 Include='$(Source_Dir)' />
    </ItemGroup>
    <Message Text="%(SRCDIR2.FullPath)" />
    <Message Text="%(SRCDIR.FullPath)" />
  </Target>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top