MSBuild& TeamBuild - BuildInParallel因MSB3021文件权限违规而失败

时间:2009-04-01 23:33:17

标签: msbuild team-build

我维护了一个相当大的软件,包含大约350个csharp项目。调试内置时钟的构建时间约为17分钟。

我一直在寻找改善构建时间的方法,而BuildInParallel属性确实看起来很吸引人。特别是因为我们有一个四核服务器来完成我们的构建,它应该能够充分利用计算能力。

但是唉...在设置属性,修改构建代理的配置文件并重新启动它之后,第一次运行确实看起来很有希望,比正常情况更快,直到它失败的程度。

在查看构建日志之后,当它尝试将标记为CopyLocal = true的引用复制到输出目录时,看起来构建失败。 如果C#项目A和C#项目B并行构建,并且两者都引用相同的第三方dll,并尝试同时复制它,则尝试复制文件的第二个进程将获得文件访问冲突 - 该文件正由另一个进程使用。

任何人都经历过这种情况,并且能够在Team Build上获得多进程构建吗?


这是其中一个失败,很难找出同时建造的其他项目。

我删除了所有不相关的内容:

  

54>在文件中定位“_CopyFilesMarkedCopyLocal”   “C:\ WINDOWS \ Microsoft.NET \框架\ v3.5版本\ Microsoft.Common.targets”   来自项目   “d:\ TEMP \ PCM \ 1.3 Maint_CI的\ Sources \模块\核心\测试\单元测试\ 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 \二进制\调试\ Oracle.DataAccess.dll”。        命令:        copy / y“.......... \ Bin \ 3rdParty \ Oracle \ Oracle.DataAccess.dll”   “d:\ TEMP \ PCM \ 1.3 Maint_CI \二进制\调试\ Oracle.DataAccess.dll”   54以及c:\ Windows \ Microsoft.NET \框架\ v3.5版本\ Microsoft.Common.targets(2703,9):   错误MSB3021:无法复制文件   “.......... \ Bin \ 3rdParty \ Oracle \ Oracle.DataAccess.dll”来   “d:\ TEMP \ PCM \ 1.3 Maint_CI \二进制\调试\ Oracle.DataAccess.dll”。该   进程无法访问该文件   'd:\ TEMP \ PCM \ 1.3 Maint_CI \二进制\调试\ Oracle.DataAccess.dll'   因为它正被另一个进程使用。       完成执行任务“复制” - 失败。 54>在项目中完成构建目标“_CopyFilesMarkedCopyLocal”   “TestDIPS.Core.Data.Server.NUnit.csproj” - FAILED。

6 个答案:

答案 0 :(得分:15)

MSBuild附带的默认目标是为CopyLocal行为设计的 - 这是VS所依赖的。当您输出到单个输出目录时,CopyLocal会出现问题。

为了能够真正并行构建,您需要在Microsoft。*。Common。*。targets文件中禁用多个CopyLocal特定行为。我过去曾和MSBuild团队的一些人谈过,这是一个特别毛茸茸的事情。即使你没有删除一些CopyLocal行为,VS测试访问器在并行构建时表现也不好。

您可以开始的一些事情:

  1. 通过将private设置为true来禁用引用的CopyLocal行为。
  2. 在构建依赖项目时,为CopyToOutputPath文件禁用CopyLocal。

答案 1 :(得分:9)

几个月前我遇到了同样的问题。

VS C#项目文件(.csproj文件)中有两种类型的文件复制:

  1. 具有“复制本地”属性的引用程序集。当属性为True时,程序集将复制到输出路径中。

  2. 具有“复制到输出目录”属性的其他文件。当属性设置为“始终复制”或“复制如果更新”时,文件将复制到输出路径中。

  3. 问题:

    答:如果同时构建了两个或多个项目,并且其中两个尝试将同一文件复制到输出目录中,则可能会遇到“错误MSB3021:无法复制文件”,“访问路径”等错误被拒绝“,”进程无法访问文件“等等。

    B:如果两个或多个项目引用了一个具有类型2的项目的公共项目。在这种情况下,在项目的并行构建期间,其中两个可能会尝试同时构建公共项目的“GetCopyToOutputDirectoryItems”目标。所以你可能再次遇到上述例外情况。

    解决方法1:

    强制不同的.csproj文件的OutputPath不在同一路径

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

    溶液2:

    步骤1:解决方案是为项目中的所有常见项目之外的所有项目设置公共项目的属性(在案例1中为False,在案例2中为“不复制”)。或者删除它们如果可能的话。

    为了发现潜在的错误,您可以在文件中搜索单词“private”(对于案例1)和“CopyToOutputDirectory”(对于案例2)* .csproj

    第2步:......

    祝你好运

答案 2 :(得分:9)

MS Build Copy任务有未记录的功能,至少谷歌保持沉默。 如果设置系统范围的环境变量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.

答案 3 :(得分:1)

看起来您的项目配置为相同的输出目录。如果将项目A和项目B配置为输出到不同的目录,则可以解决此错误。

答案 4 :(得分:1)

由于文件是只读文件,也可能发生这种情况。在这些情况下(即,不是大部分其他答案涵盖的那些),there are appropriate workarounds which vary depending on whether you're able to rely on MSBuild 3.5 or later

答案 5 :(得分:0)

您使用的是哪种编译器?据我所知,直到VS2005并行构建不适用于多个项目。这是一个已知的问题,MS一直说他们最终会解决,但我不知道他们是否真的在VS2008中解决了它。