Partager via


Écrire des tâches pour MSBuild

Les tâches sont contenues dans les cibles MSBuild et fournissent le code qui s’exécute pendant le processus de génération. MSBuild inclut une bibliothèque de tâches classiques, et vous pouvez également créer vos propres tâches. Pour plus d’informations sur la bibliothèque de tâches que MSBuild inclut, consultez la référence des tâches MSBuild.

Conditions préalables

Projet Visual Studio qui s’génère avec MSBuild.

Tâches

Parmi les exemples de tâches MSBuild, citons Copy, qui copie un ou plusieurs fichiers, MakeDir, qui crée un répertoire et Csc, qui compile les fichiers de code source C#. Chaque tâche est implémentée en tant que classe .NET qui implémente l’interface ITask définie dans l’assembly Microsoft.Build.Framework.dll .

Vous pouvez utiliser l’une des approches suivantes lorsque vous implémentez une tâche :

  • Implémentez directement l’interface ITask.

  • Dérivez votre classe de la classe d’assistance Task, qui est définie dans l’assembly Microsoft.Build.Utilities.dll. Task implémente ITask et fournit des implémentations par défaut de certains membres ITask. La journalisation est également plus facile.

Dans les deux cas, vous devez ajouter une méthode à votre classe nommée Execute, qui est appelée lors de l’exécution de la tâche. Cette méthode ne prend aucun paramètre et retourne une valeur Boolean : true si la tâche a réussi ou false si elle a échoué. L’exemple suivant montre une tâche qui n’effectue aucune action, se termine correctement et retourne true.

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

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

Le fichier projet MSBuild suivant exécute la tâche précédente :

<Project>
    <Target Name="MyTarget">
        <SimpleTask />
    </Target>
</Project>

Lorsque les tâches s’exécutent, elles peuvent également recevoir des entrées du fichier projet si vous créez des propriétés .NET sur la classe de tâches. MSBuild définit ces propriétés immédiatement avant d’appeler la méthode Execute de la tâche. Pour créer une propriété de chaîne, utilisez le code de tâche tel que l’exemple suivant :

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

Le fichier projet suivant exécute cette tâche et définit MyProperty à la valeur donnée.

<Project>
   <Target Name="MyTarget">
      <SimpleTask MyProperty="Value for MyProperty" />
   </Target>
</Project>

Comment MSBuild appelle des tâches

Lorsque MSBuild appelle une tâche, elle instancie d’abord la classe de tâches, puis appelle les setters de propriétés de cet objet pour les paramètres de tâche définis dans l’élément de tâche dans le fichier projet. Si l’élément de tâche ne spécifie pas de paramètre ou si l’expression spécifiée dans l’élément prend la valeur d’une chaîne vide, le jeu de propriétés n’est pas appelé.

Par exemple, dans le projet suivant, seul le setter est appelé pour Input3.

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

Une tâche ne devrait pas dépendre de l'ordre relatif dans lequel les setters de paramètres et de propriétés sont invoqués.

Types de paramètres de tâche

MSBuild gère en mode natif les propriétés de type string, boolITaskItemet ITaskItem[]. Si une tâche accepte un paramètre d’un type différent, MSBuild invoque ChangeType pour convertir depuis string, avec toutes les références de propriété et d’élément ChangeType développées, vers le type de destination. Si la conversion échoue pour un paramètre d’entrée, MSBuild émet une erreur et n’appelle pas la méthode de Execute() la tâche.

Inscrire des tâches

Pour exécuter une tâche, MSBuild doit savoir comment localiser et exécuter l’assembly qui contient la classe de tâche. Les tâches sont inscrites à l'aide de l'élément UsingTask (MSBuild).

Si votre tâche a des dépendances spécifiques au temps d'exécution, vous devez diriger MSBuild pour qu'il exécute la tâche dans un environnement spécifique en indiquant les attributs Architecture ou Runtime de son élément UsingTask. Pour plus d’informations, consultez Attributs UsingTask et paramètres de tâche.

Le fichier MSBuild Microsoft.Common.tasks est un fichier projet qui répertorie les UsingTask éléments qui inscrivent toutes les tâches fournies avec MSBuild. Ce fichier est automatiquement inclus lorsque MSBuild génère un projet. Si une tâche inscrite dans Microsoft.Common.tasks est également inscrite dans le fichier projet actuel, le fichier projet actuel est prioritaire. Vous pouvez donc remplacer une tâche par défaut par votre propre tâche du même nom.

Conseil

Vous pouvez voir la liste des tâches fournies avec une version spécifique de MSBuild en affichant le contenu de son fichier Microsoft.Common.tasks .

Exiger que les propriétés de tâche soient définies

Vous pouvez marquer certaines propriétés de tâche en fonction des besoins. Par conséquent, tout fichier projet qui exécute la tâche doit définir des valeurs pour ces propriétés ou la build échoue. Appliquez l’attribut [Required] à la propriété .NET dans votre tâche comme suit :

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

L’attribut [Required] est défini par RequiredAttribute dans l’espace de noms Microsoft.Build.Framework.

Déclencher des événements à partir d’une tâche

Si votre tâche dérive de la Task classe d’assistance, vous pouvez utiliser l’une des méthodes d’assistance suivantes sur la Task classe pour déclencher des événements interceptés et affichés par tous les enregistreurs d’événements inscrits :

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

Si votre tâche est implémentée ITask directement, vous pouvez toujours déclencher de tels événements, mais vous devez utiliser l’interface IBuildEngine . L’exemple suivant montre une tâche qui implémente ITask et déclenche un événement personnalisé.

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

Empaqueter la tâche

La méthode recommandée pour distribuer une tâche se trouve dans un package NuGet. Le package doit regrouper toutes les dépendances. Pour obtenir un didacticiel qui vous guide tout au long de la création d’une tâche personnalisée, consultez Créer un package NuGet.

Exemple 1

La classe C# suivante illustre une tâche dérivant de la classe d’assistance Task . Cette tâche retourne true, indiquant qu’elle a réussi.

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

Exemple 2

La classe C# suivante illustre une tâche implémentant l’interface ITask . Cette tâche retourne true, indiquant qu’elle a réussi.

using System;
using Microsoft.Build.Framework;

namespace SimpleTask2
{
    public class SimpleTask2: ITask
    {
        //When implementing the ITask interface, it's 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's 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 does its work.
            return true;
        }
    }
}

Exemple 3

Cette classe C# illustre une tâche qui dérive de la classe d’assistance Task. La tâche a une propriété de chaîne requise et déclenche un événement affiché par tous les enregistreurs d’événements inscrits.

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

Exemple 4

L’exemple suivant montre un fichier projet qui appelle l’exemple de tâche précédent. SimpleTask3

<Project>
    <UsingTask TaskName="SimpleTask3.SimpleTask3"
        AssemblyFile="SimpleTask3\bin\debug\simpletask3.dll"/>

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