Escrita de tarefas
As tarefas fornecem o código que é executado durante o processo de compilação. As tarefas estão contidas em metas. Uma biblioteca de tarefas típicas está incluída no MSBuild, e você também pode criar suas próprias tarefas. Para obter mais informações sobre a biblioteca de tarefas incluídas no MSBuild, consulte Task reference.
Tarefas
Exemplos de tarefas 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 interface ITask, que é definida no assembly Microsoft.Build.Framework.dll.
Há duas abordagens que você pode usar 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 a interface ITask e fornece implementações padrão de alguns membros da 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 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 e é concluída com êxito (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 executa esta tarefa:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<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 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
para o valor fornecido:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="MyTarget">
<SimpleTask MyProperty="Value for MyProperty" />
</Target>
</Project>
Registar tarefas
Se um projeto vai executar uma tarefa, 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 sua tarefa tiver dependências específicas de tempo de execução, você deve informar o MSBuild que ele deve executar a tarefa em um ambiente específico indicando o Architecture
e/ou Runtime
em seuUsingTask .
O arquivo MSBuild Microsoft.Common.tasks é um arquivo de projeto que contém uma lista de elementos UsingTask
que registram todas as tarefas fornecidas com o MSBuild. Este arquivo é incluído automaticamente ao criar 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 com o 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 seus Microsoft.Common.tasks.
Gerar eventos a partir de uma tarefa
Se sua tarefa derivar da classe auxiliar Task, você poderá usar qualquer um dos seguintes métodos auxiliares na classe Task para gerar eventos que serão capturados e exibidos por qualquer registrador registrado:
public override bool Execute()
{
Log.LogError("messageResource1", "1", "2", "3");
Log.LogWarning("messageResource2");
Log.LogMessage(MessageImportance.High, "messageResource3");
...
}
Se sua tarefa implementa ITask diretamente, você ainda pode gerar esses eventos, mas você 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;
}
}
Exigir que os parâmetros da tarefa sejam definidos
Você pode marcar determinadas propriedades da tarefa como "necessárias" para que qualquer arquivo de projeto que execute a tarefa deva 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.
Como o MSBuild invoca uma tarefa
Ao invocar uma tarefa, o MSBuild primeiro instancia a classe de tarefa e, em seguida, chama os setters de propriedade desse objeto para os parâmetros definidos no elemento de tarefa do 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
<Project>
<Target Name="InvokeCustomTask">
<CustomTask Input1=""
Input2="$(PropertyThatIsNotDefined)"
Input3="value3" />
</Target>
</Project>
apenas o setter para Input3
é chamado.
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
O MSBuild manipula nativamente 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 Execute()
da tarefa.
Empacotando a tarefa
A maneira recomendada de distribuir uma tarefa é em um pacote NuGet. O pacote precisa agrupar todas as dependências. Este tópico é explicado detalhadamente em um tutorial que o orienta na criação de uma tarefa personalizada. Veja Criar um pacote NuGet.
Exemplo 1
Descrição
Esta classe C# a seguir demonstra uma tarefa derivada 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
Esta 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
Esta classe C# demonstra uma tarefa que deriva da classe auxiliar Task. Ele tem uma propriedade string necessária e gera um evento que é exibido por todos os registradores 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>