MSBuild: Wie Anzahl der Warnungen erhalten angehoben?
-
02-07-2019 - |
Frage
Es gibt einen MSBuild-Skript, die Zahl, wenn Delphi und C # -Projekten, Unit-Tests usw.
enthältDas Problem ist: Wie bauen markieren schlug fehl, wenn Warnungen (für Testzwecke, nicht für Release-Builds) erhoben wurden? Mit LogError statt LogWarning in benutzerdefinierten Aufgaben scheint keine gute Wahl zu sein, denn die Build sollte so viel testen, wie es in der Lage ist (bis zum wirklichen Fehler) so viele Warnungen wie möglich in einer Zeit zu berichten Projektes (Build verwendet in CruiseControl.NET ).
Vielleicht ist die Lösung meine eigenen Logger zu erstellen, die Warnungen Flagge innerhalb speichern würde, aber ich kann nicht finden, wenn es eine Möglichkeit ist, diese Flagge am Ende des Build zu lesen?
P. S. Es gibt kein Problem ist zum Scheitern verurteilt die Build sofort nach Erhalt eine Warnung (wird Delphi-Compiler-Ausgabe von benutzerdefinierten Task verarbeitet und / warnaserror könnte für C # verwendet werden), aber das gewünschte Verhalten ist „alles bauen, alle Warnungen sammeln, nicht die Build“ über alle Warnungen zu berichten, nicht nur über die ersten.
P.P.S. Soweit ich brauche nicht Anzahl der Warnungen wirklich, aber nur Flagge ihrer Anwesenheit, entschied ich mich Signalisierungsmechanismus zu vereinfachen und trivial Mutex anstelle von Shared Memory. Code ist unter:
using System;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using System.Threading;
namespace Intrahealth.Build.WarningLogger
{
public sealed class WarningLoggerCheck : Task
{
public override bool Execute()
{
Log.LogMessage("WarningLoggerCheck:" + mutexName + "...");
result = false;
Mutex m = null;
try
{
m = Mutex.OpenExisting(mutexName);
}
catch (WaitHandleCannotBeOpenedException)
{
result = true;
}
catch (Exception)
{
}
if (result)
Log.LogMessage("WarningLoggerCheck PASSED");
else
Log.LogError("Build log contains warnings. Build is FAILED");
return result;
}
private bool result = true;
[Output]
public bool Result
{
get { return result; }
}
private string mutexName = "WarningLoggerMutex";
public string MutexName
{
get { return mutexName; }
set { mutexName = value ?? "WarningLoggerMutex"; }
}
}
public class WarningLogger : Logger
{
internal static int warningsCount = 0;
private string mutexName = String.Empty;
private Mutex mutex = null;
public override void Initialize(IEventSource eventSource)
{
eventSource.WarningRaised += new BuildWarningEventHandler(eventSource_WarningRaised);
}
private void SetMutex()
{
if (mutexName == String.Empty)
{
mutexName = "WarningLoggerMutex";
if (this.Parameters != null && this.Parameters != String.Empty)
{
mutexName = this.Parameters;
}
}
mutex = new Mutex(false, mutexName);
}
void eventSource_WarningRaised(object sender, BuildWarningEventArgs e)
{
if (e.Message != null && e.Message.Contains("MSB3146"))
return;
if (e.Code != null && e.Code.Equals("MSB3146"))
return;
if (warningsCount == 0)
SetMutex();
warningsCount++;
}
}
}
Lösung
AFAIK MSBuild hat keine eingebaute Unterstützung die Warnung Zählung an einem bestimmten Punkt des Build-Skript abzurufen. Sie können diese Schritte jedoch folgen, dieses Ziel zu erreichen:
- Erstellen Sie eine benutzerdefinierte Logger, die für das Warnereignis zuhört und zählt die Anzahl der Warnungen
- Erstellen Sie eine benutzerdefinierte Aufgabe, ein [Output] Warning Eigenschaft aussetzt
- Die benutzerdefinierte Aufgabe bekommt irgendwie den Wert der Warnung Zählung aus dem benutzerdefinierten Logger
Der schwierigste Schritt ist Schritt 3 Hierzu gibt es mehrere Möglichkeiten, und Sie können sie unter IPC frei suchen - Inter-Prozess Comunication. Folgt ein funktionierendes Beispiel dafür, wie Sie dies erreichen können. Jedes Element ist eine andere Klassenbibliothek .
Shared
http://weblogs.asp.net/rosherove/ Archiv / 2003/05/01 / 6295.aspx
Ich habe einen Wrapper erstellt für benannt gemeinsam genutzten Speicher, war ein Teil einer größeres Projekt. Es ermöglicht im Grunde serialisiert und Objektgraphen werden gespeichert und abgerufen aus dem gemeinsamen Speicher (einschließlich, wie man es erwarten würde Kreuzprozess). Ob die größere Projekt, das jemals abgeschlossen wird ist eine andere Materie, -).
SampleLogger
Implementiert die benutzerdefinierten Logger, die Spur der Warnung Zahl hält.
namespace SampleLogger
{
using System;
using Microsoft.Build.Utilities;
using Microsoft.Build.Framework;
using DM.SharedMemory;
public class MySimpleLogger : Logger
{
private Segment s;
private int warningCount;
public override void Initialize(IEventSource eventSource)
{
eventSource.WarningRaised += new BuildWarningEventHandler(eventSource_WarningRaised);
this.s = new Segment("MSBuildMetadata", SharedMemoryCreationFlag.Create, 65535);
this.s.SetData(this.warningCount.ToString());
}
void eventSource_WarningRaised(object sender, BuildWarningEventArgs e)
{
this.warningCount++;
this.s.SetData(this.warningCount.ToString());
}
public override void Shutdown()
{
this.s.Dispose();
base.Shutdown();
}
}
}
SampleTasks
Implementiert die individuelle Aufgabe, die die Anzahl der Warnungen im MSbuild Projekt angehoben liest. Die benutzerdefinierte Aufgabe liest aus dem von dem benutzerdefinierten Logger geschrieben gemeinsam genutzten Speicher in Klassenbibliothek implementiert SampleLogger .
namespace SampleTasks
{
using System;
using Microsoft.Build.Utilities;
using Microsoft.Build.Framework;
using DM.SharedMemory;
public class BuildMetadata : Task
{
public int warningCount;
[Output]
public int WarningCount
{
get
{
Segment s = new Segment("MSBuildMetadata", SharedMemoryCreationFlag.Attach, 0);
int warningCount = Int32.Parse(s.GetData() as string);
return warningCount;
}
}
public override bool Execute()
{
return true;
}
}
}
für eine Spritztour gehen.
<?xml version="1.0" encoding="UTF-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Main">
<UsingTask TaskName="BuildMetadata" AssemblyFile="F:\temp\SampleLogger\bin\debug\SampleTasks.dll" />
<Target Name="Main">
<Warning Text="Sample warning #1" />
<Warning Text="Sample warning #2" />
<BuildMetadata>
<Output
TaskParameter="WarningCount"
PropertyName="WarningCount" />
</BuildMetadata>
<Error Text="A total of $(WarningCount) warning(s) were raised." Condition="$(WarningCount) > 0" />
</Target>
</Project>
Wenn Sie den folgenden Befehl:
c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild test.xml /logger:SampleLogger.dll
Dies ist der Ausgang:
Microsoft (R) Build Engine Version 2.0.50727.3053
[Microsoft .NET Framework, Version 2.0.50727.3053]
Copyright (C) Microsoft Corporation 2005. All rights reserved.
Build started 30-09-2008 13:04:39.
__________________________________________________
Project "F:\temp\SampleLogger\bin\debug\test.xml" (default targets):
Target Main:
F:\temp\SampleLogger\bin\debug\test.xml : warning : Sample warning #1
F:\temp\SampleLogger\bin\debug\test.xml : warning : Sample warning #2
F:\temp\SampleLogger\bin\debug\test.xml(15,3): error : A total of 2 warning(s) were raised.
Done building target "Main" in project "test.xml" -- FAILED.
Done building project "test.xml" -- FAILED.
Build FAILED.
F:\temp\SampleLogger\bin\debug\test.xml : warning : Sample warning #1
F:\temp\SampleLogger\bin\debug\test.xml : warning : Sample warning #2
F:\temp\SampleLogger\bin\debug\test.xml(15,3): error : A total of 2 warning(s) were raised.
2 Warning(s)
1 Error(s)
Time Elapsed 00:00:00.01
Andere Tipps
Der C # -Compiler (csc.exe) eine / warnaserror Schalter werden Warnungen als Fehler behandeln und die Build fehl. Dies ist auch als eine Einstellung in der CSPROJ-Datei zur Verfügung. Ich gehe davon aus Delphi eine ähnliche Fähigkeit hat.
msbuild.exe %~nx1 /t:Rebuild /p:Configuration=Release >> %MrB-BUILDLOG%
findstr /r /c:"[1-9][0-9]* Error(s)" >> %MrB-BUILDLOG%
if not errorlevel 1 (
echo ERROR: sending notification email for build errors in '%~nx1'. >> %MrB-BUILDLOG%
) else (
findstr /r /c:"[1-9][0-9]* Warning(s)" >> %MrB-BUILDLOG%
if not errorlevel 1 (
echo ERROR: sending notification email for build warnings in '%~nx1'. >>
% MrB-BUILDLOG% ) Else ( echo Erfolgreiche Build von '% ~ nx1'. >>% MrB-BUILDLOG% ) )