MSBuild & TeamBuild - сбой BuildInParallel из-за нарушения прав доступа к файлу MSB3021 - PullRequest
27 голосов
/ 02 апреля 2009

Я поддерживаю сборку довольно большого программного обеспечения, состоящего примерно из 350 проектов csharp. Наше время сборки для отладки составило около 17 минут.

Я искал способы улучшить время сборки, и свойство BuildInParallel выглядело интригующим. Тем более, что у нас есть четырехъядерный сервер, выполняющий наши сборки, он действительно должен иметь возможность использовать преимущества вычислительной мощности.

Но, увы ... После установки свойства, изменения файла конфигурации для агента сборки и его перезапуска первый запуск действительно выглядел многообещающе, намного быстрее, чем обычно, вплоть до момента, когда он не удался.

После просмотра журналов сборки, похоже, что сборка завершается неудачно, когда она пытается скопировать ссылки, помеченные как CopyLocal = true, в выходной каталог. Если C # проект A и C # проект B построены параллельно, и оба ссылаются на один и тот же сторонний dll и одновременно пытаются скопировать его, второй процесс, пытающийся скопировать файл, получит нарушение доступа к файлу - файл используется другим процессом.

Кто-нибудь сталкивался с этим и смог получить многопроцессные сборки, работающие на Team Build?


Вот один из сбоев, довольно сложно понять, какой другой проект строился в то же время.

Я удалил все несущественные вещи:

54> Цель "_CopyFilesMarkedCopyLocal" в файле "C: \ WINDOWS \ Microsoft.NET \ Framework \ v3.5 \ Microsoft.Common.targets" из проекта "D: \ Temp \ PCM \ 1.3-Maint_CI \ Sources \ модули \ Ядро \ Test \ UnitTest \ TestDIPS.Core.Data.Server.NUnit \ TestDIPS.Core.Data.Server.NUnit.csproj": 54> Задание «Копировать» Копирование файла из ".......... \ Bin \ 3rdParty \ Oracle \ Oracle.DataAccess.dll" в "D: \ Temp \ PCM \ 1.3-Maint_CI \ Бинарники \ Debug \ Oracle.DataAccess.dll". Команда: copy / y ".......... \ Bin \ 3rdParty \ Oracle \ Oracle.DataAccess.dll" "D: \ Temp \ PCM \ 1.3-Maint_CI \ Бинарники \ Debug \ Oracle.DataAccess.dll" 54> C: \ WINDOWS \ Microsoft.NET \ Framework \ v3.5 \ Microsoft.Common.targets (2703,9): ошибка MSB3021: невозможно скопировать файл ".......... \ Bin \ 3rdParty \ Oracle \ Oracle.DataAccess.dll" для "D: \ Temp \ PCM \ 1.3-Maint_CI \ Бинарники \ Debug \ Oracle.DataAccess.dll". процесс не может получить доступ к файлу 'D: \ Temp \ PCM \ 1,3-Maint_CI \ Binaries \ Debug \ Oracle.DataAccess.dll' потому что он используется другим процессом. Выполнено выполнение задания «Копировать» - СБОЙ. 54> Закончено создание цели "_CopyFilesMarkedCopyLocal" в проекте "TestDIPS.Core.Data.Server.NUnit.csproj" - СБОЙ.

Ответы [ 6 ]

15 голосов
/ 30 апреля 2009

Цели по умолчанию, которые поставляются с MSBuild, разработаны для поведения CopyLocal - именно на это опирается VS. CopyLocal создает проблемы при выводе в один выходной каталог.

Чтобы иметь возможность действительно строить параллельно, вам нужно отключить несколько специфических для CopyLocal вариантов поведения в файлах целей Microsoft. *. Common. *. Я говорил с некоторыми людьми в команде MSBuild в прошлом, и это особенно сложная вещь. Даже если вы отключите некоторые свойства CopyLocal, средства доступа к тестам VS не будут хорошо работать при параллельной сборке.

Некоторые вещи, с которых вы можете начать:

  1. Отключить поведение CopyLocal для ссылок, установив для private значение true.
  2. Отключить CopyLocal для файлов CopyToOutputPath при построении зависимых проектов.
9 голосов
/ 23 марта 2013

