2008-09-30 14 views
5

は番号が含まれてMSBuildのスクリプトがある場合、DelphiおよびC#プロジェクト、ユニットテストなどMSBuild:警告の数を取得する方法?

問題がある:どのようにビルドをマークするために、警告が提起された場合には失敗した(テスト目的のためではなく、リリースビルド用)?カスタムタスクでLogWarningの代わりにLogErrorを使用すると良い選択肢ではないようです。なぜならビルドは可能な限り多くの警告を報告できるように(実際のエラーまで)テストする必要があるからです(ビルドプロジェクトはCruiseControl.NET )。

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

P.S. Delphiコンパイラの出力はカスタムタスクで処理され、/ warnaserrorはC#で使用できますが、望ましい動作は "すべてビルド、すべての警告を収集する"、 "ビルドに失敗する"最初の警告だけでなく、すべての警告について報告します。

P.P.S.私が警告の数を本当に必要とするのではなく、その存在のフラグだけで、私はシグナリングメカニズムを単純化し、共有メモリの代わりに些細な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++; 
     } 
    } 
} 

答えて

7

私の知る限りのMSBuildの成功ビルドをエコーなし組み込まれているサポートビルドスクリプトの特定のポイントで警告カウントを取得します。ただし、この目標を達成するために、これらの手順を実行することができます:

  1. 警告イベントをリッスンし、警告
  2. の数が[出力]を公開するカスタムタスクを作成してカウントしたカスタムロガーを作成WARNINGCOUNTプロパティ
  3. プロセス間のコミュを -
  4. カスタムタスクは、カスタムロガー

最も困難なステップは、いくつかのオプションがあります。このため、ステップ3であり、あなたが自由にIPCの下でそれらを検索することができますから、何とか警告カウントの値を取得します。これを達成するための実例を以下に示します。各項目は異なるクラスライブラリです。

共有メモリ

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

私は 大規模プロジェクトの一部であったという名前 共有メモリのためのラッパーを作成しました。基本的に、 のシリアライズされた型とオブジェクトグラフを に保存し、共有の メモリから( のクロスプロセスを期待しているように)格納することができます。より大きい プロジェクトが完成するかどうかは別のものです。 ;;)

SampleLogger

警告数を追跡したカスタムロガーを実装します。

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

は、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 
+0

ほとんど同じことを使用しようとしましたが、タスクサブクラスの静的メンバーを使用して警告数を収集しました(動作しませんでした)。共有メモリに関するアイディアをありがとう。 – Abelevich

1

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

+0

申し訳ありませんが、しかし、タスクは、少なくとも、として、すべての警告を収集することです(またはできるだけ多くの場合、実際のエラーまで)、それ以降はビルドに失敗したとマークします。 CruiseControlのビルドを待つのは便利ではありません。最初の警告についてのメッセージを受け取ります。問題を修正し、次のものを待つ。 – Abelevich

+0

とにかく誰が知りたいのですか?Delphi 2009はすべての警告をエラーとして処理しています –

+0

申し訳ありませんが、CC.NETが最初のエラーの後であきらめていることを認識しませんでした。 –

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%の )他( は '%〜NX1'。>>%MRB-BUILDLOG%の ) )

+0

msbuildの解決策ではありませんが、回避策 –