2008-09-30 38 views
5

有一個MSBuild腳本,其中包括數字,如果德爾福和C#項目,單元測試等MSBuild:如何獲取引發警告的次數?

問題是:如何標記構建失敗,如果警告提出(測試目的,而不是發佈版本)?在自定義任務中使用LogError而不是LogWarning似乎不是一個好的選擇,因爲構建應儘可能多地進行測試(直到真正的錯誤)才能在一段時間內報告儘可能多的警告(構建項目在CruiseControl.NET中使用)。

可能是,解決方案是創建我自己的記錄器,將存儲警告標誌裏面,但我不能找到在構建結束時是否有讀取此標誌的方法?

P.S.在收到警告(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++; 
     } 
    } 
} 

回答

7

AFAIK的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 
1

C#編譯器(csc.exe)有一個/ warnaserror將交換機將警告視爲錯誤和失敗的構建。這也可以作爲.csproj文件中的設置使用。我認爲德爾福具有類似的能力。

+0

抱歉,該任務是收集所有的警告(或者,至少,作爲儘可能多,直到真正的錯誤),然後將構建標記爲失敗。等待CruiseControl構建並不方便;接收關於第一警告的消息;解決問題並等待下一個問題。 – Abelevich 2008-09-30 10:41:29

+0

反正誰想知道:Delphi 2009有一個對待所有警告的錯誤 – 2008-09-30 11:34:26

+0

對不起,沒想到CC.NET放棄了第一個錯誤之後。 – 2008-09-30 12:14:20

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% ) )