6

Delphi および C# プロジェクト、単体テストなどの番号を含む MSBuild スクリプトがあります。

問題は、警告が発生した場合にビルドに失敗したことをマークする方法です (リリース ビルドではなく、テスト目的で)。カスタム タスクで LogWarning の代わりに LogError を使用することは、適切なオプションではないようです。これは、ビルドが可能な限り (実際のエラーが発生するまで) できるだけ多くの警告を報告するようにテストする必要があるためです (ビルド プロジェクトは CruiseControl.NET で使用されています)。 )。

おそらく、解決策は警告フラグを内部に保存する独自のロガーを作成することですが、ビルドの最後にこのフラグを読み取る方法があるかどうかわかりませんか?

PS 警告を受け取った直後にビルドを失敗しても問題ありませんが (Delphi コンパイラの出力はカスタム タスクによって処理され、C# では /warnaserror を使用できます)、望ましい動作は「すべてをビルドし、すべての警告を収集し、ビルドを失敗させます」です。最初の警告だけでなく、すべての警告について報告します。

PPS 警告の数ではなく、その存在のフラグだけが本当に必要な限り、シグナル伝達メカニズムを簡素化し、共有メモリの代わりに単純な Mutex を使用することにしました。コードは以下のとおりです。

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

3 に答える 3

7

AFAIK MSBuild には、ビルド スクリプトの特定の時点で警告カウントを取得する組み込みサポートがありません。ただし、次の手順に従って、この目標を達成できます。

  1. 警告イベントをリッスンして警告の数をカウントするカスタム ロガーを作成する
  2. [Output] WarningCount プロパティを公開するカスタム タスクを作成する
  3. カスタム タスクは、カスタム ロガーから何らかの方法で警告カウントの値を取得します。

最も難しいステップはステップ 3 です。これにはいくつかのオプションがあり、IPC - Inter Process Communication で自由に検索できます。これを達成する方法の実例に従います。各項目は異なるClass Libraryです。

共有メモリ

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
于 2008-09-30T11:46:49.513 に答える
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 '%~nx1' の正常なビルド。 >> %MrB-BUILDLOG% ) )

于 2008-09-30T10:39:24.357 に答える
1

C# コンパイラ (csc.exe) には /warnaserror スイッチがあり、警告をエラーとして扱い、ビルドに失敗します。これは、.csproj ファイルの設定としても利用できます。Delphiにも同様の能力があると思います。

于 2008-09-30T10:31:24.220 に答える