MSBuild: звездочки и странное ItemGroup Исключить поведение

У меня есть скрипт, который пытается построить ItemGroup из всех файлов в определенном каталоге, исключая файлы с определенными именами (независимо от расширения).

Список исключаемых файлов изначально содержит расширения файлов, и я использую задачи сообщества. RegexReplace заменить расширения на звездочку. Затем я использую этот список в элементе Exclude приписывать. По некоторым причинам файлы не исключаются должным образом, даже если список выглядит правильным.

Чтобы попытаться найти причину, я создал тестовый скрипт (ниже), который имеет две задачи: первая инициализирует два свойства со списком шаблонов файлов двумя различными способами. Вторая задача печатает как свойства, так и файлы, полученные в результате использования обоих этих свойств в Exclude приписывать.

Значения свойств кажутся идентичными, однако результирующие группы отличаются. Как это возможно?

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

Вывод (немного переформатирован для ясности):

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

Обратите внимание, что оба ExcludeFilesA а также ExcludeFilesB выглядят одинаково, но получающиеся группы RemainingFilesA а также RemainingFilesB отличаются.

В конечном итоге я хочу получить список RemainingFilesA используя шаблон, сгенерированный таким же образом ExcludeFilesB генерируется. Можете ли вы предложить способ, или я должен полностью переосмыслить свой подход?

2 ответа

Решение

Истинная причина этого была обнаружена случайно, когда пользовательская задача вызвала исключение.

Фактическая стоимость ExcludeFilesA является TestDir\SampleProj.*;TestDir\SampleLib1.* как и следовало ожидать. Однако фактическая стоимость ExcludeFilesB является TestDir\SampleProj.%2a;TestDir\SampleLib1.%2a,

предположительно Message освобождает строку перед ее использованием, но Include а также Exclude не делайте. Это объясняет, почему строки выглядят одинаково, но ведут себя по-разному.

Между прочим, порядок выполнения, похоже, не имеет к этому никакого отношения, и я почти уверен (после долгих экспериментов), что все выполняется и оценивается точно в том порядке, в котором оно появляется в этом сценарии.

ItemGroups должны быть оценены до выполнения целей, а PatternedFilenames ItemGroup создается на лету в своем целевом контейнере. Вы можете обойти это, используя задачу CreateItem, которая обеспечит PatternedFilenames Область применения на протяжении всего исполнения:

<RegexReplace Input="@(OriginalFilenames)" Expression="\.\w+$" Replacement=".*">
  <Output TaskParameter="Output" ItemName="PatternedFilenames_tmp"/>
</RegexReplace>
<CreateItem Include="@(PatternedFilenames_tmp)">
  <Output TaskParameter="Include" ItemName="PatternedFilenames"/>
</CreateItem>
Другие вопросы по тегам