如何使 MSBuild 不因 .NET 解决方案出错而停止 [英] How to make MSBuild to NOT stop on error on .NET solution

查看:19
本文介绍了如何使 MSBuild 不因 .NET 解决方案出错而停止的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究根据团队需求量身定制的构建服务器设置.它应该自动构建我们的 .net 解决方案.我尽量不更改 .sln 或项目文件中的任何内容.

I'm working on a custom build server setup tailored to the team needs. It should automatically build our .net solutions. I'm doing my best to not change anything in the .sln or project files.

该作业的明显构建工具是 msbuild.我已经成功地从 .sln 文件中成功编译了我们的解决方案.

The obvious build tool for the job is the msbuild. I've got it as far as to actually successfully compile our solutions from .sln files.

下一步是测试某些解决方案项目损坏时的场景.在以下情况下,我在 devenvmsbuild 之间遇到了奇怪的行为差异.有 3 个项目,其中 2nd 依赖于 1st,而 3rd 是独立和破碎的.devenv 按预期编译第 1 次和第 2 次,第 3 次失败;msbuild 编译第 1 次,第 3 次失败,并且 - 出乎意料地 - 没有尝试第 2 次.

Next step is testing the scenario when some of solution's projects are broken. And here I encountered a strange difference in behavior between devenv and msbuild in following situation. There are 3 projects, where 2nd depends on 1st, and 3rd is independent and broken. devenv compiles 1st and 2nd and fails the 3rd, as expected; msbuild compiles 1st, fails 3rd and - unexpectedly - doesn't try the 2nd.

示例解决方案(4 个文件:Complete.sln、1.csproj、2.csproj、3.csproj)

Example solution (4 files: 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

VS 2019 开发人员命令提示符"的控制台输出如下所示:

Console output from "Developer Command Prompt for VS 2019" is like following:

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\3.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\1.cs
       proj" (2) on node 1 (default targets).
     2>Build:
         Project 1
     2>Done Building Project "c:\temp\msbuild\TestSolution\Complete\1.csproj" (default targets).
     1>Project "c:\temp\msbuild\TestSolution\Complete\Complete.sln" (1) is building "c:\temp\msbuild\TestSolution\Complete\3.cs
       proj" (3) on node 2 (default targets).
     3>Build:
         Project 3
     3>c:\temp\msbuild\TestSolution\Complete\3.csproj(11,5): error : Build failed
     3>Done Building Project "c:\temp\msbuild\TestSolution\Complete\3.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\3.csproj" (default target) (3) ->
       (Build target) ->
         c:\temp\msbuild\TestSolution\Complete\3.csproj(11,5): error : Build failed

    0 Warning(s)
    1 Error(s)

Time Elapsed 00:00:00.65

请注意 msbuild 输出中缺少 Project 2 消息.

Please notice in msbuild output the Project 2 message is missing.

有没有(非侵入式)方法让 msbuild 继续编译其他项目?

Is there a (non-intrusive) way to make msbuild continue compiling other projects?

到目前为止,我想到的最好的方法是在 Complete.sln 上方的某个文件夹中创建一个 Directory.Solution.targets(参见 msdn) 包含以下内容.>

The best I came up till now is creating a Directory.Solution.targets in some folder upwards from Complete.sln (see msdn) with following content.

<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" 因为它没有找到..

Note SkipNonexistentProjects is set to Build, not True. When set to True the 2nd project is skipped with Skipping project "2.csproj.metaproj" because it was not found..

然后使用 /t:BuildAll 而不是 /t:Build 调用 msbuild.但是我需要为所有可能的解决方案和每个可能的目标执行此操作,而且我真的想要一些更好的方法,也许是我还找不到的命令行开关(/p:ContinueOnError=true;StopOnFirstFailure=false;SkipNonexistentProjects=true 没有帮助.

And then calling msbuild with /t:BuildAll instead of /t:Build. But I'd need to do this for every possible solution and every possible target, and I'd really like some better way, maybe a command line switch I wasn't able to find yet (/p:ContinueOnError=true;StopOnFirstFailure=false;SkipNonexistentProjects=true doesn't help).

UPDATE 改进了我的解决方法:现在只需要根文件夹中的一个附加文件.

UPDATE improved my workaround: now only a single additional file in a root folder is needed.

推荐答案

这个答案在问题本身中引用了我的解决方法,以提高其可见性(如 评论另一个答案).

This answer quotes my workaround in the question itself, to improve its visibility (as suggested in a comment to another answer).

到目前为止,我想到的最好的方法是在 Complete.sln 上方的某个文件夹中创建一个 Directory.Solution.targets(参见 msdn) 包含以下内容.>

The best I came up till now is creating a Directory.Solution.targets in some folder upwards from Complete.sln (see msdn) with following content.

<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" 因为它没有找到..

Note SkipNonexistentProjects is set to Build, not True. When set to True the 2nd project is skipped with Skipping project "2.csproj.metaproj" because it was not found..

然后使用 /t:BuildAll 而不是 /t:Build 调用 msbuild 会按预期构建它可以构建的所有内容.

And then calling msbuild with /t:BuildAll instead of /t:Build builds everything it can, as expected.

这对我来说是一个足够好的解决方案,尽管我仍然更喜欢不定义替代构建/重建目标的某种方式.

This is a good enough solution for me, although I would still prefer some way without defining alternate Build/Rebuild targets.

这篇关于如何使 MSBuild 不因 .NET 解决方案出错而停止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