有一个 MSBuild 脚本,其中包括 Delphi 和 C# 项目、单元测试等的编号。
问题是:如果出现警告,如何标记构建失败(出于测试目的,而不是发布构建)?在自定义任务中使用 LogError 而不是 LogWarning 似乎不是一个好的选择,因为构建应该尽可能多地测试(直到真正的错误)一次报告尽可能多的警告(构建项目在 CruiseControl.NET 中使用)。
可能是,解决方案是创建我自己的记录器,在里面存储警告标志,但我找不到在构建结束时是否有办法读取这个标志?
PS 收到警告后立即构建失败没有问题(Delphi 编译器输出由自定义任务处理,/warnaserror 可用于 C#),但期望的行为是“构建所有内容;收集所有警告;构建失败" 报告所有警告,而不仅仅是第一个警告。
PPS 至于我真的不需要警告的数量,而只是他们存在的标志,我决定简化信号机制,并使用微不足道的互斥体而不是共享内存。代码如下:
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++;
}
}
}