web-dev-qa-db-fra.com

Comment puis-je faire en sorte que MSBUILD évalue et imprime le chemin complet quand on lui donne un chemin relatif?

Comment puis-je demander à MSBuild d'évaluer et d'imprimer dans un <Message /> charger un chemin absolu avec un chemin relatif?

Groupe de propriétés

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

tâche

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

Sortie

Copie de '' vers 'c:\Program Files (x86)\Program \'

55
Eric Schoonover

Dans MSBuild 4.0 , le moyen le plus simple est le suivant:

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

Cette méthode fonctionne même si le script est <Import>ed dans un autre script; le chemin est relatif au fichier contenant le code ci-dessus.

(consolidé de réponse d'Aaron ainsi que la dernière partie de réponse de Sayed )


Dans MSBuild 3.5 , vous pouvez utiliser la tâche 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>

Sortie 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 peu long si vous me demandez, mais ça marche. Ce sera relatif au fichier de projet "d'origine", donc s'il est placé dans un fichier qui obtient <Import>ed, cela ne sera pas relatif à ce fichier.


Dans MSBuild 2.0 , il existe une approche qui ne résout pas "..". Il se comporte cependant comme un chemin absolu:

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

La propriété réservée $ (MSBuildProjectDirectory) est toujours le répertoire du script qui contient cette référence.

Ce sera également relatif au fichier de projet "d'origine", donc s'il est placé dans un fichier qui obtient <Import>ed, cela ne sera pas relatif à ce fichier.

93
Roman Starkov

MSBuild 4.0 a ajouté Fonctions de propriété qui vous permettent d'appeler des fonctions statiques dans certaines des DLL du système .net. Une très bonne chose à propos des fonctions de propriété est qu'elles évalueront en dehors d'une cible.

Pour évaluer un chemin complet, vous pouvez utiliser System.IO.Path.GetFullPath lors de la définition d'une propriété comme ceci:

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

La syntaxe est un peu moche mais très puissante.

31
Aaron Carlson

Wayne a raison de dire que les métadonnées bien connues ne s'appliquent pas aux propriétés - uniquement aux éléments. L'utilisation de propriétés telles que "MSBuildProjectDirectory" fonctionnera, mais je ne connais pas de méthode intégrée pour résoudre le chemin d'accès complet.

Une autre option consiste à écrire une tâche simple et personnalisée qui prendra un chemin relatif et crachera le chemin entièrement résolu. Cela ressemblerait à quelque chose comme ceci:

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

Et vos lignes MSBuild ressembleraient à quelque chose comme:

<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
brock.holum

Vous essayez d'accéder à une propriété de métadonnées d'élément via une propriété, ce qui n'est pas possible. Ce que vous voulez faire, c'est quelque chose comme ceci:

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

Qui générera une sortie comme:

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

(Le script a été exécuté à partir de mon dossier Documents, donc ..\Desktop est le chemin relatif correct pour accéder à mon bureau.)

Dans votre cas, remplacez le "..\Desktop" par "......\Public\Server" dans l'élément Source_Dir et vous devriez être prêt.

5
Scott Dorman

Si vous devez convertir des propriétés en éléments, vous avez deux options. Avec msbuild 2, vous pouvez utiliser la tâche CreateItem

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

et avec MSBuild 3.5, vous pouvez avoir des groupes d’éléments dans une tâche

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