Tarefas embutidas do MSBuild
As tarefas do MSBuild normalmente são criadas ao compilar uma classe que implementa a interface ITask. Para obter mais informações, consulte Tarefas.
A partir do .NET Framework versão 4, você pode criar tarefas embutidas no arquivo de projeto. Você não precisa criar um assembly separado para hospedar a tarefa. Isso facilita o controle do código-fonte e a implantação da tarefa. O código-fonte é integrado ao script.
No MSBuild 15.8, o RoslynCodeTaskFactory foi adicionado. Para o desenvolvimento atual, use o RoslynCodeTaskFactory, não o CodeTaskFactory. O CodeTaskFactory só dá suporte a versões em C# até 4.0.
A estrutura de uma tarefa embutida
Uma tarefa em linha é contida por um elemento UsingTask. Normalmente, a tarefa embutida e o elemento UsingTask
que a contém são incluídos em um arquivo .targets e importados para outros arquivos de projeto conforme a necessidade. Veja uma tarefa básica em linha. Observe que ela não faz nada.
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- This simple inline task does nothing. -->
<UsingTask
TaskName="DoNothing"
TaskFactory="CodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" >
<ParameterGroup />
<Task>
<Reference Include="" />
<Using Namespace="" />
<Code Type="Fragment" Language="cs">
</Code>
</Task>
</UsingTask>
</Project>
O elemento UsingTask
no exemplo tem três atributos que descrevem a tarefa e a fábrica de tarefas em linha que a compila.
O atributo
TaskName
nomeia a tarefa, neste caso,DoNothing
.O atributo
TaskFactory
nomeia a classe que implementa a fábrica de tarefas em linha.O atributo
AssemblyFile
fornece o local da fábrica de tarefas em linha. Como alternativa, você pode usar o atributoAssemblyName
para especificar o nome totalmente qualificado da classe do alocador de tarefas embutido, que normalmente fica em$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll
.
Os elementos restantes da tarefa DoNothing
estão vazios w são fornecidos para ilustrar a ordem e a estrutura de uma tarefa em linha. Um exemplo mais robusto será apresentado posteriormente neste tópico.
O elemento
ParameterGroup
é opcional. Quando especificado, ele declara os parâmetros para a tarefa. Para obter mais informações sobre parâmetros de entrada e de saída, confira Parâmetros de entrada e de saída mais adiante neste tópico.O elemento
Task
descreve e contém o código de origem da tarefa.O elemento
Reference
especifica referências aos assemblies do .NET que você está usando em seu código. Isso equivale à adição de uma referência a um projeto no Visual Studio. O atributoInclude
especifica o caminho do assembly referenciado.O elemento
Using
lista os namespaces que você deseja acessar. Isso se assemelha à instruçãoUsing
no Visual C#. O atributoNamespace
especifica o namespace a ser incluído.
Os elementos Reference
e Using
independem da linguagem. As tarefas em linha podem ser escritas em qualquer idioma com suporte do CodeDom .NET, por exemplo, Visual Basic ou Visual C#.
Observação
Os elementos contidos pelo elemento Task
são específicos da fábrica de tarefas, nesse caso, a fábrica de tarefas de código.
Elemento de código
O último elemento filho a aparecer no elemento Task
é o elemento Code
. O elemento Code
contém ou localiza o código que você deseja compilar em uma tarefa. O que é colocado no elemento Code
depende de como você deseja escrever a tarefa.
O atributo Language
especifica a linguagem em que seu código é escrito. Os valores aceitáveis são cs
para C#, vb
para Visual Basic.
O atributo Type
especifica o tipo de código que é encontrado no elemento Code
.
Se o valor de
Type
éClass
, o elementoCode
contém o código para uma classe que deriva da interface ITask.Se o valor de
Type
éMethod
, o código define uma substituição do métodoExecute
da interface ITask.Se o valor de
Type
éFragment
, o código define o conteúdo do métodoExecute
, mas não a assinatura ou a instruçãoreturn
.
O próprio código normalmente aparece entre um marcador <![CDATA[
e um marcador ]]>
. Como o código está em uma seção CDATA, você não precisa se preocupar com o escape de caracteres reservados, por exemplo, "<" ou ">".
Como alternativa, você pode usar o atributo Source
do elemento Code
para especificar o local de um arquivo que contém o código da sua tarefa. O código no arquivo de origem deve ser do tipo especificado pelo atributo Type
. Se o atributo Source
estiver presente, o valor padrão de Type
será Class
. Se Source
é não estiver presente, o valor padrão será Fragment
.
Observação
Ao definir a classe de tarefa no arquivo de origem, o nome da classe deve concordar com o atributo TaskName
do elemento UsingTask correspondente.
HelloWorld
Vejamos uma tarefa em linha mais robusta. A tarefa HelloWorld exibe "Hello, world!" no dispositivo padrão de registro de erros em log, que normalmente é o console do sistema ou a janela Saída do Visual Studio. O elemento Reference
no exemplo é incluído apenas para ilustração.
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- This simple inline task displays "Hello, world!" -->
<UsingTask
TaskName="HelloWorld"
TaskFactory="CodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" >
<ParameterGroup />
<Task>
<Reference Include="System.Xml"/>
<Using Namespace="System"/>
<Using Namespace="System.IO"/>
<Code Type="Fragment" Language="cs">
<![CDATA[
// Display "Hello, world!"
Log.LogError("Hello, world!");
]]>
</Code>
</Task>
</UsingTask>
</Project>
Salve a tarefa HelloWorld em um arquivo chamado HelloWorld.targets e, em seguida, invoque-o em um projeto conforme mostrado a seguir.
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="HelloWorld.targets" />
<Target Name="Hello">
<HelloWorld />
</Target>
</Project>
Parâmetros de entrada e de saída
Os parâmetros de tarefa em linha são elementos filhos de um elemento ParameterGroup
. Cada parâmetro tem o nome do elemento que o define. O código a seguir define o parâmetro Text
.
<ParameterGroup>
<Text />
</ParameterGroup>
Os parâmetros podem ter um ou mais destes atributos:
Required
é um atributo opcional que éfalse
por padrão. Setrue
, o parâmetro é necessário e deve receber um valor antes de chamar a tarefa.ParameterType
é um atributo opcional que éSystem.String
por padrão. Ele pode ser definido como qualquer tipo totalmente qualificado que seja um item ou um valor que pode ser convertido em uma cadeia de caracteres usando System.Convert.ChangeType. (Em outras palavras, qualquer tipo que possa ser passado de e para uma tarefa externa.)Output
é um atributo opcional que éfalse
por padrão. Setrue
, o parâmetro deve receber um valor antes de retornar do método Execute.
Por exemplo,
<ParameterGroup>
<Expression Required="true" />
<Files ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
<Tally ParameterType="System.Int32" Output="true" />
</ParameterGroup>
define esses três parâmetros:
Expression
é um parâmetro de entrada obrigatório do tipo System.String.Files
é um parâmetro de entrada de lista do item obrigatório.Tally
é um parâmetro de saída do tipo System.Int32.
Se o elemento Code
tem o atributo Type
de Fragment
ou Method
, as propriedades são criadas automaticamente para cada parâmetro. Caso contrário, as propriedades devem ser declaradas explicitamente no código-fonte da tarefa e devem coincidir exatamente com suas definições de parâmetro.
Exemplo
A tarefa em linha a seguir substitui todas as ocorrências de um token no arquivo especificado pelo valor especificado.
<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' ToolsVersion="15.0">
<UsingTask TaskName="TokenReplace" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
<ParameterGroup>
<Path ParameterType="System.String" Required="true" />
<Token ParameterType="System.String" Required="true" />
<Replacement ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Code Type="Fragment" Language="cs"><![CDATA[
string content = File.ReadAllText(Path);
content = content.Replace(Token, Replacement);
File.WriteAllText(Path, content);
]]></Code>
</Task>
</UsingTask>
<Target Name='Demo' >
<TokenReplace Path="C:\Project\Target.config" Token="$MyToken$" Replacement="MyValue"/>
</Target>
</Project>