【问题标题】:MSBuild & TeamBuild - BuildInParallel failing because of MSB3021 file permission violationMSBuild 和 TeamBuild - 由于 MSB3021 文件权限违规,BuildInParallel 失败
【发布时间】:2010-10-17 00:04:52
【问题描述】:

我维护了一个相当大的软件的构建,其中包含大约 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\Modules\Core\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\Binaries\Debug\Oracle.DataAccess.dll”。 命令: 复制 /y "........\Bin\3rdParty\Oracle\Oracle.DataAccess.dll" “d:\temp\PCM\1.3-Maint_CI\Binaries\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\Binaries\Debug\Oracle.DataAccess.dll”。这 进程无法访问文件 'd:\temp\PCM\1.3-Maint_CI\Binaries\Debug\Oracle.DataAccess.dll' 因为它正在被另一个进程使用。 完成执行任务“复制”——失败。 54>在项目中完成构建目标“_CopyFilesMarkedCopyLocal” "TestDIPS.Core.Data.Server.NUnit.csproj" -- 失败。

【问题讨论】:

    标签: msbuild tfsbuild


    【解决方案1】:

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

    【讨论】:

    • 我们完全使用 TFS2008,包括客户端和构建服务器
    【解决方案2】:

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

    【讨论】:

    • 是的,但这是 TeamBuild 的默认行为,如果没有其他方法可以解决,我不想更改它。
    【解决方案3】:

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

    为了能够真正并行构建,您需要在 Microsoft.*.Common.*.targets 文件中禁用多个 CopyLocal 特定行为。我过去曾与 MSBuild 团队中的一些人交谈过,这是一件特别麻烦的事情。即使您将 CopyLocal 的某些行为置空,VS 测试访问器在并行构建时也表现不佳。

    你可以从以下几点开始:

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

    【讨论】:

    • 很抱歉回复晚了,但非常感谢您的澄清回答。您的回答与我的最新发现一致,我在测试访问器方面遇到了问题。我发现我将不得不取消测试访问器或修改目标文件,这是我们不想做的事情。希望这将在 Team Build 2010 / .Net 4.0 中得到修复
    【解决方案4】:

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

    VS C#项目文件(.csproj文件)中有两种文件拷贝:

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

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

    问题:

    A:如果同时构建两个或多个项目,并且其中两个尝试将同一个文件复制到输出目录中,您可能会遇到诸如“错误 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 中设置为“不复制”)。或删除它们(如果可能)。

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

    第二步:……

    祝你好运

    【讨论】:

      【解决方案5】:

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

      【讨论】:

      • 虽然理论上可以回答这个问题,it would be preferable 在这里包含答案的基本部分,并提供链接以供参考。如果您添加相关详细信息,请标记它以引起版主注意,我现在将其删除。
      【解决方案6】:

      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.
      

      【讨论】:

      • 链接失效
      猜你喜欢
      • 1970-01-01
      • 2023-03-21
      • 2016-02-16
      • 2016-12-14
      • 1970-01-01
      • 2019-07-26
      • 1970-01-01
      • 2018-05-20
      • 1970-01-01
      相关资源
      最近更新 更多