62 Stimmen

Wie kann ich MSBUILD dazu bringen, den vollständigen Pfad auszuwerten und zu drucken, wenn ein relativer Pfad angegeben wird?

Wie kann ich MSBuild dazu bringen, die Auswertung und den Druck in einer <Message /> einen absoluten Pfad in einen relativen Pfad umwandeln?

Immobiliengruppe

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

Aufgabe

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

Ausgabe

Kopieren von '' nach 'c: \Program Dateien (x86) \Program\ '

0 Stimmen

Ich denke, dass FullPath-Metadaten nur für <ItemGroup>-Elemente gelten, nicht für <PropertyGroup>-Eigenschaften.

0 Stimmen

Ich denke, Sie haben Recht. Kennt jemand einen Weg, um von der Eigenschaft zu einem vollständigen/absoluten Pfad zu gelangen?

1 Stimmen

Sie könnten "irgendwie" dorthin gelangen, indem Sie $(ProjectDir)$(Source_Dir) verwenden, aber Sie würden überflüssige '..'s haben

108voto

Roman Starkov Punkte 55278

In MSBuild 4.0 Der einfachste Weg ist der folgende:

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

Diese Methode funktioniert auch, wenn das Skript <Import> in ein anderes Skript eingefügt werden; der Pfad ist relativ zu der Datei, die den obigen Code enthält.

(konsolidiert von Aaron's Antwort sowie den letzten Teil von Sayed's Antwort )


In MSBuild 3.5 können Sie die ConvertToAbsolutePath Aufgabe:

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

Relevanter Output:

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

Ein bisschen langatmig, wenn Sie mich fragen, aber es funktioniert. Sie ist relativ zur "Original"-Projektdatei, d.h. wenn sie innerhalb einer Datei platziert wird, die <Import> ist dies nicht relativ zu dieser Datei.


In MSBuild 2.0 gibt es einen Ansatz, der ".." nicht auflöst. Er verhält sich jedoch genau wie ein absoluter Pfad:

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

El $(MSBuildProjectDirectory) reservierte Eigenschaft ist immer das Verzeichnis des Skripts, das diesen Verweis enthält.

Diese wird auch relativ zur "Original"-Projektdatei sein, wenn sie also innerhalb einer Datei platziert wird, die <Import> ist dies nicht relativ zu dieser Datei.

0 Stimmen

Seien Sie vorsichtig mit [System.IO.Path]::GetFullPath . Ich bin auf einen Fehler beim Erstellen in Visual Studio gestoßen, weil das aktuelle Arbeitsverzeichnis in msbuild war C:\Windows\System32 . GetFullPath wird relativ zum Arbeitsverzeichnis und nicht zum Projektverzeichnis aufgelöst.

0 Stimmen

@ChrisChilvers Das ist bedauerlich. Das letzte Mal, als ich dies getestet habe (zugegebenermaßen vor langer Zeit), war es relativ zu der Datei, die den Code enthält.

0 Stimmen

Es funktioniert auch für die Rückverfolgung ..\..\your\path Stilpfade. Beachten Sie auch, dass die $(MSBuildThisFileDirectory) Makro enthält bereits einen abschließenden Schrägstrich, so dass Sie Folgendes angeben müssen your\path ohne den führenden Schrägstrich, d.h. $(MSBuildThisFileDirectory)your\path . Ein Fall, in dem dies wichtig ist, ist die Verwendung für eine OutDir für einen Microsoft-Unit-Testing-Framework-Test, können die Tests nicht ausgewertet werden, wenn Sie versuchen, die ` \\ ` in den verketteten Pfad ein, um die erstellte DLL zu finden.

35voto

Aaron Carlson Punkte 5247

MSBuild 4.0 hinzugefügt Eigenschaftsfunktionen die es Ihnen ermöglichen, statische Funktionen in einigen der .net-System-DLLs aufzurufen. Eine wirklich schöne Sache über Property Functions ist, dass sie außerhalb eines Ziels auswerten werden.

Um einen vollständigen Pfad auszuwerten, können Sie verwenden System.IO.Path.GetFullPath wenn Sie eine Eigenschaft wie diese definieren:

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

Die Syntax ist ein wenig hässlich, aber sehr leistungsfähig.

0 Stimmen

+1 Oh Mann. Das ist großartig! Genau das, wonach ich gesucht habe. Danke!

0 Stimmen

Außerdem wird der Pfad relativ zu der Projektdatei ausgewertet, in der die Eigenschaft definiert ist, was sehr praktisch ist, wenn Sie die Eigenschaft in andere Dateien einfügen möchten. Für mich war das die perfekte Lösung.

0 Stimmen

@JeanHominal Wenn Sie die <Import> Es ist immer noch relativ zu dem Ort, an den es importiert wird, was eine Schande ist. Dennoch ist dies der einzige Ansatz, der auch außerhalb von Zielen funktioniert, was ihm von mir ein +1 einbringt. Siehe diese Antwort für eine Möglichkeit, das Problem der <Import> Problem.

8voto

brock.holum Punkte 3033

Wayne hat Recht, dass die bekannten Metadaten nicht für Eigenschaften gelten, sondern nur für Objekte. Mit Eigenschaften wie "MSBuildProjectDirectory" wird funktionieren, aber ich bin mir nicht bewusst von einem eingebauten Weg, um den vollständigen Pfad aufzulösen.

Eine andere Möglichkeit besteht darin, eine einfache, benutzerdefinierte Aufgabe zu schreiben, die einen relativen Pfad annimmt und den vollständig aufgelösten Pfad ausspuckt. Sie würde etwa so aussehen:

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

Und Ihre MSBuild-Zeilen würden etwa so aussehen:

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

6 Stimmen

Alter, ich habe mehr darüber gelernt, wie man einen MS Task erstellt, als ich jemals in der MSBuild Dokumentation gelesen habe. Vielen Dank dafür! :-)

5voto

Scott Dorman Punkte 41206

Sie versuchen, über eine Eigenschaft auf eine Metadateneigenschaft eines Elements zuzugreifen, was nicht möglich ist. Was Sie tun möchten, ist etwas wie dies:

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

Das erzeugt die folgende Ausgabe:

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

(Das Skript wurde von meinem Dokumentenordner aus ausgeführt, also \Desktop ist der richtige relative Pfad, um zu meinem Desktop zu gelangen).

In Ihrem Fall ersetzen Sie die " \Desktop " mit "...... \Public\Server " in den Eintrag Source_Dir ein und schon sollte alles fertig sein.

0 Stimmen

+1 Dies funktioniert gut und ich (wie andere) landete hier auf der Suche nach einem Weg, um eine ItemGroup zu kanonisieren (ziemlich viel vorausgesetzt, ein Stapel und Kopie zu einer neuen ItemGroup war notwendig) - die Syntax, die Sie zeigen, tut es ohne diese Verwirrung. D.h. ich hatte vergessen, dass die FullPath Bekannte Metadaten

4voto

Scott Weinstein Punkte 18520

Wenn Sie Eigenschaften in Elemente umwandeln müssen, haben Sie zwei Möglichkeiten. Mit msbuild 2 können Sie die Funktion CreateItem tarea

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

und mit MSBuild 3.5 können Sie ItemGroups innerhalb eines Tasks haben

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X