Partilhar via


Escrever tarefas para o MSBuild

As tarefas estão contidas nos destinos do MSBuild e fornecem o código que é executado durante o processo de compilação. MSBuild inclui uma biblioteca de tarefas típicas, e você também pode criar suas próprias tarefas. Para obter mais informações sobre a biblioteca de tarefas que o MSBuild inclui, consulte Referência de tarefa do MSBuild.

Pré-requisitos

Um projeto do Visual Studio que compila com o MSBuild.

Tarefas

Exemplos de tarefas do MSBuild incluem Copy, 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 .NET que implementa a ITask interface definida no assembly Microsoft.Build.Framework.dll .

Você pode usar uma das seguintes abordagens ao implementar uma tarefa:

  • Implemente a interface ITask diretamente.

  • Derive sua classe da classe auxiliar Task, que é definida no assembly Microsoft.Build.Utilities.dll. Task implementa ITask e fornece implementações padrão de alguns ITask membros. Também é mais fácil efetuar o registo.

Em ambos os casos, você deve adicionar um método à sua classe chamada Execute, que é chamada quando a tarefa é executada. Esse método não usa parâmetros e retorna um valor Boolean: 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, é concluída com êxito e 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 seguinte arquivo de projeto MSBuild executa a tarefa anterior:

<Project>
    <Target Name="MyTarget">
        <SimpleTask />
    </Target>
</Project>

Quando as tarefas são executadas, elas também podem receber entradas do arquivo de projeto se você criar propriedades .NET na classe de tarefa. MSBuild define essas propriedades imediatamente antes de chamar o método Execute da tarefa. Para criar uma propriedade string, use o código de tarefa como o exemplo a seguir:

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 para o valor fornecido.

<Project>
   <Target Name="MyTarget">
      <SimpleTask MyProperty="Value for MyProperty" />
   </Target>
</Project>

Como o MSBuild invoca tarefas

Quando o MSBuild invoca uma tarefa, ele primeiro instancia a classe de tarefa e, em seguida, chama os definidores de propriedades desse objeto para os parâmetros de tarefa que são definidos no elemento de tarefa no arquivo de projeto. Se o elemento task 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 propriedades não será chamado.

Por exemplo, no projeto a seguir, apenas o setter for Input3 é chamado.

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

Uma tarefa não deve depender de nenhuma ordem relativa de invocação do setter de propriedades de parâmetros.

Tipos de parâmetros de tarefa

MSBuild manipula nativamente propriedades do tipo string, boolITaskItem 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 propriedades e itens expandidas, para o tipo de destino string. Se a conversão falhar para qualquer parâmetro de entrada, o MSBuild emitirá um erro e não chamará o método da Execute() tarefa.

Registar tarefas

Para executar uma tarefa, o MSBuild deve saber como localizar e executar o assembly que contém a classe de tarefa. As tarefas são registradas usando o elemento UsingTask (MSBuild).

Se a sua tarefa tiver dependências específicas de tempo de execução, deve direcionar o MSBuild para executar a tarefa num ambiente específico, indicando os atributos Architecture ou Runtime no seu elemento UsingTask. Para obter mais informações, consulte Atributos e parâmetros de tarefa UsingTask.

O arquivo MSBuild Microsoft.Common.tasks é um arquivo de projeto que lista os UsingTask elementos que registram todas as tarefas fornecidas com o MSBuild. Esse arquivo é incluído automaticamente quando o MSBuild cria qualquer projeto. Se uma tarefa registrada em Microsoft.Common.tasks também estiver registrada no arquivo de projeto atual, o arquivo de projeto atual terá precedência, para que você possa substituir uma tarefa padrão por sua própria tarefa de mesmo nome.

Dica

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

Exigir que as propriedades da tarefa sejam definidas

Você pode marcar determinadas propriedades da tarefa como necessárias, portanto, qualquer arquivo de projeto que execute a tarefa deve definir valores para essas propriedades ou a compilação falhará. Aplique 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.

Gerar eventos a partir de uma tarefa

Se sua tarefa derivar da Task classe auxiliar, você poderá usar qualquer um dos seguintes métodos auxiliares na Task classe para gerar eventos que são capturados e exibidos por todos os registradores registrados:

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

Se a sua tarefa implementar ITask diretamente, poderá ainda gerar tais eventos, mas deverá utilizar 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;
    }
}

Empacotar a tarefa

A maneira recomendada de distribuir uma tarefa é em um pacote NuGet. O pacote precisa agrupar todas as dependências. Para obter um tutorial que o orienta na criação de uma tarefa personalizada, consulte Criar um pacote NuGet.

Exemplo 1

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

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

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

using System;
using Microsoft.Build.Framework;

namespace SimpleTask2
{
    public class SimpleTask2: ITask
    {
        //When implementing the ITask interface, it's 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's 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 does its work.
            return true;
        }
    }
}

Exemplo 3

Esta classe C# demonstra uma tarefa que deriva da classe auxiliar Task. A tarefa tem uma propriedade string obrigatória e despoleta um evento que é exibido por todos os loggers registados.

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

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

<Project>
    <UsingTask TaskName="SimpleTask3.SimpleTask3"
        AssemblyFile="SimpleTask3\bin\debug\simpletask3.dll"/>

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