Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
As tarefas do MSBuild normalmente são criadas compilando uma classe que implementa a ITask interface. Para obter mais informações, consulte Tarefas.
Quando quiser evitar a sobrecarga de criar uma tarefa compilada, você pode criar uma tarefa embutida no arquivo de projeto ou em um arquivo importado. Não é necessário criar um assembly separado para hospedar a tarefa. O uso de uma tarefa embutida facilita o controle do código-fonte e a implantação da tarefa. O código-fonte é integrado no arquivo de projeto MSBuild ou arquivo importado, normalmente um .targets arquivo.
Você cria uma tarefa embutida usando uma fábrica de tarefas de código. Para o desenvolvimento atual, certifique-se de usar RoslynCodeTaskFactory, não CodeTaskFactory.
CodeTaskFactory suporta apenas versões C# até 4.0.
As tarefas em linha destinam-se a ser uma conveniência para pequenas tarefas que não exigem dependências complicadas. O suporte de depuração para tarefas em linha é limitado. É recomendável criar uma tarefa compilada em vez de uma tarefa embutida quando você deseja escrever código mais complexo, fazer referência a um pacote NuGet, executar ferramentas externas ou executar operações que possam produzir condições de erro. Além disso, as tarefas em linha são compiladas sempre que o build é criado, podendo haver um impacto notável no desempenho do build.
A estrutura de uma tarefa embutida
Uma tarefa embutida é contida por um elemento UsingTask . A tarefa embutida e o elemento UsingTask que a contém são normalmente incluídos num ficheiro .targets e importados para outros ficheiros de projeto, conforme necessário. Aqui está uma tarefa básica embutida que não faz nada, mas ilustra a sintaxe:
<!-- This simple inline task does nothing. -->
<UsingTask
TaskName="DoNothing"
TaskFactory="RoslynCodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" >
<ParameterGroup />
<Task>
<Reference Include="" />
<Using Namespace="" />
<Code Type="Fragment" Language="cs">
</Code>
</Task>
</UsingTask>
O UsingTask elemento no exemplo tem três atributos que descrevem a tarefa e a fábrica de tarefas embutida que a compila.
O
TaskNameatributo nomeia a tarefa, neste caso,DoNothing.O
TaskFactoryatributo nomeia a classe que implementa a fábrica de tarefas embutidas.O
AssemblyFileatributo fornece a localização da fábrica de tarefas inline. Como alternativa, você pode usar oAssemblyNameatributo para especificar o nome totalmente qualificado da classe de fábrica de tarefas embutidas, que normalmente está localizada em$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll.
Os elementos restantes da tarefa DoNothing estão vazios e são fornecidos para ilustrar a ordem e a estrutura de uma tarefa em linha. Um exemplo completo é apresentado mais adiante neste artigo.
O
ParameterGroupelemento é opcional. Quando especificado, ele declara os parâmetros para a tarefa. Para obter mais informações sobre parâmetros de entrada e saída, consulte Parâmetros de entrada e saída mais adiante neste artigo.O
Taskelemento descreve e contém o código-fonte da tarefa.O
Referenceelemento especifica referências aos assemblies .NET que você está usando em seu código. Usar esse elemento é equivalente a adicionar uma referência a um projeto no Visual Studio. OIncludeatributo especifica o caminho do assembly referenciado. Assemblies em mscorlib, .NET Standard, Microsoft.Build.Framework e Microsoft.Build.Utilities.Core, bem como algumas assemblies que são referenciadas transitivamente como dependências, estão disponíveis sem umReference.O
Usingelemento lista os namespaces que você deseja acessar. Este elemento é equivalente àusingdiretiva em C#. ONamespaceatributo especifica o namespace a ser incluído. Não funciona colocar umausingdiretiva no código inline, porque esse código é colocado no corpo de um método, onde as diretivasusingnão são permitidas.
Reference e Using são elementos agnósticos em relação à linguagem. As tarefas embutidas podem ser escritas em Visual Basic ou C#.
Observação
Os elementos contidos pelo Task elemento são específicos para a fábrica de tarefas, neste caso, a fábrica de tarefas de código.
Elemento de código
O último elemento filho a aparecer dentro do Task elemento é o Code elemento . O Code elemento contém ou localiza o código que você deseja que seja compilado em uma tarefa. O que você coloca no Code elemento depende de como você deseja escrever a tarefa.
O Language atributo especifica o idioma no qual o código é escrito. Os valores aceitáveis são cs para C#, vb para Visual Basic.
O Type atributo especifica o tipo de código encontrado no Code elemento .
Se o valor de
TypeéClass, então oCodeelemento contém código para uma classe que deriva da ITask interface.Se o valor de
TypeéMethod, então o código define uma substituição doExecutemétodo da ITask interface.Se o valor de
TypeéFragment, então o código define oExecuteconteúdo do método, mas não a assinatura ou areturninstrução.
O código em si normalmente aparece entre um <![CDATA[ marcador e um ]]> marcador. Como o código está em uma seção CDATA, você não precisa se preocupar em escapar de caracteres reservados, por exemplo, "<" ou ">".
Como alternativa, pode usar o atributo Source do elemento Code para especificar a localização 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 Type atributo. Se o Source atributo estiver presente, o valor padrão de Type é 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 TaskName atributo do elemento UsingTask correspondente.
HelloWorld
Aqui está um exemplo de uma tarefa inline simples. A tarefa HelloWorld exibe "Olá, mundo!" no dispositivo de log de erros padrão, que normalmente é o console do sistema ou a janela de saída do Visual Studio.
<Project>
<!-- This simple inline task displays "Hello, world!" -->
<UsingTask
TaskName="HelloWorld"
TaskFactory="RoslynCodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" >
<ParameterGroup />
<Task>
<Using Namespace="System"/>
<Using Namespace="System.IO"/>
<Code Type="Fragment" Language="cs">
<![CDATA[
// Display "Hello, world!"
Log.LogError("Hello, world!");
]]>
</Code>
</Task>
</UsingTask>
</Project>
Você pode salvar a tarefa HelloWorld em um arquivo chamado HelloWorld.targets e, em seguida, invocá-la a partir de um projeto da seguinte maneira.
<Project>
<Import Project="HelloWorld.targets" />
<Target Name="Hello">
<HelloWorld />
</Target>
</Project>
Parâmetros de entrada e saída
Os parâmetros de tarefa embutidos são elementos filho de um ParameterGroup elemento. Cada parâmetro leva 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 éfalsepor padrão. Setrue, então o parâmetro é necessário e deve receber um valor antes de chamar a tarefa. -
ParameterTypeé um atributo opcional que éSystem.Stringpor padrão. Ele pode ser definido como qualquer tipo totalmente qualificado que seja um item ou um valor que possa ser convertido para e de uma cadeia de caracteres usando ChangeType. (Em outras palavras, qualquer tipo que possa ser passado de e para uma tarefa externa.) -
Outputé um atributo opcional que éfalsepor padrão. Setrue, então 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 estes três parâmetros:
Expressioné um parâmetro de entrada necessário do tipo System.String.Filesé um parâmetro de entrada de lista de itens obrigatório.Tallyé um parâmetro de saída do tipo System.Int32.
Se o Code elemento tiver o Type atributo de Fragment ou Method, as propriedades serão criadas automaticamente para cada parâmetro. Caso contrário, as propriedades devem ser explicitamente declaradas no código-fonte da tarefa e devem corresponder exatamente às suas definições de parâmetro.
Depurar uma tarefa embutida
MSBuild gera um arquivo de origem da tarefa embutida e grava a saída num ficheiro de texto com um nome de ficheiro GUID na pasta de ficheiros temporários, AppData\Local\Temp\MSBuildTemp. A saída é normalmente excluída, mas para preservar esse arquivo de saída, você pode definir a variável MSBUILDLOGCODETASKFACTORYOUTPUT de ambiente como 1.
Exemplo 1
A tarefa embutida a seguir substitui todas as ocorrências de um token no arquivo fornecido pelo valor fornecido.
<Project>
<UsingTask TaskName="TokenReplace" TaskFactory="RoslynCodeTaskFactory" 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="Target.config" Token="$MyToken$" Replacement="MyValue"/>
</Target>
</Project>
Exemplo 2
A tarefa embutida a seguir gera saída serializada. Este exemplo mostra o uso de um parâmetro de saída e uma referência.
<Project>
<PropertyGroup>
<RoslynCodeTaskFactoryAssembly Condition="$(RoslynCodeTaskFactoryAssembly) == ''">$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll</RoslynCodeTaskFactoryAssembly>
</PropertyGroup>
<UsingTask
TaskName="MyInlineTask"
TaskFactory="RoslynCodeTaskFactory"
AssemblyFile="$(RoslynCodeTaskFactoryAssembly)">
<ParameterGroup>
<Input ParameterType="System.String" Required="true" />
<Output ParameterType="System.String" Output="true" />
</ParameterGroup>
<Task>
<Reference Include="System.Text.Json" /> <!-- Reference an assembly -->
<Using Namespace="System.Text.Json" /> <!-- Use a namespace -->
<Code Type="Fragment" Language="cs">
<![CDATA[
Output = JsonSerializer.Serialize(new { Message = Input });
]]>
</Code>
</Task>
</UsingTask>
<Target Name="RunInlineTask">
<MyInlineTask Input="Hello, Roslyn!" >
<Output TaskParameter="Output" PropertyName="SerializedOutput" />
</MyInlineTask>
<Message Text="Serialized Output: $(SerializedOutput)" />
</Target>
</Project>