Schreiben von Aufgaben

Aufgaben stellen den Code bereit, der während des Buildprozesses ausgeführt wird. Ziele enthalten Aufgaben. MSBuild umfasst eine Bibliothek mit typischen Aufgaben. Sie können aber auch Ihre eigenen Aufgaben erstellen. Weitere Informationen zu der in MSBuild enthaltenen Aufgabenbibliothek finden Sie in der Aufgabenreferenz.

Aufgaben

Beispiele für Aufgaben sind u. a. Copy zum Kopieren mindestens einer Datei, MakeDir zum Erstellen eines Verzeichnisses und Csc zum Kompilieren einer C#-Quellcodedatei. Jede Aufgabe wird als .NET-Klasse implementiert, die die ITask-Schnittstelle implementiert, die in der Assembly Microsoft.Build.Framework.dll definiert ist.

Es gibt zwei Ansätze zur Implementierung einer Aufgabe:

  • Implementieren Sie die ITask-Schnittstelle direkt.

  • Leiten Sie Ihre Klasse von der Hilfsklasse Task ab, die in der Assembly Microsoft.Build.Utilities.dll definiert ist. „Task“ implementiert „ITask“ und stellt Standardimplementierungen einiger „ITask“-Elemente dar. Darüber hinaus wird die Protokollierung vereinfacht.

In beiden Fällen müssen Sie Ihrer Klasse eine Methode mit dem Namen Execute hinzufügen. Dabei handelt es sich um die Methode, die aufgerufen wird, wenn eine Aufgabe ausgeführt wird. Sie nimmt keine Parameter und gibt einen Boolean-Wert zurück: true, wenn die Aufgabe erfolgreich ausgeführt wurde oder false, wenn sie fehlgeschlagen ist. Im folgenden Beispiel wird ein Aufgabe gezeigt, der keine Aktion ausführt und erfolgreich abgeschlossen wird (Rückgabe: true).

using System;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace MyTasks
{
    public class SimpleTask : Task
    {
        public override bool Execute()
        {
            return true;
        }
    }
}

Die folgende Projektdatei führt diese Aufgabe aus:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <Target Name="MyTarget">
        <SimpleTask />
    </Target>
</Project>

Wenn Aufgaben ausgeführt werden, können sie gleichzeitig Eingaben von der Projektdatei enthalten, wenn Sie .NET-Eigenschaften in der Aufgabenklasse erstellen. MSBuild legt diese Eigenschaften unmittelbar vor dem Aufrufen der Execute-Methode der Aufgabe fest. Verwenden Sie z.B. wie im Folgenden dargestellten Aufgabencode, um eine Zeichenfolgeneigenschaft zu erstellen:

using System;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace MyTasks
{
    public class SimpleTask : Task
    {
        public override bool Execute()
        {
            return true;
        }

        public string MyProperty { get; set; }
    }
}

Die folgende Projektdatei führt diese Aufgabe aus und legt MyProperty auf den vorhandenen Wert fest:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <Target Name="MyTarget">
      <SimpleTask MyProperty="Value for MyProperty" />
   </Target>
</Project>

Protokollaufgaben

Wenn das Projekt eine Aufgaben ausführen möchte, muss MSBuild wissen, wo die Assembly mit der Aufgabenklasse zu finden ist. Aufgaben werden über das UsingTask-Element (MSBuild) registriert.

Wenn Ihre Aufgabe laufzeitspezifische Abhängigkeiten hat, müssen Sie MSBuild mitteilen, dass die Aufgabe in einer bestimmten Umgebung ausgeführt werden soll, indem Sie die Architecture und/oder Runtime in seiner UsingTask angeben.

Die MSBuild-Datei Microsoft.Common.Tasks ist eine Projektdatei mit einer Liste mit UsingTask-Elementen, die alle Aufgaben registrieren, die mit MSBuild bereitgestellt werden. Diese Datei wird beim Erstellen von Projekten automatisch eingeschlossen. Wenn eine Aufgabe, die in Microsoft.Common.Tasks registriert wird, ebenfalls in der aktuellen Projektdatei registriert wird, hat die aktuelle Projektdatei Vorrang. Sie können also eine Standardaufgabe mit Ihrer eigenen Aufgabe, die denselben Namen hat, außer Kraft setzen.

Tipp

Sie können eine Liste der mit einer bestimmten MSBuild-Version bereitgestellten Aufgaben anzeigen, indem Sie die Inhalte in deren Microsoft.Common.Tasks-Element einsehen.

Auslösen von Ereignissen aus einer Aufgabe

Wenn Ihre Aufgabe aus der Task-Hilfsklasse abgeleitet wird, können Sie eine der folgenden Hilfsmethoden für die Task-Klasse verwenden, damit ein Ereignis ausgelöst wird, das von allen registrierten Protokollierungen abgefangen und angezeigt wird:

public override bool Execute()
{
    Log.LogError("messageResource1", "1", "2", "3");
    Log.LogWarning("messageResource2");
    Log.LogMessage(MessageImportance.High, "messageResource3");
    ...
}

Wenn Ihre Aufgabe ITask direkt implementiert, können Sie solche Ereignisse immer noch auslösen, allerdings nur noch über die IBuildEngine-Schnittstelle. Im folgenden Beispiel wird eine Aufgabe gezeigt, die „ITask“ implementiert und ein benutzerdefiniertes Ereignis auslöst:

