2009-12-19 5 views
3

J'ai un script qui tente de construire un ItemGroup sur tous les fichiers d'un répertoire donné tout en excluant les fichiers avec certains noms (indépendamment de l'extension).MSBuild: astérisques et étrange ItemGroup Comportement d'exclusion

La liste des fichiers à exclure contient initialement des extensions de fichier, et j'utilise les tâches de communauté RegexReplace pour remplacer les extensions par un astérisque. J'utilise ensuite cette liste dans l'attribut Exclude de l'élément. Pour une raison quelconque, les fichiers ne sont pas exclus correctement, même si la liste semble correcte.

Pour essayer de trouver la cause, j'ai créé un script de test (ci-dessous) qui a deux tâches: d'abord, initialiser deux propriétés avec la liste des modèles de fichiers de deux manières différentes. La deuxième tâche imprime les propriétés et les fichiers résultant de l'utilisation de ces deux propriétés dans l'attribut Exclude.

Les valeurs des propriétés semblent identiques, mais les groupes résultants sont différents. Comment est-ce possible?

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" 
     DefaultTargets="Init;Test" ToolsVersion="3.5"> 
    <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/> 

    <Target Name="Init"> 
    <ItemGroup> 
     <OriginalFilenames Include="TestDir\SampleProj.exe"/> 
     <OriginalFilenames Include="TestDir\SampleLib1.dll"/> 
    </ItemGroup> 
    <RegexReplace Input="@(OriginalFilenames)" Expression="\.\w+$" Replacement=".*"> 
     <Output TaskParameter="Output" ItemName="PatternedFilenames"/> 
    </RegexReplace> 
    <PropertyGroup> 
     <ExcludeFilesA>TestDir\SampleProj.*;TestDir\SampleLib1.*</ExcludeFilesA> 
     <ExcludeFilesB>@(PatternedFilenames)</ExcludeFilesB> 
    </PropertyGroup> 
    </Target> 

    <Target Name="Test"> 
    <Message Text='ExcludeFilesA: $(ExcludeFilesA)' /> 
    <Message Text='ExcludeFilesB: $(ExcludeFilesB)' /> 
    <ItemGroup> 
     <AllFiles Include="TestDir\**"/> 
     <RemainingFilesA Include="TestDir\**" Exclude="$(ExcludeFilesA)"/> 
     <RemainingFilesB Include="TestDir\**" Exclude="$(ExcludeFilesB)"/> 
    </ItemGroup> 
    <Message Text="&#xA;**AllFiles**&#xA;@(AllFiles, '&#xA;')" /> 
    <Message Text="&#xA;**PatternedFilenames**&#xA;@(PatternedFilenames, '&#xA;')" /> 
    <Message Text="&#xA;**RemainingFilesA**&#xA;@(RemainingFilesA, '&#xA;')" /> 
    <Message Text="&#xA;**RemainingFilesB**&#xA;@(RemainingFilesB, '&#xA;')" /> 
    </Target> 

</Project> 

sortie (reformaté un peu pour plus de clarté):

ExcludeFilesA: TestDir\SampleProj.*;TestDir\SampleLib1.* 
ExcludeFilesB: TestDir\SampleProj.*;TestDir\SampleLib1.* 

AllFiles: 
    TestDir\SampleLib1.dll 
    TestDir\SampleLib1.pdb 
    TestDir\SampleLib2.dll 
    TestDir\SampleLib2.pdb 
    TestDir\SampleProj.exe 
    TestDir\SampleProj.pdb 

PatternedFilenames: 
    TestDir\SampleProj.* 
    TestDir\SampleLib1.* 

RemainingFilesA: 
    TestDir\SampleLib2.dll 
    TestDir\SampleLib2.pdb 

RemainingFilesB: 
    TestDir\SampleLib1.dll 
    TestDir\SampleLib1.pdb 
    TestDir\SampleLib2.dll 
    TestDir\SampleLib2.pdb 
    TestDir\SampleProj.exe 
    TestDir\SampleProj.pdb 

Observez que les deux ExcludeFilesA et ExcludeFilesB semblent identiques, mais les groupes résultants RemainingFilesA et RemainingFilesB diffèrent.

Finalement, je veux obtenir la liste RemainingFilesA en utilisant le modèle généré de la même manière ExcludeFilesB est généré. Pouvez-vous suggérer un moyen, ou dois-je repenser complètement mon approche?

Répondre

2

La vraie cause de cela a été révélé par hasard quand une tâche personnalisée a lancé une exception.

La valeur réelle de ExcludeFilesA est TestDir\SampleProj.*;TestDir\SampleLib1.* comme on pourrait s'y attendre. Cependant, la valeur réelle de ExcludeFilesB est TestDir\SampleProj.%2a;TestDir\SampleLib1.%2a.

Sans doute Message désapparaît la chaîne avant de l'utiliser, mais Include et Exclude ne le font pas. Cela expliquerait pourquoi les chaînes se ressemblent mais se comportent différemment. Incidemment, l'ordre d'exécution ne semble pas avoir de rapport avec cela, et je suis sûr (suite à une expérimentation approfondie) que tout est exécuté et évalué exactement dans l'ordre dans lequel il apparaît dans ce script.

+0

Bonne prise ... gentille! – KMoraz

+0

Merci beaucoup! J'ai essayé d'échapper à l'astérisque dans une barre 'pour l'obtenir plus tard sans mot entier, et je n'ai trouvé aucune information à ce sujet. Votre recherche m'a aidé - en utilisant '% 2a' désactivé expansion et toutes les transformations' @ -> 'dans la commande ultérieure obtenu l'astérisque. – quetzalcoatl

+0

et immédiatement après avoir écrit ce commentaire, j'ai trouvé https://docs.microsoft.com/en-us/visualstudio/msbuild/special-characters-to-escape où il est explicitement indiqué pour inclure et astérisque, d'oh. – quetzalcoatl

0

ItemGroups doivent être évalués avant l'exécution des cibles et le groupe d'éléments PatternedFilenames est créé à la volée dans son conteneur cible. Vous pouvez contourner cela en utilisant la tâche CreateItem, qui assurera la portée PatternedFilenames tout au long de l'exécution:

<RegexReplace Input="@(OriginalFilenames)" Expression="\.\w+$" Replacement=".*"> 
    <Output TaskParameter="Output" ItemName="PatternedFilenames_tmp"/> 
</RegexReplace> 
<CreateItem Include="@(PatternedFilenames_tmp)"> 
    <Output TaskParameter="Include" ItemName="PatternedFilenames"/> 
</CreateItem> 
+0

Oh ... merci pour la solution de contournement, je vais essayer cela. Pourriez-vous éventuellement expliquer l'ordre dans lequel les choses se produisent plus en détail s'il vous plaît? Clairement, 'ExcludeFilesA' est initialisé avant la création de l'ItemGroup' RemainingFilesA'; comment se passe-t-il la même chose pour 'RemainingFilesB'? On dirait presque que l'ordre est: 1. "Init" se termine; 2. ItemGroups de "Test" évalué; 3. RegexReplace évalué; 4. "Test" commence et imprime les messages. Mais sûrement cela ne peut pas être ainsi? ... –

+0

Lire la section «Ordre d'évaluation des biens et des articles» ici: http://msdn.microsoft.com/en-us/library/dd997067(VS.100).aspx Ce poste est lié à votre problème: http://elegantcode.com/2006/12/11/msbuild-items-run-time-evaluation-behavior/ – KMoraz

Questions connexes