Udostępnij za pośrednictwem


Zadania wbudowane programu MSBuild

Zadania programu MSBuild są zwykle tworzone przez kompilowanie klasy, która implementuje ITask interfejs. Aby uzyskać więcej informacji, zobacz Zadania.

Począwszy od programu .NET Framework w wersji 4, można tworzyć zadania wbudowane w pliku projektu. Nie trzeba tworzyć oddzielnego zestawu do hostowania zadania. Ułatwia to śledzenie kodu źródłowego i łatwiejsze wdrażanie zadania. Kod źródłowy jest zintegrowany ze skryptem.

W programie MSBuild 15.8 dodano element RoslynCodeTaskFactory . W przypadku bieżącego programowania należy użyć elementu RoslynCodeTaskFactory, a nie CodeTaskFactory. CodeTaskFactory obsługuje tylko wersje języka C# do wersji 4.0.

Struktura zadania wbudowanego

Wbudowane zadanie jest zawarte za pomocą elementu UsingTask . Wbudowane zadanie i UsingTask element, który go zawiera, są zwykle uwzględniane w pliku .targets i importowane do innych plików projektu zgodnie z potrzebami. Oto podstawowe zadanie wbudowane. Zwróć uwagę, że nic nie robi.

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

Element UsingTask w przykładzie ma trzy atrybuty opisujące zadanie i wbudowaną fabrykę zadań, która ją kompiluje.

  • Atrybut TaskName nazywa zadanie , w tym przypadku DoNothing.

  • Atrybuty TaskFactory nazwiją klasę, która implementuje fabrykę zadań wbudowanych.

  • Atrybut AssemblyFile udostępnia lokalizację wbudowanej fabryki zadań. Alternatywnie można użyć atrybutu AssemblyName , aby określić w pełni kwalifikowaną nazwę wbudowanej klasy fabryki zadań, która zazwyczaj znajduje się w $(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll.

Pozostałe elementy DoNothing zadania są puste i są udostępniane w celu zilustrowania kolejności i struktury zadania wbudowanego. Bardziej niezawodny przykład zostanie przedstawiony w dalszej części tego tematu.

  • Element ParameterGroup jest opcjonalny. Gdy zostanie określony, deklaruje parametry zadania. Aby uzyskać więcej informacji na temat parametrów wejściowych i wyjściowych, zobacz Parametry wejściowe i wyjściowe w dalszej części tego tematu.

  • Element Task opisuje i zawiera kod źródłowy zadania.

  • Element Reference określa odwołania do zestawów .NET używanych w kodzie. Jest to odpowiednik dodawania odwołania do projektu w programie Visual Studio. Atrybut Include określa ścieżkę przywołytowanego zestawu.

  • Element Using zawiera listę przestrzeni nazw, do których chcesz uzyskać dostęp. Przypomina to instrukcję Using w języku Visual C#. Atrybut Namespace określa przestrzeń nazw do uwzględnienia.

Reference i Using elementy są niezależne od języka. Zadania wbudowane można napisać w jednym z obsługiwanych języków .NET CodeDom, na przykład Visual Basic lub Visual C#.

Uwaga

Elementy zawarte przez Task element są specyficzne dla fabryki zadań, w tym przypadku fabryki zadań kodu.

Element kodu

Ostatnim elementem podrzędnym Task , który ma pojawić się w elemecie , jest Code element . Element Code zawiera lub lokalizuje kod, który chcesz skompilować w zadaniu. To, co umieścisz w elemenie Code , zależy od tego, jak chcesz napisać zadanie.

Atrybut Language określa język, w którym jest napisany kod. Dopuszczalne wartości to cs C#, vb dla języka Visual Basic.

Atrybut Type określa typ kodu, który znajduje się w elemecie Code .

  • Jeśli wartość Type to Class, Code element zawiera kod klasy pochodzącej z interfejsu ITask .

  • Jeśli wartość Type to Method, kod definiuje przesłonięć Execute metodę interfejsu ITask .

  • Jeśli wartość Type to Fragment, kod definiuje zawartość Execute metody, ale nie podpis lub instrukcję return .

Sam kod zwykle pojawia się między znacznikiem <![CDATA[ a znacznikiem ]]> . Ponieważ kod znajduje się w sekcji CDATA, nie musisz martwić się o ucieczkę zastrzeżonych znaków, na przykład "<" lub ">".

Alternatywnie możesz użyć Source atrybutu Code elementu, aby określić lokalizację pliku zawierającego kod zadania. Kod w pliku źródłowym musi być typu określony przez Type atrybut . Source Jeśli atrybut jest obecny, wartość domyślna to TypeClass. Jeśli Source nie ma wartości, wartość domyślna to Fragment.

Uwaga

Podczas definiowania klasy zadań w pliku źródłowym nazwa klasy musi być zgodna z atrybutem TaskName odpowiedniego elementu UsingTask .

Helloworld

Oto bardziej niezawodne zadanie wbudowane. Zadanie HelloWorld wyświetla komunikat "Hello, world!" na domyślnym urządzeniu rejestrowania błędów, które jest zazwyczaj konsolą systemową lub oknem danych wyjściowych programu Visual Studio. Element Reference w przykładzie jest dołączany tylko do ilustracji.

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

Zadanie HelloWorld można zapisać w pliku o nazwie HelloWorld.targets, a następnie wywołać je z projektu w następujący sposób.

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

Parametry wejściowe i wyjściowe

Wbudowane parametry zadania to elementy podrzędne ParameterGroup elementu. Każdy parametr przyjmuje nazwę elementu, który go definiuje. Poniższy kod definiuje parametr Text.

<ParameterGroup>
  <Text />
</ParameterGroup>

Parametry mogą mieć co najmniej jeden z następujących atrybutów:

  • Required jest opcjonalnym atrybutem, który jest false domyślnie. Jeśli trueparametr jest wymagany i musi mieć wartość przed wywołaniem zadania.

  • ParameterType jest opcjonalnym atrybutem, który jest System.String domyślnie. Można go ustawić na dowolny w pełni kwalifikowany typ, który jest elementem lub wartością, którą można przekonwertować na i z ciągu przy użyciu elementu System.Convert.ChangeType. (Innymi słowy, dowolny typ, który można przekazać do i z zadania zewnętrznego).

  • Output jest opcjonalnym atrybutem, który jest false domyślnie. Jeśli trueparametr , należy podać wartość przed zwróceniem z metody Execute.

Przykład:

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

definiuje następujące trzy parametry:

  • Expression jest wymaganym parametrem wejściowym typu System.String.

  • Files jest wymaganym parametrem wejściowym listy elementów.

  • Tally jest parametrem wyjściowym typu System.Int32.

Code Jeśli element ma Type atrybut Fragment lub Method, właściwości są tworzone automatycznie dla każdego parametru. W przeciwnym razie właściwości muszą być jawnie zadeklarowane w kodzie źródłowym zadania i muszą dokładnie odpowiadać ich definicjom parametrów.

Przykład

Następujące zadanie wbudowane zastępuje każde wystąpienie tokenu w danym pliku daną wartością.

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