Как удалить несколько файлов с помощью проекта msbuild/web deployment?

У меня есть странная проблема с тем, как msbuild ведет себя с проектом развертывания веб-сайтов VS2008 и хотел бы знать, почему это кажется случайным образом неправильным.

Мне нужно удалить несколько файлов из папки развертывания, которая должна существовать только в моей среде разработки. Файлы были созданы веб-приложением во время dev/testing и не включены в проект/решение Visual Studio.

Конфигурация, которую я использую, выглядит следующим образом:

<!--  Partial extract from Microsoft Visual Studio 2008 Web Deployment Project -->
<ItemGroup>
  <DeleteAfterBuild Include="$(OutputPath)data\errors\*.xml" /> <!-- Folder 1: 36 files -->
  <DeleteAfterBuild Include="$(OutputPath)data\logos\*.*" />    <!-- Folder 2: 2 files -->
  <DeleteAfterBuild Include="$(OutputPath)banners\*.*" />       <!-- Folder 3: 1 file -->
</ItemGroup>

<Target Name="AfterBuild">
  <Message Text="------ AfterBuild process starting ------" Importance="high" />
    <Delete Files="@(DeleteAfterBuild)">
      <Output TaskParameter="DeletedFiles" PropertyName="deleted" />
    </Delete>
    <Message Text="DELETED FILES: $(deleted)" Importance="high" />
  <Message Text="------ AfterBuild process complete ------" Importance="high" />
</Target>

Проблема заключается в том, что когда я делаю сборку/восстановление проекта веб-развертывания, он "иногда" удаляет все файлы, но в других случаях он ничего не удалит! Или он удалит только одну или две из трех папок в группе элементов DeleteAfterBuild. Кажется, что нет последовательности в том, когда процесс сборки решает удалить файлы или нет.

Когда я отредактировал конфигурацию, чтобы включить только папку 1 (например), она правильно удалит все файлы. Затем добавляя папки 2 и 3, он начинает удалять все файлы по мере необходимости. Затем, казалось бы, в случайные моменты, я перестрою проект, и он не удалит ни один из файлов!

Я попытался переместить эти элементы в группу элементов ExcludeFromBuild (вероятно, там, где она должна быть), но она дает мне тот же непредсказуемый результат.

Кто-нибудь испытал это? Я делаю что-то неправильно? Почему это происходит?

Ответ 1

<ItemGroup> оценивается при загрузке script и до <Target>.

Кажется, что есть несколько способов сделать это правильно -

  • Включите <ItemGroup> внутри <Target>, и он должен быть оценен в нужное время. Это будет работать с MS-Build v3.5 +

  • Используйте <CreateItem> для создания списка элементов

Пример построения script для этого -

<!-- Using ItemGroup -->
<Target Name="AfterBuild">
  <ItemGroup>
    <DeleteAfterBuild Include="$(OutputPath)data\errors\*.xml" />
  </ItemGroup>
  <Delete Files="@(DeleteAfterBuild)" />
</Target>

<!-- Using CreateItem -->
<Target Name="AfterBuild">
  <CreateItem Include="$(OutputPath)data\errors\*.xml">
    <Output TaskParameter="Include" ItemName="DeleteAfterBuild"/>
  </CreateItem>
  <Delete Files="@(DeleteAfterBuild)" />
</Target>

Чтобы объяснить, почему процесс удаления генерировал "непредсказуемые" результаты -

  • Начните с пути вывода чистой сборки
  • Build # 1 - создайте проект развертывания веб-сайтов. @(DeleteAfterBuild) будет оценивать без файлов, поскольку файлы не существуют в папке $(OutputPath) и не будут удалять какие-либо файлы как часть AfterBuild target
  • Build # 2 - создайте проект развертывания веб-сайтов. @(DeleteAfterBuild) будет оценивать все ожидаемые файлы в папке $(OutputPath) и удалит файлы как часть AfterBuild target
  • В принципе, мы вернемся к стадии 2. Повторите. Полученные результаты предсказуемы - больше не царапайте голову.

Справочный материал: Как создать группы элементов на лету, Отложенная оценка элементов в файле MSBUILD

Ответ 2

Проверьте запись в блоге, которую я только что разместил MSBuild: оценка предметов и свойств, я думаю, это может вам помочь. Дайте мне знать, если нет.

Сказал Ибрагим Хашими

Ответ 3

Я понимаю, что это уже ответили, но я думал, что добавлю свои 5 центов. Для проекта веб-развертывания нет необходимости использовать предоставленные цели, просто добавьте группу элементов, содержащую элементы ExcludeFromBuild. Я предоставил соответствующий раздел из нижней части моего файла проекта развертывания для справки.

  <Import Project="$(MSBuildExtensionsPath)\Microsoft\WebDeployment\v9.0\Microsoft.WebDeployment.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.WebDeployment.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="BeforeMerge">
  </Target>
  <Target Name="AfterMerge">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
  <ItemGroup>
    <ExcludeFromBuild Include="$(SourceWebPhysicalPath)\obj\**\*.*" />
    <ExcludeFromBuild Include="$(SourceWebPhysicalPath)\Properties\**\*.*" />
    <ExcludeFromBuild Include="$(SourceWebPhysicalPath)\**\*.csproj*" />
    <ExcludeFromBuild Include="$(SourceWebPhysicalPath)\**\*.resx" />
    <ExcludeFromBuild Include="$(SourceWebPhysicalPath)\**\*.Publish.xml" />
    <ExcludeFromBuild Include="$(SourceWebPhysicalPath)\LocalTestRun.testrunconfig" />
    <ExcludeFromBuild Include="$(SourceWebPhysicalPath)\TestResults\**\*.*" />
  </ItemGroup>