So überprüfen Sie, ob eine MSBuild-Task fehlschlägt, wenn ContinueOnError = true verwendet wird

Ich leite dieMSBuild Aufgabe mitContinueOnError= wahr:

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

Mein Build ist also immer erfolgreich.

Gibt es eine Möglichkeit herauszufinden, ob ein Fehler auftritt?

Ich konnte keine findenAusgabe desMSBuild Aufgabe, die diese Informationen enthält. Die einzige Möglichkeit, die ich kenne, besteht darin, die Protokolldatei auf Fehler zu analysieren, aber es sieht für mich nach einer Problemumgehung aus.

(Ich benutze MSBuild 4.0)

Dies ist eine Antwort auf das letzte Feedback von @Ilya.
Ich verwende Feedback / Antwort wegen der Länge und Formatierungsbeschränkungen der Kommentare.

Das Protokoll ist auf einzelne Ziele oder auf spezifischere Aufgaben zugeschnitten ...

Dies war in der Tat die erste Frage, die sich stellte, als ich Ihren Kommentar mit dem Vorschlag zur Verwendung lasLog.HasLoggedErrors: "Was ist der Umfang des Protokolls?".
Leider konnte ich keine ordnungsgemäße Dokumentation finden. MSND hilft nicht viel ...
Warum wusstest du, dass es für die Aufgabe bestimmt ist?
Ich bin überhaupt nicht im Zweifel über Ihre Aussage! Ich frage mich nur, ob es irgendwo eine richtige Dokumentation gibtMSBuild jahrelang ;-)

Was bauen Sie auf jeden Fall als Projekt?

Meine Testprojekte sind sehr einfach.
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>

DasCopyNotExistingFile.proj versucht nur, eine Datei zu kopieren, die nicht existiert:

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

Und das ist meine benutzerdefinierte AufgabeMSBuildWithHasLoggedErrors

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

Wenn ich mein MyTest.proj baue dasHasLoggedErrorswird eingestellt auffalse obwohl ein Fehler (MSB3021) wurde (?) im Konsolenlogger protokolliert:

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.

Meine Erwartung warHasLoggedErrors würde eingestellt werden auftrue.



Eine Möglichkeit besteht darin, sich selbst zu erstellen, aber mit einem anderen Ziel, z. B. Ihren DefaultTargets, startet man Ihre benutzerdefinierte MSBuildWrapper-Aufgabe, die auf sich selbst zeigt (dh $ (MSBuildProjectFile)), aber mit einem anderen Ziel, das andere Builds ausführt, kopiert

Ich habe es bereits versucht (das waren meine Untersuchungen, die ich in meinem Beitrag meinte). Leider funktioniert es auch nicht :-(
(Mir ist bewusst, dass Sie gesagt habenin der Theorie). Mein neuesSingle Projekt sieht so aus:

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

Wenn ich dieses Projekt baueHasLoggedErrors wird weiterhin auf gesetztfalse.
(Außerdem ist mein "realer" Build, den ich gerade verwalte, sehr viel komplexer und enthält mehrere Projektdateien mit Zielen. Daher kann ich nicht alle in eine einzige Projektdatei packen.)

oder schreiben Sie einen benutzerdefinierten Logger und übergeben Sie ihn über die Befehlszeile

Das war meine letzte Hoffnung!
Mein "richtiger" Buildhat Die Befehlszeile wurde von einem benutzerdefinierten Protokollierer durchlaufen (der Einfachheit halber habe ich ihn für mein Testprojekt nicht verwendet). Das ist eigentlich das Protokoll (eine XML-Datei), das ich analysieren werde, um herauszufinden, ob Fehler protokolliert wurden.
Übrigens dachte ich, der Konsolenlogger ist eine Art "globaler" Logger. Liege ich falsch?

Jedenfalls hilft der benutzerdefinierte Logger auch nicht, derLog.HasLoggedErrors ist immer noch auf eingestelltfalse.
Kann ich nicht auf einen bestimmten Logger (z. B. meinen benutzerdefinierten Logger) verweisen, um zu fragen, ob er Fehler protokolliert hat?

Es sieht wirklich so ausLog ist auf einzelne Ziele zugeschnitten.

Hmm ... wenn das Nachdenken über die Instanz von buildengine der letzte Ausweg ist, würde ich es immer noch vorziehen, das Protokoll zu analysieren.
(Tadelt mich nicht! :-))

Meine Entscheidung
Nach einigen Untersuchungen habe ich mich entschlossen, bei meiner ursprünglichen Lösung zu bleiben: Analysieren Sie das Protokoll, um herauszufinden, ob der Build fehlgeschlagen ist.

Überprüfen Sie meine Kommentare, um zu sehen, warum ich diese Vorschläge den bisherigen Vorschlägen vorzuziehen.

Wenn jemand andere Ideen hat, zögern Sie nicht zu teilen :-)

(Ansonsten kann diese Frage geschlossen werden, nehme ich an ...)

Antworten auf die Frage(5)

Ihre Antwort auf die Frage