如果使用ContinueOnError = true,如何检查MSBuild-Task是否失败

Ele*_*ena 12 msbuild msbuild-task msbuild-4.0

我正在使用ContinueOnError = true运行MSBuild任务:

<MSBuild Projects="@(ComponentToDeploy)"
    Targets="$(DeploymentTargets)"
    Properties="$(CommonProperties);%(AdditionalProperties)"
    ContinueOnError="true" 
    Condition="%(Condition)"/>
Run Code Online (Sandbox Code Playgroud)

所以我的构建总是成功的.

有没有办法找出是否发生任何错误?

我找不到包含此信息的MSBuild任务的任何输出.我知道的唯一方法是解析日志文件中的错误,但对我来说它看起来像是一种解决方法.

(我正在使用MSBuild 4.0)


这是@Ilya最后反馈的答案.
我正在使用反馈/答案,因为评论的长度和格式限制.

日志范围限定为单个目标或更具体的任务......

这确实是我在阅读您的评论时出现的第一个问题,建议使用Log.HasLoggedErrors:" 这是日志的范围吗? ".
不幸的是,我无法找到合适的文档.MSND没有多大帮助......
为什么你知道它的任务范围是什么?
我对你的陈述毫不怀疑!我只是想知道某处是否有适当的文档..(我多年没有使用过MSBuild ;-)

无论如何,你在建设什么项目?

我的测试项目非常简单.
MyTest.project

<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="ElenasTarget" ToolsVersion="4.0">

    <UsingTask AssemblyFile="$(MSBuildProjectDirectory)\MyCompany.Tools.MSBuild.Tasks.dll" TaskName="MSBuildWithHasLoggedErrors" />

    <ItemGroup>
        <MyProjects Include="CopyNotExistingFile.proj" />
    </ItemGroup>

    <Target Name="ElenasTarget">
        <MSBuildWithHasLoggedErrors Projects="@(MyProjects)" ContinueOnError="true" >
            <Output TaskParameter="HasLoggedErrors" PropertyName="BuildFailed" />
         </MSBuildWithHasLoggedErrors>

         <Message Text="BuildFailed=$(BuildFailed)" />
  </Target>
</Project>
Run Code Online (Sandbox Code Playgroud)

CopyNotExistingFile.proj只是试图复制不存在的文件:

<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Target1" ToolsVersion="4.0">
    <Target Name="Target1"> 
         <Copy SourceFiles="C:\lalala.bum" DestinationFiles="C:\tralala.bam" />
  </Target>
</Project>
Run Code Online (Sandbox Code Playgroud)

这是我的自定义任务MSBuildWithHasLoggedErrors

namespace MyCompany.Tools.MSBuild.Tasks
{
    public class MSBuildWithHasLoggedErrors : Microsoft.Build.Tasks.MSBuild
    {
        [Output]
        public bool HasLoggedErrors { get; private set; }

        public override bool Execute()
        {
            try
            {
                base.Execute();
                HasLoggedErrors = Log.HasLoggedErrors;
            }
            catch (Exception e)
            {
                Log.LogErrorFromException(e, true);
                return false;
            }

            return true;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我构建我的MyTest.proj,HasLoggedErrors将设置为false虽然错误(MSB3021)已记录(?)到控制台记录器:

Project "C:\Users\elena\mytest.proj" on node 1 (default targets).
Project "C:\Users\elena\mytest.proj" (1) is building "C:\Users\elena\CopyNotExistingFile.proj" (2) on node 1 (default targets).
Target1:
  Copying file from "C:\lalala.bum" to "C:\tralala.bam".
C:\Users\elena\CopyNotExistingFile.proj(5,4): error MSB3021: Unable to copy file "C:\lalala.bum" to "C:\tralala.bam". Could not find file 'C:\lalala.bum'.
Done Building Project "C:\Users\elena\CopyNotExistingFile.proj" (default targets) -- FAILED.
ElenasTarget:
  BuildFailed=False
Done Building Project "C:\Users\elena\mytest.proj" (default targets).

Build succeeded.
Run Code Online (Sandbox Code Playgroud)

我的期望是HasLoggedErrors设定的true.



一种方法是构建self但具有不同的目标,例如你的DefaultTargets一个启动指向自身的自定义MSBuildWrapper任务(即$(MSBuildProjectFile)),但是使用不同的目标执行其他构建,副本

我已经尝试过了(这是我在我的帖子中的调查).不幸的是它也不起作用:-
((我知道你在理论上说过).我的新项目看起来像这样:

<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="ElenasTarget" ToolsVersion="4.0">

    <UsingTask AssemblyFile="$(MSBuildProjectDirectory)\MyCompany.Tools.MSBuild.Tasks.dll" TaskName="MSBuildWithHasLoggedErrors" />

    <Target Name="ElenasTarget">
        <MSBuildWithHasLoggedErrors Projects="$(MSBuildProjectFile)" Targets="CopyNotExistingFile" ContinueOnError="true" >
            <Output TaskParameter="HasLoggedErrors" PropertyName="BuildFailed" />
         </MSBuildWithHasLoggedErrors>

         <Message Text="BuildFailed=$(BuildFailed)" />
  </Target>

  <Target Name="CopyNotExistingFile" >
         <Copy SourceFiles="C:\lalala.bum" DestinationFiles="C:\tralala.bam" />
  </Target>
</Project>
Run Code Online (Sandbox Code Playgroud)

如果我构建此项目HasLoggedErrors仍将设置为false.
(此外,我目前正在维护的"真正的"构建包含多个包含目标的项目文件,因此我无法将它们全部打包在一个项目文件中.

或编写自定义记录器并通过命令行传递它

那是我最后的希望!
我的"真实"版本一个通过命令行传递的自定义记录器(为简单起见,我没有将它用于我的测试项目).这实际上是生成我要解析的日志(XML文件),以确定是否记录了任何错误.
顺便说一句,我认为控制台记录器是一种"全局"记录器.我错了吗?

无论如何,自定义记录器也没有帮助,Log.HasLoggedErrors仍然设置为false.
有什么方法我不知道引用特定的记录器(例如我的自定义记录器)来询问它是否记录了任何错误?

看起来确实Log是针对个别目标的.

嗯......如果对buildengine实例的反射是最后的手段,我仍然会更喜欢解析日志.
(别怪我!:-))


我的决定
经过一些调查后,我决定坚持我的初始解决方案:解析日志以确定构建是否失败.

检查我的评论,看看为什么我更喜欢到目前为止提供的建议.

如果有人有其他想法,请不要犹豫分享:-)

(否则这个问题可以关闭,我想...)

Aar*_*sen 20

MSBuildLastTaskResult 保留的属性将被设置为True当最后一个任务成功,False如果最后的任务失败:

<MSBuild Projects="@(ComponentToDeploy)"
         Targets="$(DeploymentTargets)"
         Properties="$(CommonProperties);%(AdditionalProperties)"
         ContinueOnError="true" 
         Condition="%(Condition)" />
<Message Text="MSBuild failed!" Condition="'$(MSBuildLastTaskResult)' == 'False'" />
Run Code Online (Sandbox Code Playgroud)

我相信这是在MSBuild v4.0中引入的.