Задача MS Build Copy имеет недокументированную функцию, по крайней мере, Google хранит молчание. Если задана общесистемная переменная среды MSBUILDALWAYSRETRY = 1 Эта задача будет повторять попытку копирования файла, даже если во время операции копирования возникнет исключение «Отказ в доступе»

Пример вывода

C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets (3513): Got System.UnauthorizedAccessException: Access to the path 'C:\Builds\8\28\Binaries\Release\fr\System.Spatial.resources.dll' is denied.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.File.InternalCopy(String sourceFileName, String destFileName, Boolean overwrite, Boolean checkHost)
   at System.IO.File.Copy(String sourceFileName, String destFileName, Boolean overwrite)
   at Microsoft.Build.Tasks.Copy.CopyFileWithLogging(FileState sourceFileState, FileState destinationFileState)
   at Microsoft.Build.Tasks.Copy.DoCopyWithRetries(FileState sourceFileState, FileState destinationFileState, CopyFileWithState copyFile) copying C:\Builds\8\28\Sources\Main\Solutions\packages\System.Spatial.5.2.0\lib
et40\fr\System.Spatial.resources.dll to C:\Builds\8\28\Binaries\Release\fr\System.Spatial.resources.dll and HR is -2147024891
 C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets (3513): Retrying on ERROR_ACCESS_DENIED because MSBUILDALWAYSRETRY = 1
 C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets (3513): Could not copy "C:\Builds\8\28\Sources\Main\Solutions\packages\System.Spatial.5.2.0\lib
et40\fr\System.Spatial.resources.dll" to "C:\Builds\8\28\Binaries\Release\fr\System.Spatial.resources.dll". Beginning retry 1 in 1000ms. Access to the path 'C:\Builds\8\28\Binaries\Release\fr\System.Spatial.resources.dll' is denied.
9 голосов
/ 23 ноября 2009

У меня та же проблема много месяцев назад.

Существует два типа копирования файлов в файлах проекта VS C # (файлы .csproj):

  1. Ссылочные сборки, имеющие свойство «Копировать локально». когда свойство имеет значение True, сборка копируется в выходной путь.

  2. Дополнительные файлы, которые имеют свойство «Копировать в выходной каталог». если для свойства установлено значение «всегда копировать» или «копировать, если новее», файл копируется в выходной путь.

Проблема:

A: Если два или более проектов создаются одновременно и два из них пытаются скопировать один и тот же файл в выходной каталог, вы можете столкнуться с ошибками, такими как «ошибка MSB3021: невозможно скопировать файл», «Доступ к пути запрещено »,« Процесс не может получить доступ к файлу »и т. д.

B: Если два или более проектов ссылаются на общий проект, который имеет несколько элементов типа 2. В этом случае во время параллельной сборки проектов два из них могут попытаться создать цель «GetCopyToOutputDirectoryItems» для общего проекта одновременно , Так что вы можете снова столкнуться с вышеуказанными исключениями.

Solution1:

заставляет OutputPath различных файлов .csproj не находиться по одному и тому же пути

http://social.msdn.microsoft.com/Forums/is/tfsbuild/thread/a62a6f98-ec44-46c1-a0d0-7f441f0db973

solution2:

Шаг 1. Решение состоит в том, чтобы установить свойство общих элементов (False в случае 1 и «не копировать» в случае 2) для всех, кроме одного из этих общих элементов в ваших проектах. или удалите их, если это возможно.

Чтобы найти потенциальные ошибки, вы можете искать слова «private» (для случая 1) и «CopyToOutputDirectory» (для случая 2) в файлах * .csproj

Step2: ...

Удачи

1 голос
/ 24 ноября 2009

Это также может произойти из-за того, что файл доступен только для чтения. В этих случаях (т. Е. Не охваченных большинством других ответов), существуют подходящие обходные пути, которые варьируются в зависимости от того, можете ли вы полагаться на MSBuild 3.5 или более позднюю версию .

1 голос
/ 23 апреля 2009

Похоже, что ваши проекты настроены на один и тот же выходной каталог. Если вы сконфигурируете Project A и Project B для вывода в разные каталоги, это устранит эту ошибку.

0 голосов
/ 23 апреля 2009

Какой компилятор вы используете? Насколько я знаю, до VS2005 параллельная сборка не работала для нескольких проектов. Это известная проблема, которую MS продолжает говорить, что они в конечном итоге исправят, но я не знаю, действительно ли они решили ее в VS2008.

...