MSBuild 內嵌工作
MSBuild 工作通常是透過編譯實作 ITask 介面的類別來建立。 如需詳細資訊,請參閱工作。
從 .NET Framework 4 版開始,您可以在專案檔中建立內嵌工作。 您不必建立個別的組件來裝載工作。 這讓您能夠更輕鬆地追蹤原始程式碼,並讓部署工作變得更容易。 原始程式碼已整合到指令碼。
在 MSBuild 15.8 中,已新增 RoslynCodeTaskFactory。 對於目前的開發,請務必使用 RoslynCodeTaskFactory,而不是 CodeTaskFactory。 CodeTaskFactory 僅支援最多到 4.0 的 C# 版本。
內嵌工作的結構
內嵌工作包含於 UsingTask 項目中。 內嵌工作與包含它的 UsingTask
項目通常會包含於 .targets 檔案中,並視需要匯入其他專案檔。 以下是基本的內嵌工作。 請注意,它不會執行任何動作。
<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
項目具有三個描述工作的屬性,以及編譯工作的內嵌工作 Factory。
TaskName
屬性會為工作命名,在此案例中為DoNothing
。TaskFactory
屬性會為實作內嵌工作 Factory 的類別命名。AssemblyFile
屬性會提供內嵌工作 Factory 的位置。 或者,您可以使用AssemblyName
屬性來指定內嵌工作 Factory 類別的完整名稱,通常位於$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll
中。
DoNothing
工作的其餘項目是空的,它們的用途是用來說明內嵌工作的順序和結構。 本主題後續內容中將提供更強固的範例。
ParameterGroup
項目是選擇性的。 指定時,它將會宣告工作的參數。 如需輸入和輸出參數的詳細資訊,請參閱本主題稍後的輸入和輸出參數。Task
項目會描述並包含工作原始程式碼。Reference
項目會指定您在程式碼中使用的 .NET 組件參考。 這相當於在 Visual Studio 中加入專案的參考。Include
屬性會指定參考組件的路徑。Using
項目會列出您想要存取的命名空間。 這類似於 Visual C# 中的Using
陳述式。Namespace
屬性會指定要包含的命名空間。
Reference
和 Using
項目與語言無關。 內嵌工作可以使用任何一種受支援的 .NET CodeDom 語言來撰寫,例如:Visual Basic 或 Visual C#。
注意
Task
項目包含的項目皆為工作 Factory (在此案例中為程式碼工作 Factory) 特定。
Code 項目
Task
項目內顯示的最後一個子項目是 Code
項目。 Code
項目會包含或尋找您想要編譯為工作的程式碼。 您放入 Code
項目的內容取決於您要撰寫工作的方式。
Language
屬性會指定您用來撰寫程式碼的語言。 可接受的值為 cs
(適用於 C#)、vb
(適用於 Visual Basic)。
Type
屬性會指定可在 Code
項目中找到的程式碼類型。
如果
Type
的值是Class
,則Code
元素會包含衍生自 ITask 介面的類別程式碼。如果
Type
的值是Method
,則程式碼會定義 ITask 介面之Execute
方法的覆寫。如果
Type
的值是Fragment
,則程式碼會定義Execute
方法的內容,但不會定義簽章或return
陳述式。
程式碼本身通常會出現在 <![CDATA[
標記和 ]]>
標記之間。 因為此程式碼是在 CDATA 區段中,所以您不必擔心逸出保留的字元,如 "<" 或 ">"。
或者,您可以使用 Code
項目的 Source
屬性,來指定包含您工作程式碼的檔案位置。 原始程式檔中的程式碼必須是 Type
屬性所指定的類型。 如果 Source
屬性存在,Type
的預設值為 Class
。 如果 Source
不存在,預設值為 Fragment
。
注意
在原始程式檔中定義工作類別時,類別名稱必須與對應的 UsingTask 項目的 TaskName
屬性相符。
HelloWorld
以下是更強固的內嵌工作。 HelloWorld 工作會在預設的錯誤記錄裝置上顯示 "Hello, world!",此裝置通常是系統主控台或 Visual Studio 的 [輸出] 視窗。 範例所包含的 Reference
項目僅供說明之用。
<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.targets 的檔案中儲存 HelloWorld 工作,然後從專案中叫用它,如下所示。
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="HelloWorld.targets" />
<Target Name="Hello">
<HelloWorld />
</Target>
</Project>
輸入和輸出參數
內嵌工作參數是 ParameterGroup
項目的子項目。 每個參數都會採用定義它的項目名稱。 下列程式碼會定義參數 Text
。
<ParameterGroup>
<Text />
</ParameterGroup>
參數可能具備下列其中一或多個屬性:
Required
是選擇性屬性,預設值為false
。 如果是true
,則為必要參數,必須為它提供值,才能呼叫工作。ParameterType
是選擇性屬性,預設值為System.String
。 它可能會設定為任何完整的類型,這種類型是可使用 System.Convert.ChangeType 從字串轉換或轉換自字串的項目或值。 (換句話說,就是可傳遞到外部工作或從外部工作傳入的任何類型)。Output
是選擇性屬性,預設值為false
。 如果是true
,則必須為參數提供值,才能從 Execute 方法傳回。
例如,
<ParameterGroup>
<Expression Required="true" />
<Files ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
<Tally ParameterType="System.Int32" Output="true" />
</ParameterGroup>
定義下列三個參數:
Expression
是 System.String 類型的必要輸入參數。Files
是必要的項目清單輸入參數。Tally
是 System.Int32 類型的輸出參數。
如果 Code
項目具有 Fragment
或 Method
的 Type
屬性,則會自動為每個參數建立屬性。 否則,必須在工作原始程式碼中明確宣告屬性,而且屬性必須完全符合它們的參數定義。
範例
下列內嵌工作會使用指定的值,來取代在指定檔案中出現的每一個語彙基元。
<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>