103 votes

Copier tous les fichiers et dossiers en utilisant msbuild

Je me demande si quelqu'un pourrait m'aider avec quelques scripts de msbuild que j'essaie d'écrire. Ce que je voudrais faire est de copier tous les fichiers et sous-dossiers d'un dossier à un autre dossier en utilisant msbuild.

{ProjectName}
      |----->Source
      |----->Tools
              |----->Viewer
                       |-----{about 5 sub dirs}

Ce que je dois pouvoir faire, c'est copier tous les fichiers et sous-dossiers du dossier tools dans le dossier debug de l'application. Voici le code que j'ai jusqu'à présent.

<ItemGroup>
    <Viewer Include="..\$(ApplicationDirectory)\Tools\viewer\**\*.*" />
</ItemGroup>

<Target Name="BeforeBuild">
    <Copy SourceFiles="@(Viewer)" DestinationFolder="@(Viewer->'$(OutputPath)\\Tools')" />
</Target>

Le build script s'exécute mais ne copie aucun des fichiers ou dossiers.

Merci

151voto

regex Points 316

Je cherchais aussi de l'aide à ce sujet. Cela m'a pris un certain temps, mais voici ce que j'ai fait et qui a très bien fonctionné.

<Target Name="AfterBuild">
    <ItemGroup>
        <ANTLR Include="..\Data\antlrcs\**\*.*" />
    </ItemGroup>
    <Copy SourceFiles="@(ANTLR)" DestinationFolder="$(TargetDir)\%(RecursiveDir)" SkipUnchangedFiles="true" />
</Target>

Ceci a copié récursivement le contenu du dossier nommé antlrcs à la $(TargetDir) .

4 votes

Oui, c'est la meilleure réponse. La même que celle recommandée ici sur le blog msdn : blogs.msdn.com/b/msbuild/archive/2005/11/07/490068.aspx

21 votes

L'astuce semble être d'ajouter %(RecursiveDir) dans le dossier de destination recréera la structure du répertoire. Sinon, la sortie est plate. Ceci est la meilleure réponse.

1 votes

Il faut les mettre à la fond du fichier .fsproj, ou il ne prend pas.

73voto

brock.holum Points 1745

Je pense que le problème vient de la façon dont vous créez votre ItemGroup et dont vous appelez la tâche de copie. Voyez si cela a un sens :

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
    <PropertyGroup>
        <YourDestinationDirectory>..\SomeDestinationDirectory</YourDestinationDirectory>
        <YourSourceDirectory>..\SomeSourceDirectory</YourSourceDirectory>
    </PropertyGroup>

    <Target Name="BeforeBuild">
        <CreateItem Include="$(YourSourceDirectory)\**\*.*">
            <Output TaskParameter="Include" ItemName="YourFilesToCopy" />
        </CreateItem>

        <Copy SourceFiles="@(YourFilesToCopy)"
                DestinationFiles="@(YourFilesToCopy->'$(YourDestinationDirectory)\%(RecursiveDir)%(Filename)%(Extension)')" />
    </Target>
</Project>

0 votes

CreateItem La tâche est dépréciée. regex est l'alternative. msdn.microsoft.com/fr/us/library/s2y3e43x.aspx

36voto

zXen Points 241

Je suis un peu nouveau dans MSBuild mais je trouve la tâche EXEC pratique pour des situations comme celles-ci. J'ai rencontré le même problème dans mon projet et ceci a fonctionné pour moi et était beaucoup plus simple. Quelqu'un peut me dire si ce n'est pas une bonne pratique.

<Target Name="CopyToDeployFolder" DependsOnTargets="CompileWebSite">
    <Exec Command="xcopy.exe  $(OutputDirectory) $(DeploymentDirectory) /e" WorkingDirectory="C:\Windows\" />
</Target>

9 votes

J'ose poser la question dans l'autre sens. Y a-t-il une raison de ne jamais utiliser la tâche de copie de msbuild qui remplit le journal ?

4 votes

Potentiellement. Si vous avez une ferme de construction (Jenkins, TeamCity, etc.), le service d'agent peut être exécuté sous un compte différent qui n'a pas xcopy dans le chemin. Vous pouvez essayer des choses comme %windir%. \system32 dans le chemin, mais même cela ne fonctionne pas toujours.

0 votes

C'est la solution qui a fonctionné pour moi. De plus, je n'ai pas eu besoin de définir le WorkingDirectory.

14voto

amit thakur Points 61
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
    <PropertyGroup>
        <YourDestinationDirectory>..\SomeDestinationDirectory</YourDestinationDirectory>
        <YourSourceDirectory>..\SomeSourceDirectory</YourSourceDirectory>
    </PropertyGroup>

    <Target Name="BeforeBuild">
        <CreateItem Include="$(YourSourceDirectory)\**\*.*">
            <Output TaskParameter="Include" ItemName="YourFilesToCopy" />
        </CreateItem>

        <Copy SourceFiles="@(YourFilesToCopy)"
                DestinationFiles="$(YourFilesToCopy)\%(RecursiveDir)" />
    </Target>
</Project>

\**\*.* aide à récupérer les fichiers de tous les dossiers. RecursiveDir aide à placer tous les fichiers dans le dossier respectif...

2 votes

Les fichiers de destination font référence à 1 élément et les fichiers de source font référence à 33 éléments. Ils doivent avoir le même nombre d'éléments. Ugh msbuild peut être génial, mais c'est un tel morceau de ferraille mal documenté parfois.

0 votes

CreateItem La tâche est dépréciée. regex est l'alternative. msdn.microsoft.com/fr/us/library/s2y3e43x.aspx

4voto

aku Points 54867

Avez-vous essayé de spécifier un répertoire de destination concret au lieu de

DestinationFolder="@(Viewer->'$(OutputPath)\\Tools')" ? 

Je ne suis pas très compétent avec la syntaxe avancée de MSBuild, mais

@(Viewer->'$(OutputPath)\\Tools') 

ça me semble bizarre. script semble bon, donc le problème pourrait être dans les valeurs de $(ApplicationDirectory) et $(OutputPath)

Voici un article de blog qui pourrait vous être utile :

Comment faire : copier récursivement des fichiers en utilisant la tâche <Copy>.

1 votes

+1 pour le lien, qui est plus concis que la réponse acceptée de zXen.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X