Produção de tarefas

Tarefas fornecem o código que é executado durante o processo de build. Tarefas estão contidas nos destinos. Uma biblioteca de tarefas típicas está incluída no MSBuild e você também pode criar suas próprias tarefas. Para saber mais sobre a biblioteca de tarefas incluída com MSBuild, confira Referência de tarefas.

Tarefas

Exemplos de tarefas incluem Copiar, que copia um ou mais arquivos, MakeDir, que cria um diretório e Csc, que compila arquivos de código-fonte C#. Cada tarefa é implementada como uma classe do .NET que implementa a interface ITask, a qual é definida no assembly Microsoft.Build.Framework.dll.

Há duas abordagens que você pode usar ao implementar uma tarefa:

  • Implemente a interface ITask diretamente.

  • Derive a classe da classe auxiliar, Task, definida no assembly Microsoft.Build.Utilities.dll. Tarefa implementa ITask e fornece implementações padrão de alguns membros do ITask. Além disso, o registro em log é mais fácil.

Em ambos os casos, você deve adicionar à sua classe um método chamado Execute, que é o método que é chamado quando a tarefa é executada. Esse método não usa nenhum parâmetro e retorna um Boolean valor: true se a tarefa foi bem-sucedida ou false se falhou. O exemplo a seguir mostra uma tarefa que não executa nenhuma ação e é concluída com sucesso (retorna true).

using System;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace MyTasks
{
    public class SimpleTask : Task
    {
        public override bool Execute()
        {
            return true;
        }
    }
}

O arquivo de projeto a seguir executa essa tarefa:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <Target Name="MyTarget">
        <SimpleTask />
    </Target>
</Project>

Quando executar tarefas, elas também poderá receber entradas do arquivo de projeto se você criar propriedades .NET na classe task. MSBuild define essas propriedades imediatamente antes de chamar o método de tarefa Execute. Para criar uma propriedade de cadeia de caracteres, use o código da tarefa como:

using System;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace MyTasks
{
    public class SimpleTask : Task
    {
        public override bool Execute()
        {
            return true;
        }

        public string MyProperty { get; set; }
    }
}

O seguinte arquivo de projeto executa essa tarefa e define MyProperty como o valor especificado:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <Target Name="MyTarget">
      <SimpleTask MyProperty="Value for MyProperty" />
   </Target>
</Project>

Tarefas de registro

Se um projeto for executar uma tarefa, o MSBuild deverá saber como localizar e executar o assembly que contém a classe de tarefa. Registre as tarefas usando o elemento UsingTask (MSBuild).

Se sua tarefa tiver dependências específicas de runtime, você deverá informar ao MSBuild que ela deve executar a tarefa em um ambiente específico indicando o Architecture e/ou Runtime em seu UsingTask.

O arquivo MSBuild Microsoft.Common.tasks do UsingTask é um arquivo de projeto que contém uma lista de elementos que registra todas as tarefas que são fornecidas com MSBuild. Esse arquivo é incluído automaticamente na criação de qualquer projeto. Se uma tarefa que está registrada no Microsoft.Common.tasks também estiver registrada no arquivo de projeto atual, o último terá precedência; ou seja, você pode substituir uma tarefa padrão por sua própria tarefa de mesmo nome.

Dica

Você pode ver uma lista das tarefas fornecidas com uma versão específica do MSBuild visualizando o conteúdo de seu Microsoft.Common.tasks.

Gerar eventos de uma tarefa

Se a tarefa deriva da classe auxiliar Task, você pode usar qualquer um dos seguintes métodos auxiliares na classe Task para acionar eventos que serão capturados e exibidos por quaisquer agentes registrados:

public override bool Execute()
{
    Log.LogError("messageResource1", "1", "2", "3");
    Log.LogWarning("messageResource2");
    Log.LogMessage(MessageImportance.High, "messageResource3");
    ...
}

Se a tarefa implementa ITask diretamente, você ainda pode acionar esses eventos, mas deve usar a interface IBuildEngine. O exemplo a seguir mostra uma tarefa que implementa ITask e gera um evento personalizado:

public class SimpleTask : ITask
{
    public IBuildEngine BuildEngine { get; set; }

    public override bool Execute()
    {
        TaskEventArgs taskEvent =
            new TaskEventArgs(BuildEventCategory.Custom,
            BuildEventImportance.High, "Important Message",
           "SimpleTask");
        BuildEngine.LogBuildEvent(taskEvent);
        return true;
    }
}

