Cómo verificar si una tarea de MSBuild falla si se usa ContinueOnError = true

Estoy ejecutando elMSBuild tarea conContinueOnError= verdadero:

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

Así que mi compilación siempre tiene éxito.

¿Hay alguna manera de averiguar si ocurre algún error?

No pude encontrar ningunaSalida delMSBuild Tarea que contiene esta información. La única forma que conozco es analizar el archivo de registro en busca de errores, pero para mí parece una solución alternativa.

(Estoy usando MSBuild 4.0)

Esta es una respuesta a la última respuesta de @Ilya.
Estoy usando comentarios / respuestas debido a la longitud y las restricciones de formato de los comentarios.

Log está dentro del alcance de objetivos individuales o para ser tareas más específicas ...

Esta fue la primera pregunta que surgió cuando estaba leyendo su comentario con la sugerencia de usarLog.HasLoggedErrors: "¿Fue el alcance del registro?".
Desafortunadamente no pude encontrar una documentación adecuada. MSND no ayuda mucho ...
¿Por qué sabías que está dentro del alcance de la tarea?
¡No tengo ninguna duda sobre tu declaración! Me pregunto si hay alguna documentación adecuada en algún lugar .. (No he estado usandoMSBuild durante años ;-)

En cualquier caso, ¿qué estás construyendo como proyecto?

Mis proyectos de prueba son muy 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>

losCopyNotExistingFile.proj solo intenta copiar un archivo que no 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>

Y esta es mi tarea personalizada.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;
        }
    }
}

Si construyo mi MyTest.proj elHasLoggedErrorsse establecerá enfalse aunque un error (MSB3021) se registró (?) en el registrador de consola:

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.

Mi expectativa eraHasLoggedErrors se establecería entrue.



una forma es construir uno mismo pero con un objetivo diferente, por ejemplo, su DefaultTargets one lanza su tarea personalizada MSBuildWrapper apuntando a sí mismo (es decir, $ (MSBuildProjectFile)) pero con un objetivo diferente que hace otras compilaciones, copias

Ya lo he intentado (que eran mis investigaciones a las que me refería en mi publicación). Lamentablemente tampoco funciona :-(
(Soy consciente de que dijisteEn teoria). Mi nuevosoltero El proyecto se ve así:

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

Si construyo este proyectoHasLoggedErrors todavía se establecerá enfalse.
(Además, mi compilación "real" que actualmente mantengo es mucho más compleja y contiene varios archivos de proyecto con objetivos ... por lo que no puedo empaquetarlos en un solo archivo de proyecto).

o escribir un registrador personalizado y pasarlo a través de la línea de comandos

Esa fue mi última esperanza!
Mi "real" buildtiene un registrador personalizado pasó a través de la línea de comandos (no lo usé para mi proyecto de prueba por simplicidad). Eso es en realidad producir el registro (un archivo XML) que voy a analizar para averiguar si se ha registrado algún error.
Por cierto, pensé que el registrador de consola es una especie de registrador "global". ¿Me equivoco?

De todos modos, el logger personalizado tampoco ayuda, elLog.HasLoggedErrors todavía está configurado parafalse.
¿Hay alguna forma de que no sepa hacer referencia a un registrador en particular (por ejemplo, mi registrador personalizado) para preguntar si se ha registrado algún error?

Realmente pareceLog Está orientado a objetivos individuales.

Hmm ... si la reflexión sobre la instancia de buildengine es el último recurso, todavía preferiría analizar el registro.
(¡No me culpes! :-))

Mi decisión
Después de algunas investigaciones, he decidido seguir con mi solución inicial: analizar el registro para averiguar si la compilación ha fallado.

Compruebe mis comentarios para ver por qué prefiero que se hayan proporcionado las sugerencias hasta ahora.

Si alguien tiene otras ideas, no dude en compartirlas :-)

(De lo contrario esta pregunta se puede cerrar, supongo ...)

Respuestas a la pregunta(5)

Su respuesta a la pregunta