Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
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. Você não precisa 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 ao arquivo de projeto do MSBuild ou ao arquivo importado, normalmente um .targets arquivo.
Você cria uma tarefa embutida usando uma fábrica de tarefas de código. Para o desenvolvimento atual, use RoslynCodeTaskFactory, não CodeTaskFactory.
CodeTaskFactory só dá suporte a versões do C# até 4.0.
Tarefas embutidas são destinadas como uma conveniência para tarefas pequenas que não exigem dependências complicadas. O suporte de depuração para tarefas embutidas é limitado. É recomendável criar uma tarefa compilada em vez de tarefa embutida quando você deseja escrever um 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 embutidas são compiladas sempre que você cria, para que possa haver um impacto perceptível no desempenho da compilação.
A estrutura de uma tarefa embutida
Uma tarefa embutida é contida por um elemento UsingTask . A tarefa embutida e o elemento que a UsingTask contém normalmente são incluídos em um .targets arquivo e importados para outros arquivos de projeto, conforme necessário. Aqui está uma tarefa embutida básica 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 embutidas que a compila.
O
TaskNameatributo nomeia a tarefa, nesse caso,DoNothing.O
TaskFactoryatributo nomeia a classe que implementa a fábrica de tarefas embutidas.O
AssemblyFileatributo fornece o local da fábrica de tarefas embutidas. Como alternativa, você pode usar oAssemblyNameatributo para especificar o nome totalmente qualificado da classe de fábrica de tarefas embutida, que normalmente está localizada em$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll.
Os elementos restantes da DoNothing tarefa estão vazios e são fornecidos para ilustrar a ordem e a estrutura de uma tarefa embutida. Um exemplo completo é apresentado posteriormente neste artigo.
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 saída, consulte os 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 alguns assemblies que são referenciados transitivamente como dependências, estão disponíveis sem umReference.O
Usingelemento lista os namespaces que você deseja acessar. Esse elemento é equivalente àusingdiretiva em C#. ONamespaceatributo especifica o namespace a ser incluído. Não funciona para colocar umausingdiretiva no código embutido, porque esse código é colocado em um corpo do método, ondeusingas diretivas não são permitidas.
Reference e Using os elementos são independentes de linguagem. Tarefas embutidas podem ser escritas no Visual Basic ou em C#.
Observação
Os elementos contidos pelo Task elemento são específicos para a fábrica de tarefas, nesse caso, a fábrica de tarefas de código.
Elemento code
O último elemento filho a ser exibido 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
TypeforClass, o elemento conterá códigoCodepara uma classe derivada da ITask interface.Se o valor
TypeforMethod, o código definirá uma substituição doExecutemétodo da ITask interface.Se o valor
TypeforFragment, o código definirá o conteúdo doExecutemétodo, mas não a assinatura ou a instruçãoreturn.
O próprio código 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, você pode usar o Source atributo do Code elemento para especificar o local de um arquivo que contém o código para 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 Type padrão 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 TaskName atributo do elemento UsingTask correspondente.
HelloWorld
Aqui está um exemplo de uma tarefa embutida simples. A tarefa HelloWorld exibe "Olá, mundo!" no dispositivo de log de erros padrão, que normalmente é o console do sistema ou a janela 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 invocá-la de um projeto da seguinte maneira.
<Project>
<Import Project="HelloWorld.targets" />
<Target Name="Hello">
<HelloWorld />
</Target>
</Project>
Parâmetros de entrada e saída
Parâmetros de tarefa embutidos são elementos filho de um ParameterGroup elemento. Cada parâmetro usa 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 desses atributos:
-
Requiredé um atributo opcional que éfalsepor padrão. Setrue, 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 de e para 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, o parâmetro deverá 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 necessário.Tallyé um parâmetro de saída do tipo System.Int32.
Se o Code elemento tiver o Type atributo de Fragment ou Method, em seguida, as propriedades serão criadas automaticamente para cada parâmetro. Caso contrário, as propriedades devem ser declaradas explicitamente no código-fonte da tarefa e devem corresponder exatamente às definições de parâmetro.
Depurar uma tarefa embutida
O MSBuild gera um arquivo de origem na tarefa embutida e grava a saída no arquivo de texto com um nome de arquivo GUID na pasta de arquivos 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 cada ocorrência 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 uma 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>