工作撰寫

提供在建置流程期間執行之程式碼的工作。 工作是包含在目標中。 一般工作程式庫會隨附於 MSBuild,您也可以建立自己的工作。 如需 MSBuild 隨附之工作程式庫的詳細資訊,請參閱工作參考

工作

工作範例包括複製一或多個檔案的 Copy、建立目錄的 MakeDir,以及編譯 C# 原始程式碼檔的 Csc。 每個工作都會實作為 .NET 類別,此類別會實作 ITask 介面,此介面定義於 Microsoft.Build.Framework.dll 組件中。

實作工作時有兩種方法可供使用:

  • 直接實作 ITask 介面。

  • 從協助程式類別 Task 衍生您的類別,此協助程式類別定義於 Microsoft.Build.Utilities.dll 組件中。 工作會實作 ITask 並提供部分 ITask 成員的預設實作。 此外,記錄會更容易。

這兩種情況都必須在您的類別中新增名為 Execute 的方法,這是工作執行時所呼叫的方法。 這個方法不採用任何參數,並會傳回 Boolean 值:如果工作成功為 true,如果失敗為 false。 下列範例顯示不執行任何動作且順利完成的工作 (傳回 true)。

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

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

下列專案檔會執行此工作:

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

如果您在工作類別上建立 .NET 屬性,則工作在執行時,也可以接收來自專案檔的輸入。 MSBuild 會先立即設定這些屬性,再呼叫工作的 Execute 方法。 若要建立字串屬性,請使用下列工作碼:

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

下列專案檔會執行此工作,並將 MyProperty 設定成指定值:

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

註冊工作

如果專案即將執行工作,MSBuild 必須知道如何找出並執行包含工作類別的組件。 工作是使用 UsingTask 元素 (MSBuild) 註冊的。

如果您的工作有執行階段特定相依性,您必須在其 UsingTask 中指出 Architecture 和/或 Runtime,以通知 MSBuild 應該在特定環境中執行工作。

MSBuild 檔案 Microsoft.Common.tasks 是包含 UsingTask 元素清單的專案檔案,這些元素會註冊所有隨附於 MSBuild 的工作。 建置任何專案時,都會自動包含此檔案。 如果在 Microsoft.Common.tasks 中註冊的工作也在目前的專案檔中註冊,則以目前的專案檔為優先,所以您可使用自己的同名工作覆寫預設工作。

提示

您可檢視 Microsoft.Common.tasks 的內容,以查看特定 MSBuild 版本隨附的工作清單。

從工作引發事件

如果您的工作衍生自 Task 協助程式類別,您可以對 Task 類別使用下列任一 helper 方法,引發要被攔截且由任何已註冊記錄器顯示的事件:

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

如果您的工作直接實作 ITask,您仍會引發這類事件,但必須使用 IBuildEngine 介面。 下例示範的工作會實作 ITask 並引發自訂事件:

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

要求設定工作參數

您可將某些工作屬性標記為「必要」,讓所有執行工作的專案檔都必須設定這些屬性值,否則組建會失敗。 在您的工作中將 [Required] 屬性套用至 .NET 屬性,如下所示:

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

RequiredAttributeMicrosoft.Build.Framework 命名空間中定義 [Required] 屬性。

MSBuild 如何叫用工作

叫用工作時,MSBuild 會先具現化工作類別,然後針對專案檔的工作元素中設定的工作參數呼叫該物件的屬性 setter。 如果工作元素未指定參數,或專案中指定的運算式評估為空字串,則不會呼叫屬性 setter。

例如,在專案中

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

只會呼叫 Input3 的 setter。

工作不應該相依於 parameter-property setter 引動過程的任何相對順序。

工作參數類型

MSBuild 會以原生方式處理 stringboolITaskItemITaskItem[] 類型的屬性。 如果工作接受不同類型的參數,則 MSBuild 會叫用 ChangeType 以從 string (已展開所有屬性和項目參考) 轉換至目的地類型。 如果任何輸入參數的轉換失敗,MSBuild 會發出錯誤,而且不會呼叫工作的 Execute() 方法。

範例 1

描述

以下 C# 類別示範衍生自 Task 協助程式類別的工作。 此工作會傳回 true,指出是否成功。

代碼

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

範例 2

描述

以下 C# 類別示範實作 ITask 介面的工作。 此工作會傳回 true,指出是否成功。

代碼

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

範例 3

描述

此 C# 類別示範衍生自 Task 協助程式類別的工作。 它具有必要的字串屬性,會引發所有已註冊記錄器顯示的事件。

代碼

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

範例 4

描述

下例示範的專案檔會叫用前一個範例的工作:SimpleTask3。

代碼

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