MSBuild:如何获取发出的警告数量?

问题描述 投票:0回答:3

有一个 MSBuild 脚本,其中包括一些 Delphi 和 C# 项目、单元测试等。

问题是:如果出现警告(出于测试目的,而不是发布版本),如何标记构建失败?在自定义任务中使用 LogError 而不是 LogWarning 似乎不是一个好的选择,因为构建应该尽可能多地进行测试(直到真正的错误),以便一次报告尽可能多的警告(构建项目在 CruiseControl.NET 中使用) ).

也许,解决方案是创建我自己的记录器,在里面存储警告标志,但我找不到是否有办法在构建结束时读取此标志?

附注收到警告后立即构建失败是没有问题的(Delphi 编译器输出由自定义任务处理,并且 /warnaserror 可用于 C#),但所需的行为是“构建所有内容;收集所有警告;构建失败”报告所有警告,而不仅仅是第一个警告。

P.P.S.至于我确实不需要数量的警告,而只是它们存在的标志,我决定简化信号机制,并使用简单的互斥体而不是共享内存。代码如下:

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++;
        }
    }
}
msbuild cruisecontrol.net
3个回答
7
投票

据我所知,MSBuild 没有内置支持来检索构建脚本给定点的警告计数。但是,您可以按照以下步骤来实现此目标:

  1. 创建一个自定义记录器来监听警告事件并计算警告数量
  2. 创建公开 [Output] warningCount 属性的自定义任务
  3. 自定义任务以某种方式从自定义记录器获取警告计数的值

最困难的步骤是步骤3。为此有几个选项,您可以在IPC - 进程间通信下自由搜索它们。下面是一个如何实现这一目标的工作示例。每个项目都是不同的类库

共享内存

http://weblogs.asp.net/rosherove/archive/2003/05/01/6295.aspx

我已经为命名创建了一个包装器 共享内存是 更大的项目。它基本上允许 序列化类型和对象图 存储在共享中并从共享中检索 记忆(包括你所期望的 跨进程)。是否较大 项目能否完成是另一回事 很重要;-)。

样本记录器

实现跟踪警告计数的自定义记录器。

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

示例任务

实现读取 MSbuild 项目中引发的警告数量的自定义任务。自定义任务从类库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;
        }
    }
}

去兜风。

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

如果运行以下命令:

c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild test.xml /logger:SampleLogger.dll

这将是输出:

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

1
投票

C# 编译器 (csc.exe) 有一个 /warnaserror 开关,会将警告视为错误并使构建失败。这也可以作为 .csproj 文件中的设置使用。我认为 Delphi 也有类似的能力。


1
投票
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 Successful build of '%~nx1'. >> %MrB-BUILDLOG%
  )
)
© www.soinside.com 2019 - 2024. All rights reserved.