我编写了一个MSBuild项目文件,试图并行构建我的VS2010解决方案的所有配置:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<ItemGroup>
<BuildFile Include="$(SourceRoot)MyProject.sln" />
<Config Include="Debug">
<Configuration>Debug</Configuration>
</Config>
<Config Include="Release">
<Configuration>Release</Configuration>
</Config>
</ItemGroup>
<Target Name="BuildAll" Outputs="%(Config.Configuration)">
<Message Text="Start building for configuration: %(Config.Configuration)" />
<MSBuild Projects="@(BuildFile)"
Properties="Configuration=%(Config.Configuration)"
Targets="Build" />
</Target>
</Project>
我用:
启动msbuildmsbuild /m /p:BuildInParallel=true /t:BuildAll buildall.proj
问题是我的解决方案有很多.Net项目都有相同的输出文件夹。这些项目也使用相同的外部程序集。
通常,会同时生成两个输出可执行文件,并同时复制它们的依赖项。这会导致错误:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(3001,9):
error MSB3021:
Unable to copy file "xxx\NLog.dll" to "D:\src\Blackbird\shared\bin\debug\NLog.xml". The process
cannot access the file 'xxx\NLog.dll because it is being used by another process.
我认为这意味着:“2个不同的项目使用NLog并尝试同时在输出文件夹中复制其程序集”...
有没有办法解决这个问题?我真的想避免修改解决方案中的所有项目。
查看任务源代码“C:\ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ Microsoft.Common.targets(3001,9)”,我看到有可能让msbuild重试副本:
<Copy
SourceFiles="@(ReferenceCopyLocalPaths)"
DestinationFiles="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')"
SkipUnchangedFiles="$(SkipCopyUnchangedFiles)"
OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)"
Retries="$(CopyRetryCount)"
RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"
UseHardlinksIfPossible="$(CreateHardLinksForCopyLocalIfPossible)"
Condition="'$(UseCommonOutputDirectory)' != 'true'"
>
我尝试设置变量CopyRetryCount,CopyRetryDelayMilliseconds,...我希望如果复制失败,几毫秒后完成另一个副本就会成功。但我一直无法设置这些参数。我怎样才能改变它们?
还有其他解决方案吗?
答案 0 :(得分:3)
我找到了解决方案
<MSBuild Projects="@(BuildFile)"
Properties="Configuration=%(Config.Configuration);Retries=10;RetryDelayMilliseconds=50"
Targets="Build" />
它按预期工作,但现在它会在重试副本之前生成警告
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(3001,9):
warning MSB3026: Could not copy
"D:\src\xxx\System.Data.SQLite.pdb" to "..\Debug\System.Data.SQLite.pdb".
Beginning retry 1 in 50ms. The process cannot access the file
'..\Debug\System.Data.SQLite.pdb' because it is being used by another process.
在我上次测试期间,它产生了36次此警告!有没有办法抑制警告MSB0326?
答案 1 :(得分:0)
通常,在构建期间运行的任何内容都不得对其输入获取独占锁定 - 仅限共享读取锁定。看来构建过程中的某些东西(可能是NLog,无论是什么)都违反了这一点 - 它对输入"xxx\NLog.dll"
进行了独占锁定,因此当另一个msbuild节点尝试复制相同的输入时,它会失败。
对于您所遇到的特定症状,重试是一种合理的解决方法 - 尽管不能保证始终能够成功。
答案 2 :(得分:0)
我遇到了同样的问题。我需要在我的AntiVirus中添加适当的异常,以避免产生MsBuild生成的DLL。