如何使 MSBuild 在 .NET 解决方案出现错误时不停止
How to make MSBuild to NOT stop on error on .NET solution
我正在根据团队的需要定制构建服务器设置。
它应该会自动构建我们的 .net 解决方案。
我尽力不更改 .sln 或项目文件中的任何内容。
这项工作的明显构建工具是 msbuild
。我已经成功地从 .sln 文件编译了我们的解决方案。
下一步是测试某些解决方案的项目被破坏时的场景。在下面的情况下,我在 devenv
和 msbuild
之间遇到了奇怪的行为差异。有 3 个项目,其中 2nd 依赖于 1st,而 3rd 是独立且损坏的。 devenv
编译第 1 次和第 2 次,第 3 次失败,如预期的那样; msbuild
第一次编译,第三次失败,而且 - 出乎意料 - 没有尝试第二次。
示例解决方案(4 个文件:Complete.sln、1.csproj、2.csproj、3.csproj)
--- 1.csproj
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>2.0</OldToolsVersion>
</PropertyGroup>
<Target Name="Build">
<Message Importance="High" Text="Project 1" />
</Target>
</Project>
--- 2.csproj
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>2.0</OldToolsVersion>
</PropertyGroup>
<Target Name="Build">
<Message Importance="High" Text="Project 2" />
</Target>
</Project>
--- 3.csproj
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>2.0</OldToolsVersion>
</PropertyGroup>
<Target Name="Build">
<Message Importance="High" Text="Project 3" />
<Error Text="Build failed" />
</Target>
</Project>
--- Complete.sln
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29709.97
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "1", "1.csproj", "{AA88BE9A-5006-4CCE-8871-A67F413DBADF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "2", "2.csproj", "{BAF51480-4B90-454A-96F5-E63A05A486EF}"
ProjectSection(ProjectDependencies) = postProject
{AA88BE9A-5006-4CCE-8871-A67F413DBADF} = {AA88BE9A-5006-4CCE-8871-A67F413DBADF}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "3", "3.csproj", "{12C30CFB-7387-4CD2-81D4-87E14209C408}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AA88BE9A-5006-4CCE-8871-A67F413DBADF}.Debug|x86.ActiveCfg = Debug|x86
{AA88BE9A-5006-4CCE-8871-A67F413DBADF}.Debug|x86.Build.0 = Debug|x86
{BAF51480-4B90-454A-96F5-E63A05A486EF}.Debug|x86.ActiveCfg = Debug|x86
{BAF51480-4B90-454A-96F5-E63A05A486EF}.Debug|x86.Build.0 = Debug|x86
{12C30CFB-7387-4CD2-81D4-87E14209C408}.Debug|x86.ActiveCfg = Debug|x86
{12C30CFB-7387-4CD2-81D4-87E14209C408}.Debug|x86.Build.0 = Debug|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {75E95C15-489D-4D3F-82CA-735FB7B88910}
EndGlobalSection
EndGlobal
"Developer Command Prompt for VS 2019" 的控制台输出如下所示:
e>devenv /Build Debug Complete.sln
Microsoft Visual Studio 2019 Version 16.4.3.
Copyright (C) Microsoft Corp. All rights reserved.
1>------ Build started: Project: 1, Configuration: Debug x86 ------
2>------ Build started: Project: 3, Configuration: Debug x86 ------
1> Project 1
2> Project 3
2>C:\temp\msbuild\TestSolution\Complete.csproj(11,2): error : Build failed
3>------ Build started: Project: 2, Configuration: Debug x86 ------
3> Project 2
========== Build: 2 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
>msbuild Complete.sln /p:Configuration=Debug /p:Platform=x86 /m
Microsoft (R) Build Engine version 16.4.0+e901037fe for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.
Build started 23.01.2020 11:10:38.
1>Project "c:\temp\msbuild\TestSolution\Complete\Complete.sln" on node 1 (default targets).
1>ValidateSolutionConfiguration:
Building solution configuration "Debug|x86".
1>Project "c:\temp\msbuild\TestSolution\Complete\Complete.sln" (1) is building "c:\temp\msbuild\TestSolution\Complete.cs
proj" (2) on node 1 (default targets).
2>Build:
Project 1
2>Done Building Project "c:\temp\msbuild\TestSolution\Complete.csproj" (default targets).
1>Project "c:\temp\msbuild\TestSolution\Complete\Complete.sln" (1) is building "c:\temp\msbuild\TestSolution\Complete.cs
proj" (3) on node 2 (default targets).
3>Build:
Project 3
3>c:\temp\msbuild\TestSolution\Complete.csproj(11,5): error : Build failed
3>Done Building Project "c:\temp\msbuild\TestSolution\Complete.csproj" (default targets) -- FAILED.
1>Done Building Project "c:\temp\msbuild\TestSolution\Complete\Complete.sln" (default targets) -- FAILED.
Build FAILED.
"c:\temp\msbuild\TestSolution\Complete\Complete.sln" (default target) (1) ->
"c:\temp\msbuild\TestSolution\Complete.csproj" (default target) (3) ->
(Build target) ->
c:\temp\msbuild\TestSolution\Complete.csproj(11,5): error : Build failed
0 Warning(s)
1 Error(s)
Time Elapsed 00:00:00.65
请注意 msbuild
输出中缺少 Project 2
消息。
是否有(非侵入式)方式让msbuild
继续编译其他项目?
到目前为止我想出的最好的办法是在 Complete.sln
(参见 msdn)向上的某个文件夹中创建一个 Directory.Solution.targets
,内容如下。
<Project>
<Target Name="SetSkip">
<ItemGroup>
<ProjectReference Update="*">
<SkipNonexistentProjects>Build</SkipNonexistentProjects>
</ProjectReference>
</ItemGroup>
</Target>
<Target Name="BuildAll" DependsOnTargets="SetSkip">
<CallTarget Targets="Build"/>
</Target>
</Project>
注意 SkipNonexistentProjects
设置为 Build
,而不是 True
。当设置为 True
时,第二个项目被 Skipping project "2.csproj.metaproj" because it was not found.
.
跳过
然后用 /t:BuildAll
而不是 /t:Build
调用 msbuild
。但是我需要为 每个可能的解决方案和 每个可能的目标执行此操作,我真的很想要一些更好的方法,也许是我还找不到的命令行开关(/p:ContinueOnError=true;StopOnFirstFailure=false;SkipNonexistentProjects=true
没有帮助)。
更新 改进了我的解决方法:现在只需要根文件夹中的一个附加文件。
How to make MSBuild to NOT stop on error on .NET solution
答案是 否 因为它看起来像是一个关于 msbuild 的问题。所以我们只能有解决方法而不是解决方案...
我可以在我的机器上用 VS2019 和 msbuild 16.0 重现同样的问题。由于使用 devenv 一切正常,我认为您可以 post 一期 here 到 Msbuild 团队。 (我尝试了几个 msbuild 属性,但它们不起作用,所以我认为这个问题)
这里有一些临时解决方法:
1.If 你在这个解决方案中没有太多项目,你可以使用 target
开关以特定顺序构建特定项目,检查 this document.
对我来说,我使用像 msbuild Library.sln -target:LibraryA;LibraryB;LibraryC /p:Configuration=Debug /p:Platform="Any CPU" -m
这样的命令,然后 msbuild 将构建 LibraryB
。
2.If 您在同一个解决方案中有很多项目,您可以在解决方案文件夹中创建一个自定义构建脚本 build.proj
文件,内容如下:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="CustomBuild">
<MSBuild Projects="LibraryA\LibraryA.vbproj" Properties="Configuration=$(Configuration);Platform=$(Platform)"/>
<MSBuild Projects="LibraryB\LibraryB.vbproj" Properties="Configuration=$(Configuration);Platform=$(Platform)"/>
<MSBuild Projects="LibraryC\LibraryC.vbproj" Properties="Configuration=$(Configuration);Platform=$(Platform)"/>
然后使用像 msbuild build.proj /p:Configuration=xx;Platform=xx 这样的命令来构建这些项目。
您可以暂时尝试这些解决方法,或者您可以使用 devenv 命令进行构建。但是对于问题本身,如果我没有误解的话,解决方案应该是 msbuild 团队的一个修复......希望以上所有内容都有帮助:)
这个答案在问题本身中引用了我的解决方法,以提高其可见性(如 对另一个答案的建议)。
到目前为止,我最好的办法是在 Complete.sln
(参见 msdn)向上的某个文件夹中创建一个 Directory.Solution.targets
,内容如下。
<Project>
<Target Name="SetSkip">
<ItemGroup>
<ProjectReference Update="*">
<SkipNonexistentProjects>Build</SkipNonexistentProjects>
</ProjectReference>
</ItemGroup>
</Target>
<Target Name="BuildAll" DependsOnTargets="SetSkip">
<CallTarget Targets="Build"/>
</Target>
<Target Name="RebuildAll" DependsOnTargets="SetSkip">
<CallTarget Targets="Rebuild"/>
</Target>
<Target Name="CleanAll" DependsOnTargets="SetSkip">
<CallTarget Targets="Clean"/>
</Target>
</Project>
注意 SkipNonexistentProjects
设置为 Build
,而不是 True
。当设置为 True
时,第二个项目被 Skipping project "2.csproj.metaproj" because it was not found.
跳过。
然后使用 /t:BuildAll
而不是 /t:Build
调用 msbuild
会按预期构建它所能构建的一切。
这对我来说 足够好 解决方案,尽管我仍然更喜欢不定义替代 Build/Rebuild 目标的方法。
我正在根据团队的需要定制构建服务器设置。 它应该会自动构建我们的 .net 解决方案。 我尽力不更改 .sln 或项目文件中的任何内容。
这项工作的明显构建工具是 msbuild
。我已经成功地从 .sln 文件编译了我们的解决方案。
下一步是测试某些解决方案的项目被破坏时的场景。在下面的情况下,我在 devenv
和 msbuild
之间遇到了奇怪的行为差异。有 3 个项目,其中 2nd 依赖于 1st,而 3rd 是独立且损坏的。 devenv
编译第 1 次和第 2 次,第 3 次失败,如预期的那样; msbuild
第一次编译,第三次失败,而且 - 出乎意料 - 没有尝试第二次。
示例解决方案(4 个文件:Complete.sln、1.csproj、2.csproj、3.csproj)
--- 1.csproj
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>2.0</OldToolsVersion>
</PropertyGroup>
<Target Name="Build">
<Message Importance="High" Text="Project 1" />
</Target>
</Project>
--- 2.csproj
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>2.0</OldToolsVersion>
</PropertyGroup>
<Target Name="Build">
<Message Importance="High" Text="Project 2" />
</Target>
</Project>
--- 3.csproj
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>2.0</OldToolsVersion>
</PropertyGroup>
<Target Name="Build">
<Message Importance="High" Text="Project 3" />
<Error Text="Build failed" />
</Target>
</Project>
--- Complete.sln
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29709.97
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "1", "1.csproj", "{AA88BE9A-5006-4CCE-8871-A67F413DBADF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "2", "2.csproj", "{BAF51480-4B90-454A-96F5-E63A05A486EF}"
ProjectSection(ProjectDependencies) = postProject
{AA88BE9A-5006-4CCE-8871-A67F413DBADF} = {AA88BE9A-5006-4CCE-8871-A67F413DBADF}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "3", "3.csproj", "{12C30CFB-7387-4CD2-81D4-87E14209C408}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AA88BE9A-5006-4CCE-8871-A67F413DBADF}.Debug|x86.ActiveCfg = Debug|x86
{AA88BE9A-5006-4CCE-8871-A67F413DBADF}.Debug|x86.Build.0 = Debug|x86
{BAF51480-4B90-454A-96F5-E63A05A486EF}.Debug|x86.ActiveCfg = Debug|x86
{BAF51480-4B90-454A-96F5-E63A05A486EF}.Debug|x86.Build.0 = Debug|x86
{12C30CFB-7387-4CD2-81D4-87E14209C408}.Debug|x86.ActiveCfg = Debug|x86
{12C30CFB-7387-4CD2-81D4-87E14209C408}.Debug|x86.Build.0 = Debug|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {75E95C15-489D-4D3F-82CA-735FB7B88910}
EndGlobalSection
EndGlobal
"Developer Command Prompt for VS 2019" 的控制台输出如下所示:
e>devenv /Build Debug Complete.sln
Microsoft Visual Studio 2019 Version 16.4.3.
Copyright (C) Microsoft Corp. All rights reserved.
1>------ Build started: Project: 1, Configuration: Debug x86 ------
2>------ Build started: Project: 3, Configuration: Debug x86 ------
1> Project 1
2> Project 3
2>C:\temp\msbuild\TestSolution\Complete.csproj(11,2): error : Build failed
3>------ Build started: Project: 2, Configuration: Debug x86 ------
3> Project 2
========== Build: 2 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
>msbuild Complete.sln /p:Configuration=Debug /p:Platform=x86 /m
Microsoft (R) Build Engine version 16.4.0+e901037fe for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.
Build started 23.01.2020 11:10:38.
1>Project "c:\temp\msbuild\TestSolution\Complete\Complete.sln" on node 1 (default targets).
1>ValidateSolutionConfiguration:
Building solution configuration "Debug|x86".
1>Project "c:\temp\msbuild\TestSolution\Complete\Complete.sln" (1) is building "c:\temp\msbuild\TestSolution\Complete.cs
proj" (2) on node 1 (default targets).
2>Build:
Project 1
2>Done Building Project "c:\temp\msbuild\TestSolution\Complete.csproj" (default targets).
1>Project "c:\temp\msbuild\TestSolution\Complete\Complete.sln" (1) is building "c:\temp\msbuild\TestSolution\Complete.cs
proj" (3) on node 2 (default targets).
3>Build:
Project 3
3>c:\temp\msbuild\TestSolution\Complete.csproj(11,5): error : Build failed
3>Done Building Project "c:\temp\msbuild\TestSolution\Complete.csproj" (default targets) -- FAILED.
1>Done Building Project "c:\temp\msbuild\TestSolution\Complete\Complete.sln" (default targets) -- FAILED.
Build FAILED.
"c:\temp\msbuild\TestSolution\Complete\Complete.sln" (default target) (1) ->
"c:\temp\msbuild\TestSolution\Complete.csproj" (default target) (3) ->
(Build target) ->
c:\temp\msbuild\TestSolution\Complete.csproj(11,5): error : Build failed
0 Warning(s)
1 Error(s)
Time Elapsed 00:00:00.65
请注意 msbuild
输出中缺少 Project 2
消息。
是否有(非侵入式)方式让msbuild
继续编译其他项目?
到目前为止我想出的最好的办法是在 Complete.sln
(参见 msdn)向上的某个文件夹中创建一个 Directory.Solution.targets
,内容如下。
<Project>
<Target Name="SetSkip">
<ItemGroup>
<ProjectReference Update="*">
<SkipNonexistentProjects>Build</SkipNonexistentProjects>
</ProjectReference>
</ItemGroup>
</Target>
<Target Name="BuildAll" DependsOnTargets="SetSkip">
<CallTarget Targets="Build"/>
</Target>
</Project>
注意 SkipNonexistentProjects
设置为 Build
,而不是 True
。当设置为 True
时,第二个项目被 Skipping project "2.csproj.metaproj" because it was not found.
.
然后用 /t:BuildAll
而不是 /t:Build
调用 msbuild
。但是我需要为 每个可能的解决方案和 每个可能的目标执行此操作,我真的很想要一些更好的方法,也许是我还找不到的命令行开关(/p:ContinueOnError=true;StopOnFirstFailure=false;SkipNonexistentProjects=true
没有帮助)。
更新 改进了我的解决方法:现在只需要根文件夹中的一个附加文件。
How to make MSBuild to NOT stop on error on .NET solution
答案是 否 因为它看起来像是一个关于 msbuild 的问题。所以我们只能有解决方法而不是解决方案...
我可以在我的机器上用 VS2019 和 msbuild 16.0 重现同样的问题。由于使用 devenv 一切正常,我认为您可以 post 一期 here 到 Msbuild 团队。 (我尝试了几个 msbuild 属性,但它们不起作用,所以我认为这个问题)
这里有一些临时解决方法:
1.If 你在这个解决方案中没有太多项目,你可以使用 target
开关以特定顺序构建特定项目,检查 this document.
对我来说,我使用像 msbuild Library.sln -target:LibraryA;LibraryB;LibraryC /p:Configuration=Debug /p:Platform="Any CPU" -m
这样的命令,然后 msbuild 将构建 LibraryB
。
2.If 您在同一个解决方案中有很多项目,您可以在解决方案文件夹中创建一个自定义构建脚本 build.proj
文件,内容如下:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="CustomBuild">
<MSBuild Projects="LibraryA\LibraryA.vbproj" Properties="Configuration=$(Configuration);Platform=$(Platform)"/>
<MSBuild Projects="LibraryB\LibraryB.vbproj" Properties="Configuration=$(Configuration);Platform=$(Platform)"/>
<MSBuild Projects="LibraryC\LibraryC.vbproj" Properties="Configuration=$(Configuration);Platform=$(Platform)"/>
然后使用像 msbuild build.proj /p:Configuration=xx;Platform=xx 这样的命令来构建这些项目。
您可以暂时尝试这些解决方法,或者您可以使用 devenv 命令进行构建。但是对于问题本身,如果我没有误解的话,解决方案应该是 msbuild 团队的一个修复......希望以上所有内容都有帮助:)
这个答案在问题本身中引用了我的解决方法,以提高其可见性(如
到目前为止,我最好的办法是在 Complete.sln
(参见 msdn)向上的某个文件夹中创建一个 Directory.Solution.targets
,内容如下。
<Project>
<Target Name="SetSkip">
<ItemGroup>
<ProjectReference Update="*">
<SkipNonexistentProjects>Build</SkipNonexistentProjects>
</ProjectReference>
</ItemGroup>
</Target>
<Target Name="BuildAll" DependsOnTargets="SetSkip">
<CallTarget Targets="Build"/>
</Target>
<Target Name="RebuildAll" DependsOnTargets="SetSkip">
<CallTarget Targets="Rebuild"/>
</Target>
<Target Name="CleanAll" DependsOnTargets="SetSkip">
<CallTarget Targets="Clean"/>
</Target>
</Project>
注意 SkipNonexistentProjects
设置为 Build
,而不是 True
。当设置为 True
时,第二个项目被 Skipping project "2.csproj.metaproj" because it was not found.
跳过。
然后使用 /t:BuildAll
而不是 /t:Build
调用 msbuild
会按预期构建它所能构建的一切。
这对我来说 足够好 解决方案,尽管我仍然更喜欢不定义替代 Build/Rebuild 目标的方法。