Parâmetros de tarefa que precisam de configuração

Você pode marcar determinadas propriedades de tarefa como "necessárias" para que qualquer arquivo de projeto que executa a tarefa deve definir valores para essas propriedades ou o build falhará. Aplicar o atributo [Required] à propriedade .NET em sua tarefa da seguinte maneira:

[Required]
public string RequiredProperty { get; set; }

O atributo [Required] é definido por RequiredAttribute no namespace Microsoft.Build.Framework.

Como o MSBuild invoca uma tarefa

Ao invocar uma tarefa, o MSBuild cria uma instância da classe de tarefa e, em seguida, chama os setters de propriedade desse objeto para parâmetros de tarefa definidos no elemento de tarefa no arquivo de projeto. Se o elemento de tarefa não especificar um parâmetro ou se a expressão especificada no elemento for avaliada como uma cadeia de caracteres vazia, o setter de propriedade não será chamado.

Por exemplo, no projeto

<Project>
 <Target Name="InvokeCustomTask">
  <CustomTask Input1=""
              Input2="$(PropertyThatIsNotDefined)"
              Input3="value3" />
 </Target>
</Project>

somente o setter para Input3 é chamado.

Uma tarefa não deve depender de nenhuma ordem relativa de invocação de setter de propriedade de parâmetro.

Os tipos de parâmetro.

O MSBuild manipula nativamente as propriedades do tipo string, bool, ITaskItem e ITaskItem[]. Se uma tarefa aceitar um parâmetro de um tipo diferente, o MSBuild invocará ChangeType para converter de string (com todas as referências de propriedade e item expandidas) para o tipo de destino. Se a conversão falhar para qualquer parâmetro de entrada, o MSBuild emitirá um erro e não chamará o método da tarefa Execute().

Exemplo 1

Descrição

Essa classe C# a seguir demonstra uma tarefa derivando da classe auxiliar Task. Esta tarefa retorna true, indicando que foi bem-sucedida.

Código

using System;
using Microsoft.Build.Utilities;

namespace SimpleTask1
{
    public class SimpleTask1: Task
    {
        public override bool Execute()
        {
            // This is where the task would presumably do its work.
            return true;
        }
    }
}

Exemplo 2

Descrição

Essa classe C# a seguir demonstra uma tarefa implementando a interface ITask. Esta tarefa retorna true, indicando que foi bem-sucedida.

Código

using System;
using Microsoft.Build.Framework;

namespace SimpleTask2
{
    public class SimpleTask2: ITask
    {
        //When implementing the ITask interface, it is necessary to
        //implement a BuildEngine property of type
        //Microsoft.Build.Framework.IBuildEngine. This is done for
        //you if you derive from the Task class.
        public IBuildEngine BuildEngine { get; set; }

        // When implementing the ITask interface, it is necessary to
        // implement a HostObject property of type object.
        // This is done for you if you derive from the Task class.
        public object HostObject { get; set; }

        public bool Execute()
        {
            // This is where the task would presumably do its work.
            return true;
        }
    }
}

Exemplo 3

Descrição

Essa classe C# demonstra uma tarefa que deriva da classe auxiliar Task. Tem uma propriedade de cadeia de caracteres obrigatória e gera um evento que é exibido por todos os agentes registrados.

Código

using System;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace SimpleTask3
{
    public class SimpleTask3 : Task
    {
        private string myProperty;

        // The [Required] attribute indicates a required property.
        // If a project file invokes this task without passing a value
        // to this property, the build will fail immediately.
        [Required]
        public string MyProperty
        {
            get
            {
                return myProperty;
            }
            set
            {
                myProperty = value;
            }
        }

        public override bool Execute()
        {
            // Log a high-importance comment
            Log.LogMessage(MessageImportance.High,
                "The task was passed \"" + myProperty + "\".");
            return true;
        }
    }
}

Exemplo 4

Descrição

O exemplo a seguir mostra um arquivo de projeto invocando a tarefa de exemplo anterior, SimpleTask3.

Código

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <UsingTask TaskName="SimpleTask3.SimpleTask3"
        AssemblyFile="SimpleTask3\bin\debug\simpletask3.dll"/>

    <Target Name="MyTarget">
        <SimpleTask3 MyProperty="Hello!"/>
    </Target>
</Project>