Встроенные задачи MSBuildMSBuild inline tasks

Задачи MSBuild обычно создаются путем компиляции класса, реализующего интерфейс ITask.MSBuild tasks are typically created by compiling a class that implements the ITask interface. Дополнительные сведения см. в разделе Задачи.For more information, see Tasks.

Начиная с версии 4 .NET Framework, вы можете создавать встроенные задачи в файле проекта.Starting in .NET Framework version 4, you can create tasks inline in the project file. Для размещения задачи не нужно создавать отдельную сборку.You do not have to create a separate assembly to host the task. Это упрощает как отслеживание исходного кода, так и развертывание задачи.This makes it easier to keep track of source code and easier to deploy the task. Исходный код встроен в скрипт.The source code is integrated into the script.

В MSBuild 15.8 был добавлен RoslynCodeTaskFactory, позволяющий создавать кроссплатформенные встроенные задачи .NET Standard.In MSBuild 15.8, the RoslynCodeTaskFactory was added which can create .NET Standard cross-platform inline tasks. Если вам нужно использовать встроенные задачи в .NET Core, следует использовать RoslynCodeTaskFactory.If you need to use inline tasks on .NET Core, you must use the RoslynCodeTaskFactory.

Структура встроенной задачиThe structure of an inline task

Элемент UsingTask содержит встроенную задачу.An inline task is contained by a UsingTask element. Встроенная задача и содержащий ее элемент UsingTask обычно включены в TARGETS -файл и при необходимости импортируются в другие файлы проекта.The inline task and the UsingTask element that contains it are typically included in a .targets file and imported into other project files as required. Ниже представлен пример обычной встроенной задачи.Here is a basic inline task. Обратите внимание, что в нем не предусмотрено выполнение каких-либо действий.Notice that it does nothing.

<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>

