2011-12-29 28 views
4

我正在使用批處理作爲目標,我希望能夠執行特定於發生錯誤的迭代的OnError清理。這是一個完全通用的示例:如何在msbuild中使用目標批處理時處理錯誤?

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" DefaultTargets="Build"> 

<ItemGroup> 
    <Example Include="Item1"> 
     <Color>Blue</Color> 
    </Example> 
    <Example Include="Item2"> 
     <Color>Red</Color> 
    </Example> 
</ItemGroup> 

<Target Name="Build" 
    Inputs="@(Example)" 
    Outputs="%(Example.Color).txt"> 
    <Error Text="An error occurred during %(Example.Color)" /> 
    <OnError ExecuteTargets="HandleErrors" /> 
</Target> 

<Target Name="HandleErrors"> 
    <Message Text="Do some cleanup about %(Example.Color)" Importance="high" /> 
</Target> 

</Project> 

當Color爲藍色時,生成目標失敗。但HandleErrors目標運行兩次,每個顏色一次。有沒有辦法讓它只運行在故障期間處於活動狀態的顏色?

回答

9

我覺得目前還不清楚究竟是在這裏發生了什麼。在我們回答你的問題之前,讓我們通過修改你的proj文件來看看發生了什麼。

下面是一個修改後的文件sample-no-error.proj,其中我刪除了錯誤部分,並在其中添加了一個Message任務。

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" DefaultTargets="Build"> 
    <ItemGroup> 
     <Example Include="Item1"> 
      <Color>Blue</Color> 
     </Example> 
     <Example Include="Item2"> 
      <Color>Red</Color> 
     </Example> 
    </ItemGroup> 

    <Target Name="Build" 
     Inputs="@(Example)" 
     Outputs="%(Example.Color).txt"> 

    <Message Text="Inside of Build, color: %(Example.Color)" /> 
    </Target> 
</Project> 

當我從命令行構建這個結果是。 enter image description here 由此我們可以看到目標本身被執行了兩次。這是因爲在目標上你用輸出=%(Example.Color).txt來裝飾它。當你使用%(...)你開始MSBuild批處理。有兩種配料方式;目標配料,任務配料。目標批處理是每個批次執行一個完整目標的地方(這是您在這裏執行的操作)。任務批處理是每個批次執行任務的地方。

我已經得到了另一個示例,除了我在Build目標中添加了一條額外的Message語句外,

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" DefaultTargets="Build"> 
    <ItemGroup> 
     <Example Include="Item1"> 
      <Color>Blue</Color> 
     </Example> 
     <Example Include="Item2"> 
      <Color>Red</Color> 
     </Example> 
    </ItemGroup> 

    <Target Name="Build" 
     Inputs="@(Example)" 
     Outputs="%(Example.Color).txt"> 

    <Message Text="Inside of Build, color: %(Example.Color)" /> 

    <Error Text="An error occurred during %(Example.Color)" /> 
    <OnError ExecuteTargets="HandleErrors" /> 
    </Target> 

    <Target Name="HandleErrors"> 
    <Message Text="Inside of the HandleErrors target" /> 
    <Message Text="Do some cleanup about %(Example.Color)" Importance="high" /> 
    </Target> 
</Project> 

當我建立這個結果是。 enter image description here 基於此,我們可以看到Build目標被執行了一次,並且發生了一個錯誤,所以它沒有像上一個沒有錯誤的例子那樣第二次執行。之後,HandleErrors目標被踢入。在它內部遇到了該元素。

<Message Text="Inside of the HandleErrors target" /> 

並且該消息被髮送到記錄器(注意這只是被調用一次)。之後,它來了。

<Message Text="Do some cleanup about %(Example.Color)" Importance="high" /> 

現在這產生了兩條消息語句。這是因爲任務批量已經開始在這裏啓動。每個唯一的批量爲(紅色和藍色)的%(Example.Color)會調用該任務。所以我們知道目標只被調用一次(發生原始錯誤的地方),但是您將整個示例項目集傳遞給它。

如果你想知道哪個值產生了錯誤,你必須跟蹤你的構建目標。您可以將當前顏色放置在屬性中,然後將其引用到HandleErrors目標中。例如,看看下面的sample-id-errors.proj。

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" DefaultTargets="Build"> 
    <ItemGroup> 
     <Example Include="Item1"> 
      <Color>Blue</Color> 
     </Example> 
     <Example Include="Item2"> 
      <Color>Red</Color> 
     </Example> 
    </ItemGroup> 

    <Target Name="Build" 
     Inputs="@(Example)" 
     Outputs="%(Example.Color).txt"> 
    <PropertyGroup> 
     <_LastUsedColor>%(Example.Color)</_LastUsedColor> 
    </PropertyGroup> 

    <Message Text="Inside of Build, color: %(Example.Color)" /> 

    <Error Text="An error occurred during %(Example.Color)" /> 
    <OnError ExecuteTargets="HandleErrors" /> 
    </Target> 

    <Target Name="HandleErrors"> 
    <Message Text="Inside of the HandleErrors target" /> 
    <Message Text="The color which caused the error was: $(_LastUsedColor)"/> 
    </Target> 
</Project> 

在這裏你可以看到生成的裏面如果出現錯誤,我只是使用相同的屬性,它的目標內我只是設置的值的_LastUsedColor屬性,然後。當我建立這個文件的結果是。

enter image description here

我覺得這是你要完成的任務。如果你不知道它是如何工作的,那麼批次就相當混亂。我在網上有一堆關於批次的資源http://sedotech.com/resources#Batching.

+0

啊哈!我沒有錯過我在HandleErrors目標中通過引用%(Example.Color)來執行任務批處理。當然,設置一個屬性只是我所需要的。感謝您的快速和奇妙的詳細迴應(併爲您的不可缺少的書:-)。 – 2011-12-29 21:48:57

+0

當然沒問題。 – 2011-12-29 23:03:11

0

IIUC,您的HandleErrors將分開批處理。

您將有條件地或無條件地使用錯誤任務。無論哪種情況,您都應該能夠使用MSBuild任務來調用HandleErrors並將%(Example.Color)作爲屬性傳遞。例如:

<MSBuild Targets="HandleErrors" Properties="ErrorColor=%(Example.Color)" /> 

另一種方式可能是,創建屬性以防止出現錯誤,並在HandleErrors目標中使用該屬性。雖然上述方法會更清潔。