Como verificar se um MSBuild-Task falhar se usando ContinueOnError = true

Eu estou correndo oMSBuild tarefa comContinueOnError= true:

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

Então, minha construção sempre é bem-sucedida.

Existe uma maneira de descobrir se algum erro ocorre?

Eu não consegui encontrar nenhumSaída doMSBuild tarefa contendo esta informação. A única maneira que eu sei é analisar o arquivo de log para erros, mas parece uma solução para mim.

(Estou usando o MSBuild 4.0)

Esta é uma resposta ao último feedback de @Ilya.
Estou usando feedback / resposta por causa das restrições de tamanho e formatação dos comentários.

O log tem o escopo para destinos individuais ou para tarefas mais específicas ...

Esta foi a primeira pergunta que surgiu quando eu estava lendo o seu comentário com a sugestão de usarLog.HasLoggedErrors: "Foi o escopo do Log?".
Infelizmente não consegui encontrar uma documentação apropriada. MSND não ajuda muito ...
Por que você sabe que é o escopo da tarefa?
Eu não estou em dúvida sobre a sua declaração em tudo! Eu só estou querendo saber se há uma documentação adequada em algum lugar .. (eu não tenho usadoMSBuild por anos ;-)

De qualquer forma, o que você está construindo como projeto?

Meus projetos de teste são muito simples.
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>

oCopyNotExistingFile.proj apenas tenta copiar um arquivo que não existe:

<?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>

E esta é minha tarefa personalizadaMSBuildWithHasLoggedErrors

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;
        }
    }
}

Se eu construir meu MyTest.projHasLoggedErrorsserá definido parafalse embora um erro (MSB3021) foi registrado (?) no logger do console:

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.

Minha expectativa eraHasLoggedErrors seria definido paratrue.



Uma maneira é construir auto, mas com alvo diferente, por exemplo, seu DefaultTargets um lança sua tarefa personalizada MSBuildWrapper apontando para si mesmo (ou seja, $ (MSBuildProjectFile)), mas com um destino diferente que faz outras compilações, cópias

Eu já tentei (que foram as minhas investigações que eu quis dizer no meu post). Infelizmente não funciona :-(
(Eu estou ciente que você disseem teoria). Meu novosolteiro projeto parece com isso:

<?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>

Se eu construir este projetoHasLoggedErrors ainda será definido parafalse.
(Além disso, minha build "real" que estou mantendo atualmente é muito mais complexa, contendo vários arquivos de projeto com targets ... então eu não posso empacotá-los em um único arquivo de projeto).

ou escrevendo um registrador personalizado e passando-o pela linha de comando

Essa foi a minha última esperança!
Minha construção "real"tem um logger personalizado passou pela linha de comando (eu não o usei para o meu projeto de teste por uma questão de simplicidade). Isso está realmente produzindo o log (um arquivo XML) que vou analisar para descobrir se algum erro foi registrado.
BTW, eu pensei que o logger do console é uma espécie de logger "global". Estou errado?

De qualquer forma, o logger customizado não ajuda nemLog.HasLoggedErrors ainda está definido parafalse.
Existe alguma maneira que eu não estou ciente de fazer referência a um logger particular (por exemplo, meu logger personalizado) para perguntar se ele registrou algum erro?

Realmente pareceLog tem escopo para alvos individuais.

Hmm ... se o reflexo na instância do buildengine for o último recurso, eu ainda preferiria analisar o log.
(Não me culpe! :-))

Minha decisão
Depois de algumas investigações, decidi continuar com a minha solução inicial: analisar o log para descobrir se a compilação falhou.

Confira meus comentários para ver porque eu prefiro que as sugestões tenham sido fornecidas até agora.

Se alguém tiver outras idéias, não hesite em compartilhar :-)

(Caso contrário, esta questão pode ser encerrada, suponho ...)

questionAnswers(5)

yourAnswerToTheQuestion