2011-12-29 3 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> 

Ошибка сборки, если цвет синий. Но HandleErrors Target запускается дважды, один раз для каждого цвета. Есть ли способ заставить его работать только для цвета, который был активен во время сбоя?

ответ

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 Из этого можно видеть, что сама цель выполнялась два раза. Это связано с тем, что на цели вы ее украсили Выходы =% (пример. Цвета) .txt. Когда вы используете % (...), вы запускаете пакет MSBuild. Существует два типа дозирования; целевое дозирование, пакетное задание. Целевая группировка - это то, где целая цель выполняется за партию (вот что вы здесь делаете). Задание задач - это выполнение задачи за каждую партию.

У меня есть еще один образец, который есть именно то, что у вас есть, за исключением того, что я добавил дополнительный оператор сообщения внутри объекта Build.

<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 На основании этого мы видим, что цель сборки была выполнена один раз, и произошла ошибка, поэтому она не была выполнена во второй раз, как в предыдущем примере, где не было ошибки. После этого в него попала цель HandleErrors. Внутри этого столкнулся элемент.

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

И сообщение было отправлено регистраторам (обратите внимание, что это было вызвано только один раз). После этого он пришел.

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

Теперь это привело к двум сообщениям. Это связано с тем, что здесь началось запугивание задач. Задача вызывается один раз за уникальную партию% (Example.Color), которая является красной и синей. Таким образом, мы знаем, что цель была вызвана только один раз (когда произошла исходная ошибка), но вы передаете ей весь набор элементов Example.

Если вы хотите узнать, какое значение вызвало ошибку, вам нужно будет отслеживать это в своем целевом объекте Build. Вы можете просто поместить текущий цвет в свойство, а затем ссылаться на него в своей цели HandleErrors. Например, рассмотрим пример-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

Aha! Я пропустил, что делаю Task tasking в Target HandyErrors, ссылаясь на% (Example.Color). И, конечно, настройка собственности делает именно то, что мне нужно. Спасибо за быстрый и удивительно подробный ответ (и за вашу незаменимую книгу :-). –

+0

Несомненно, никаких проблем. –

0

IIUC, ваши HandleErrors будут отдельно упакованы.

Вы использовали бы проблему с ошибкой либо условно, либо безоговорочно. В любом случае вы должны использовать задачу MSBuild для вызова HandleErrors и передать% (Example.Color) в качестве свойства. Что-то вроде:

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

Другой способ может быть, создать свойство в случае ошибки, и использовать его в мишени HandleErrors. Хотя вышеупомянутый подход был бы более чистым.

Смежные вопросы