Элемент UsingTask в примере включает три атрибута, описывающих задачу и фабрику встроенной задачи, компилирующую ее.The UsingTask element in the example has three attributes that describe the task and the inline task factory that compiles it.

  • Атрибут TaskName содержит имя задачи. В примере используется имя — DoNothing.The TaskName attribute names the task, in this case, DoNothing.

  • Атрибут TaskFactory содержит класс, реализующий фабрику встроенной задачи.The TaskFactory attribute names the class that implements the inline task factory.

  • Атрибут AssemblyFile включает расположение фабрики встроенной задачи.The AssemblyFile attribute gives the location of the inline task factory. Вы также можете использовать атрибут AssemblyName для указания полного имени класса фабрики встроенной задачи, который обычно расположен в $(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll.Alternatively, you can use the AssemblyName attribute to specify the fully qualified name of the inline task factory class, which is typically located in $(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll.

Остальные элементы задачи DoNothing пусты и приведены, чтобы показать порядок и структуру встроенной задачи.The remaining elements of the DoNothing task are empty and are provided to illustrate the order and structure of an inline task. Более сложный пример представлен в этой статье далее.A more robust example is presented later in this topic.

  • Элемент ParameterGroup является необязательным.The ParameterGroup element is optional. Если он все же используется, его функция заключается в указании параметров задачи.When specified, it declares the parameters for the task. Дополнительные сведения о входных и выходных параметрах см. в разделе Входные и выходные параметры ниже.For more information about input and output parameters, see Input and output parameters later in this topic.

  • Элемент Task содержит исходный код задачи и описывает его.The Task element describes and contains the task source code.

  • Элемент Reference указывает ссылки на сборки .NET, используемые в коде.The Reference element specifies references to the .NET assemblies that you are using in your code. Это эквивалентно добавлению ссылки в проект в Visual Studio.This is equivalent to adding a reference to a project in Visual Studio. Атрибут Include задает путь к сборке, на которую указывает ссылка.The Include attribute specifies the path of the referenced assembly.

  • Элемент Using необходим для вывода списка пространств имен, к которым нужно получить доступ.The Using element lists the namespaces that you want to access. Он похож на оператор Using в Visual C#.This resembles the Using statement in Visual C#. Атрибут Namespace указывает пространство имен, которое нужно включить.The Namespace attribute specifies the namespace to include.

Элементы Reference и Using подходят для любого языка.Reference and Using elements are language-agnostic. Встроенные задачи можно написать на любом из поддерживаемых языков .NET CodeDom, например Visual Basic или Visual C#.Inline tasks can be written in any one of the supported .NET CodeDom languages, for example, Visual Basic or Visual C#.

Примечание

Элементы, содержащиеся в элементе Task, характерны для фабрики задачи, в этом случае для фабрики кода задачи.Elements contained by the Task element are specific to the task factory, in this case, the code task factory.

Code, элементCode element

Последний дочерний элемент в элементе Task — Code.The last child element to appear within the Task element is the Code element. Элемент Code содержит код, который нужно скомпилировать в задачу, или определяет его местонахождение.The Code element contains or locates the code that you want to be compiled into a task. Содержимое в элементе Code зависит от того, каким образом вы хотите написать задачу.What you put in the Code element depends on how you want to write the task.

Атрибут Language указывает язык, на котором написан код.The Language attribute specifies the language in which your code is written. Допустимые значения: cs для C# и vb для Visual Basic.Acceptable values are cs for C#, vb for Visual Basic.

Атрибут Type указывает тип кода, находящийся в элементе Code.The Type attribute specifies the type of code that is found in the Code element.

  • Если значением атрибута Type является Class, элемент Code содержит код для класса, производного от интерфейса ITask.If the value of Type is Class, then the Code element contains code for a class that derives from the ITask interface.

  • Если значением атрибута Type является Method, код определяет переопределение метода Execute интерфейса ITask.If the value of Type is Method, then the code defines an override of the Execute method of the ITask interface.

  • Если значением атрибута Type является Fragment, тогда код определяет содержимое метода Execute, а не сигнатуру или оператор return.If the value of Type is Fragment, then the code defines the contents of the Execute method, but not the signature or the return statement.

Сам код отображается, как правило, между метками <![CDATA[ и ]]>.The code itself typically appears between a <![CDATA[ marker and a ]]> marker. Так как код размещается в разделе CDATA, вам не нужно беспокоиться об экранировании зарезервированных знаков, например <" or ">.Because the code is in a CDATA section, you do not have to worry about escaping reserved characters, for example, "<" or ">".

Вы также можете использовать атрибут Source элемента Code, чтобы указать расположение файла, содержащего код для задачи.Alternatively, you can use the Source attribute of the Code element to specify the location of a file that contains the code for your task. Код в исходном файле должен иметь тип, заданный атрибутом Type.The code in the source file must be of the type that is specified by the Type attribute. Если есть атрибут Source, тогда по умолчанию значением атрибута Type является Class.If the Source attribute is present, the default value of Type is Class. Если атрибут Source отсутствует, значением по умолчанию будет Fragment.If Source is not present, the default value is Fragment.

Примечание

При определении класса задачи в исходном файле имя класса должно быть согласовано с атрибутом TaskName соответствующего элемента UsingTask.When defining the task class in the source file, the class name must agree with the TaskName attribute of the corresponding UsingTask element.

HelloWorldHelloWorld

Рассмотрим более сложную встроенную задачу.Here is a more robust inline task. Задача HelloWorld отображает приветствие "Hello, world!".The HelloWorld task displays "Hello, world!" Оно отображается на устройстве регистрации ошибок по умолчанию. Как правило, это системная консоль или окно вывода Visual Studio.on the default error logging device, which is typically the system console or the Visual Studio Output window. В примере элемент Reference используется просто для наглядности.The Reference element in the example is included just for illustration.

<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>

Задачу HelloWorld можно сохранить в файл с именем HelloWorld.targets , а затем вызвать его из проекта, как показано ниже.You could save the HelloWorld task in a file that is named HelloWorld.targets , and then invoke it from a project as follows.

<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="HelloWorld.targets" />
  <Target Name="Hello">
    <HelloWorld />
  </Target>
</Project>

Входные и выходные параметрыInput and output parameters

Параметры встроенной задачи являются дочерними элементами элемента ParameterGroup.Inline task parameters are child elements of a ParameterGroup element. Каждый параметр принимает имя элемента, который его определяет.Every parameter takes the name of the element that defines it. Код, представленный ниже, определяет параметр Text.The following code defines the parameter Text.

<ParameterGroup>
  <Text />
</ParameterGroup>

Параметры могут иметь один или несколько атрибутов:Parameters may have one or more of these attributes:

  • Атрибут Required является необязательным и по умолчанию имеет значение false.Required is an optional attribute that is false by default. Если же используется значение true, тогда этот параметр обязателен и перед вызовом задачи ему необходимо присвоить значение.If true, then the parameter is required and must be given a value before calling the task.

  • Атрибут ParameterType является необязательным и по умолчанию имеет значение System.String.ParameterType is an optional attribute that is System.String by default. Вы можете его задать для любого полного типа, являющегося элементом или значением, которые можно преобразовать как в строку, так и из нее, используя System.Convert.ChangeType.It may be set to any fully qualified type that is either an item or a value that can be converted to and from a string by using System.Convert.ChangeType. Другими словами, любой тип, который можно передать во внешнюю задачу или же из нее.(In other words, any type that can be passed to and from an external task.)

  • Атрибут Output является необязательным и по умолчанию имеет значение false.Output is an optional attribute that is false by default. Если же используется значение true, тогда этому параметру необходимо присвоить значение перед возвратом из метода Execute.If true, then the parameter must be given a value before returning from the Execute method.

Например, примененная к объекту директиваFor example,

<ParameterGroup>
  <Expression Required="true" />
  <Files ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
  <Tally ParameterType="System.Int32" Output="true" />
</ParameterGroup>

определяет следующие три параметра:defines these three parameters:

  • Expression является обязательным входным параметром типа System.String.Expression is a required input parameter of type System.String.

  • Files является обязательным входным параметром списка элементов.Files is a required item list input parameter.

  • Tally является выходным параметром типа System.Int32.Tally is an output parameter of type System.Int32.

Если в элементе Code значением атрибута Type является Fragment или Method, тогда свойства для каждого параметра создаются автоматически.If the Code element has the Type attribute of Fragment or Method, then properties are automatically created for every parameter. В противном случае свойства следует явно объявить в исходном коде задачи. Кроме того, они должны в точности соответствовать определениям своих параметров.Otherwise, properties must be explicitly declared in the task source code, and must exactly match their parameter definitions.

ПримерExample

Как показано ниже, встроенная задача заменяет каждое вхождение токена в указанном файле на указанное значение.The following inline task replaces every occurrence of a token in the given file with the given value.

<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>

См. такжеSee also