public class SimpleTask : ITask
{
    public IBuildEngine BuildEngine { get; set; }

    public override bool Execute()
    {
        TaskEventArgs taskEvent =
            new TaskEventArgs(BuildEventCategory.Custom,
            BuildEventImportance.High, "Important Message",
           "SimpleTask");
        BuildEngine.LogBuildEvent(taskEvent);
        return true;
    }
}

Erfordern, dass Aufgabenparameter festgelegt werden

Sie können Aufgabeneigenschaften als „Erforderlich“ markieren, damit jede Projektdatei, die die Aufgabe ausführt, Werte für diese Eigenschaften oder die fehlgeschlagenen Builds festlegt. Wenden Sie das erforderliche [Required]-Attribut in der .NET-Eigenschaft in Ihrer Aufgabe wie folgt an:

[Required]
public string RequiredProperty { get; set; }

Das [Required]-Attribut wird von RequiredAttribute im Microsoft.Build.Framework-Namespace definiert.

Aufruf einer Aufgabe durch MSBuild

Zum Aufrufen einer Aufgabe instanziiert MSBuild zunächst die Aufgabenklasse. Anschließend werden die Eigenschaftensetter des Objekts für Aufgabenparameter aufgerufen, die in der Projektdatei im Aufgabenelement festgelegt sind. Der Eigenschaftensetter wird nicht aufgerufen, wenn das Aufgabenelement keinen Parameter angibt oder der im Element angegebene Ausdruck eine leere Zeichenfolge ergibt.

Sehen Sie sich z. B. folgendes Projekt an:

<Project>
 <Target Name="InvokeCustomTask">
  <CustomTask Input1=""
              Input2="$(PropertyThatIsNotDefined)"
              Input3="value3" />
 </Target>
</Project>

Hier wird nur der Setter für Input3 aufgerufen.

Eine Aufgabe sollte nicht von der relativen Reihenfolge des Aufrufs von Parameter und Eigenschaftensetter abhängen.

Typen von Aufgabenparametern

In MSBuild erfolgt werden die Eigenschaften vom Typ string, bool, ITaskItem und ITaskItem[] nativ verarbeitet. Akzeptiert eine Aufgabe einen Parameter eines anderen Typs, ruft MSBuild ChangeType auf, um eine Konvertierung von string (mit Erweiterung aller Eigenschaften- und Elementverweise) in den Zieltyp durchzuführen. Ist die Konvertierung für einen Eingabeparameter nicht erfolgreich, gibt MSBuild einen Fehler aus und ruft die Methode Execute() der Aufgabe nicht auf.

Beispiel 1

Beschreibung

Die folgende C#-Klasse veranschaulicht eine aus der Task-Hilfsklasse abgeleitete Aufgabe. Dieser Task gibt den Wert true zurück, der darauf hindeutet, dass der Task erfolgreich ausgeführt wird.

Code

using System;
using Microsoft.Build.Utilities;

namespace SimpleTask1
{
    public class SimpleTask1: Task
    {
        public override bool Execute()
        {
            // This is where the task would presumably do its work.
            return true;
        }
    }
}

Beispiel 2

Beschreibung

Die folgende C#-Klasse veranschaulicht eine Aufgabe zur Implementierung der ITask-Schnittstelle. Dieser Task gibt den Wert true zurück, der darauf hindeutet, dass der Task erfolgreich ausgeführt wird.

Code

using System;
using Microsoft.Build.Framework;

namespace SimpleTask2
{
    public class SimpleTask2: ITask
    {
        //When implementing the ITask interface, it is necessary to
        //implement a BuildEngine property of type
        //Microsoft.Build.Framework.IBuildEngine. This is done for
        //you if you derive from the Task class.
        public IBuildEngine BuildEngine { get; set; }

        // When implementing the ITask interface, it is necessary to
        // implement a HostObject property of type object.
        // This is done for you if you derive from the Task class.
        public object HostObject { get; set; }

        public bool Execute()
        {
            // This is where the task would presumably do its work.
            return true;
        }
    }
}

Beispiel 3

Beschreibung

Diese C#-Klasse veranschaulicht eine aus der Task-Hilfsklasse abgeleitete Aufgabe. Sie verfügt über eine erforderliche Zeichenfolgeneigenschaft und löst ein Ereignis aus, das von allen registrierten Protokollierungen angezeigt wird.

Code

using System;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace SimpleTask3
{
    public class SimpleTask3 : Task
    {
        private string myProperty;

        // The [Required] attribute indicates a required property.
        // If a project file invokes this task without passing a value
        // to this property, the build will fail immediately.
        [Required]
        public string MyProperty
        {
            get
            {
                return myProperty;
            }
            set
            {
                myProperty = value;
            }
        }

        public override bool Execute()
        {
            // Log a high-importance comment
            Log.LogMessage(MessageImportance.High,
                "The task was passed \"" + myProperty + "\".");
            return true;
        }
    }
}

Beispiel 4

Beschreibung

Im folgenden Beispiel wird eine Projektdatei dargestellt, die die vorherigen Beispielaufgabe „SimpleTask3“ aufruft.

Code

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <UsingTask TaskName="SimpleTask3.SimpleTask3"
        AssemblyFile="SimpleTask3\bin\debug\simpletask3.dll"/>

    <Target Name="MyTarget">
        <SimpleTask3 MyProperty="Hello!"/>
    </Target>
</Project>