共用方式為


逐步解說:使用 MSBuild

MSBuild 是 Microsoft 和 Visual Studio 的組建平台。 此逐步解說介紹 MSBuild 的建置組塊,以及顯示如何撰寫、管理和偵錯 MSBuild 專案。 您將學習:

  • 建立和管理專案檔。

  • 如何使用建置屬性。

  • 如何使用建置項目。

您可以從 Visual Studio 或 [命令視窗] 執行 MSBuild。 在此逐步解說中,您可以使用 Visual Studio 建立 MSBuild 專案檔。 您可在 Visual Studio 中編輯專案檔,並使用 [命令視窗] 來建置專案及檢查結果。

建立 MSBuild 專案

Visual Studio 專案系統是以 MSBuild 為基礎。 這可讓您輕鬆使用 Visual Studio 建立新的專案檔。 在本章節中,您會建立 Visual C# 專案檔。 您也可以選擇建立 Visual Basic 專案檔。 在此逐步解說中,這兩個專案檔之間的差異並不顯著。

若要建立專案檔

  1. 開啟 Visual Studio。

  2. 在 [檔案] 功能表上,指向 [新增],然後按一下 [專案]。

  3. 在 [新增專案] 對話方塊中,選取 Visual C# 專案類型,然後選取 [Windows Form 應用程式] 範本。 在 [名稱] 方塊中,輸入 BuildApp。 輸入方案的 [位置],例如 D:\。 接受 [為方案建立目錄] (已選取)、[加入至原始檔控制] (未選取) 和 [方案名稱] ( BuildApp) 的預設值。

    按一下 [確定] 建立專案檔。

檢查專案檔

在上一節中,您已使用 Visual Studio 建立 Visual C# 專案檔。 在 [方案總管] 中,專案檔是以名為 BuildApp 的專案節點表示。 您可以使用 Visual Studio 程式碼編輯器來檢查專案檔。

若要檢查專案檔

  1. 在 [方案總管] 中,按一下 BuildApp 專案節點。

  2. 在 [屬性] 瀏覽器中,請注意 [專案檔] 屬性是 BuildApp.csproj。 所有專案檔都會以尾碼 "proj" 命名。 如果您建立了 Visual Basic 專案,則專案檔名會是 BuildApp.vbproj。

  3. 以滑鼠右鍵按一下專案節點,然後按一下 [卸載專案]。

  4. 再次以滑鼠右鍵按一下專案節點,然後按一下 [編輯 BuildApp.csproj]。

    專案檔會顯示在程式碼編輯器中。

目標和工作

專案檔是根節點為 Project 的 XML 格式檔案。

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build"  xmlns="https://schemas.microsoft.com/developer/msbuild/2003">

您必須在專案項目中指定 xmlns 命名空間。

建立應用程式工作完成與 目標工作 項目。

  • 工作 (Task) 是工作 (Work) 的最小單位,換言之,就是組建的「原子」。 工作 (Task) 是可具有輸入和輸出的獨立可執行元件。 專案檔中目前並未參考或定義工作。 在以下各節中,您會將工作加入至專案檔。 如需詳細資訊,請參閱MSBuild 工作主題。

  • 目標是具名的工作序列。 在專案檔的結尾處目前有兩個以 HTML 註解括住的目標:BeforeBuild 和 AfterBuild。

    <Target Name="BeforeBuild">
    </Target>
    <Target Name="AfterBuild">
    </Target>
    

    如需詳細資訊,請參閱MSBuild 目標主題。

專案節點具有選擇性 DefaultTargets 屬性,可選取要建置的預設目標,在此案例中為 Build。

<Project ToolsVersion="4.0" DefaultTargets="Build" ...

Build 目標並未定義於專案檔中。 但是,此目標是使用 Import 項目從 Microsoft.CSharp.targets 檔案匯入。

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

每次參考匯入的檔案時,匯入的檔案便會有效地插入到專案檔中。

MSBuild 會追蹤組建的目標,並保證每個目標只會建置一次。

加入目標和工作

在專案檔中加入目標。 將工作加入至可印出訊息的目標。

若要加入目標和工作

  1. 在專案檔中加入下列各行,並緊接在 Import 陳述式之後:

    <Target Name="HelloWorld">
    </Target>
    

    這會建立名為 HelloWorld 的目標。 請注意,您在編輯專案檔時可以取得 IntelliSense 支援。

  2. 將文字行加入至 HelloWorld 目標,結果產生的區段看起來會像以下的樣子:

    <Target Name="HelloWorld">
      <Message Text="Hello"></Message>
      <Message Text="World"></Message>
    </Target>
    
  3. 儲存專案檔案。

Message 工作是 MSBuild 隨附的許多工作之一。 如需可用工作的完整清單和用法的相關資訊,請參閱 MSBuild 工作參考

Message 工作會將 Text 屬性的字串值視為輸入並顯示於輸出裝置上。 HelloWorld 目標會執行 Message 工作兩次:首先顯示 "Hello",然後再顯示 "World"。

建置目標

從 [Visual Studio 命令提示字元] 執行 MSBuild,以建置上面定義的 HelloWorld 目標。 使用 /target 或 /t 命令列參數來選取目標。

注意事項注意事項

在以下各節中,我們會以 [命令視窗] 代表 [Visual Studio 命令提示字元]。

若要建置目標

  1. 按一下 [開始],然後按一下 [所有程式]。 找到 [Visual Studio Tools] 資料夾並按一下其中的 [Visual Studio 命令提示字元]。

  2. 從命令視窗巡覽至含有專案檔的資料夾,在此案例中是 D:\BuildApp\BuildApp。

  3. 使用命令參數 /t:HelloWorld 執行 msbuild。 這會選取並建置 HelloWorld 目標:

    msbuild buildapp.csproj /t:HelloWorld
    
  4. 檢查 [命令視窗] 中的輸出。 您應該會看到 "Hello" 和 "World" 這兩行:

    Hello
    World
    
注意事項注意事項

如果您看到 The target "HelloWorld" does not exist in the project ,可能是您忘了在程式碼編輯器中儲存專案檔。請儲存檔案,然後再試一次。

交替使用程式碼編輯器和命令視窗,您即可變更專案檔而且迅速看到結果。

注意事項注意事項

如果您未使用 /t 命令參數執行 msbuild,msbuild 會建置 Project 項目的 DefaultTarget 屬性所提供的目標,在此案例中是 "Build"。這會建置 Windows Form 應用程式 BuildApp.exe。

建置屬性

建置屬性是可引導建置的名稱/值組。 專案檔的頂部已經定義數個建置屬性:

<PropertyGroup>
...
  <ProductVersion>10.0.11107</ProductVersion>
  <SchemaVersion>2.0</SchemaVersion>
  <ProjectGuid>{30E3C9D5-FD86-4691-A331-80EA5BA7E571}</ProjectGuid>
  <OutputType>WinExe</OutputType>
...
</PropertyGroup>

所有屬性都是 PropertyGroup 項目的子項目。 屬性的名稱是子項目的名稱,而屬性的值是子項目的文字項目。 例如:

<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>

會定義名為 TargetFrameworkVersion 的屬性,並提供字串值 "v4.0" 給它。

建置屬性可以隨時重新定義。 如果

<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>

之後出現在專案檔中,或出現在之後匯入專案檔的檔案中,則 TargetFrameworkVersion 會採用新值 "v3.5"。

檢查屬性值

若要取得屬性的值,請使用下列語法,其中 PropertyName 是屬性的名稱:

$(PropertyName)

使用此語法來檢查專案檔中的部分屬性。

若要檢查屬性值

  1. 在程式碼編輯器中,以下列程式碼取代 HelloWorld 目標:

    <Target Name="HelloWorld">
      <Message Text="Configuration is $(Configuration)" />
      <Message Text="MSBuildToolsPath is $(MSBuildToolsPath)" />
    </Target>
    
  2. 儲存專案檔案。

  3. 從 [命令視窗] 輸入並執行此行:

    msbuild buildapp.csproj /t:HelloWorld
    
  4. 檢查輸出結果, 您應該會看到下列兩行 (您的 .NET Framework 版本可能不同):

    Configuration is Debug
    MSBuildToolsPath is C:\Windows\Microsoft.NET\Framework\v4.0.20317
    
注意事項注意事項

如果您沒有看到這兩行,可能是您忘了在程式碼編輯器中儲存專案檔。請儲存檔案,然後再試一次。

Dd393573.collapse_all(zh-tw,VS.110).gif條件式屬性

許多屬性 (如 Configuration) 會視條件而定義,也就是說,Condition 屬性 (Attribute) 會出現在屬性 (Property) 項目中。 只有當條件評估為 "true" 時,才能定義或重新定義條件式屬性。 請注意,未定義的屬性的預設值為空字串。 例如:

<Configuration   Condition=" '$(Configuration)' == '' ">Debug</Configuration>

表示「如果尚未定義 Configuration 屬性,則加以定義,並為其提供 'Debug' 值」。

幾乎所有 MSBuild 項目都可以有 Condition 屬性。 如需使用 Condition 屬性的詳細討論,請參閱 MSBuild 條件

Dd393573.collapse_all(zh-tw,VS.110).gif保留的屬性

MSBuild 保留一些屬性名稱來儲存專案檔和 MSBuild 二進位檔案的相關資訊。 MSBuildToolsPath 是保留屬性的範例 (MSBuild 3.5 的新增功能)。 保留的屬性和其他任何屬性一樣,都使用 $ 標記法來參考。 如需詳細資訊,請參閱HOW TO:參考專案檔的名稱或位置MSBuild 保留屬性

Dd393573.collapse_all(zh-tw,VS.110).gif環境變數

在專案檔中參考環境變數的方式,就跟建置屬性的方式一樣。 例如,若要在專案檔中使用 PATH 環境變數,請使用 $(Path)。 如果專案含有與環境變數同名的屬性定義,則專案的屬性會覆寫環境變數的值。 如需詳細資訊,請參閱HOW TO:在組建中使用環境變數

從命令列設定屬性

您可以在命令列上使用 /property 或 /p 命令列參數定義屬性。 從命令列接收的屬性值會覆寫在專案檔和環境變數中設定的屬性值。

若要從命令列設定屬性值

  1. 從 [命令視窗] 輸入並執行此行:

    msbuild buildapp.csproj /t:HelloWorld /p:Configuration=Release
    
  2. 檢查輸出結果, 您應該會看見此行:

    Configuration is Release.
    

MSBuild 會建立 Configuration 屬性並提供給它 "Release" 值。

特殊字元

某些字元在 MSBuild 專案檔中有特殊意義, 例如分號 (;) 和星號 (*) 這類字元。 若要在專案檔中使用這些特殊字元做為常值,則必須使用 %xx 語法指定這些字元,其中 xx 代表字元的 ASCII 十六進位值。

變更 Message 工作,以特殊字元顯示 Configuration 屬性的值,讓它更容易判讀。

若要在 Message 工作中使用特殊字元

  1. 在程式碼編輯器中,以此行取代兩個 Message 工作:

    <Message Text="%24(Configuration) is %22$(Configuration)%22" />
    
  2. 儲存專案檔案。

  3. 從 [命令視窗] 輸入並執行此行:

    msbuild buildapp.csproj /t:HelloWorld
    
  4. 檢查輸出結果, 您應該會看見此行:

    $(Configuration) is "Debug"
    

如需詳細資訊,請參閱MSBuild 特殊字元

建置項目

項目是做為建置系統之輸入的一段資訊 (通常是檔案名稱)。 例如,代表原始程式檔的項目集合可能會傳遞至名為 Compile 的工作,以便編譯至組件中。

所有項目 (Item) 都是 ItemGroup 項目 (Element) 的子項目 (Child Element)。 項目 (Item) 名稱是子項目 (Child Element) 的名稱,而項目 (Item) 值是子項目 (Child Element) 的 Include 屬性值。 同名的項目 (Item) 值會收集到該名稱的項目類型中。 例如:

<ItemGroup>
    <Compile Include="Program.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>

定義包含兩個項目的項目群組。 Compile 項目類型有兩個值:"Program.cs" 和 "Properties\AssemblyInfo.cs"。

下列程式碼會在一個 Include 屬性中宣告兩個檔案 (以分號分隔) 來建立相同的項目類型。

<ItemGroup>
    <Compile Include="Program.cs;Properties\AssemblyInfo.cs" />
</ItemGroup>

如需詳細資訊,請參閱MSBuild 項目

注意事項注意事項

檔案路徑是含有 MSBuild 專案檔之資料夾的相對路徑。

檢查項目類型值

若要取得項目類型的值,請使用下列語法,其中 ItemType 是項目類型的名稱:

@(ItemType)

使用此語法來檢查專案檔中的 Compile 項目類型。

若要檢查項目類型值

  1. 在程式碼編輯器中,以下列程式碼取代 HelloWorld 目標工作:

    <Target Name="HelloWorld">
      <Message Text="Compile item type contains @(Compile)" />
    </Target>
    
  2. 儲存專案檔案。

  3. 從 [命令視窗] 輸入並執行此行:

    msbuild buildapp.csproj /t:HelloWorld
    
  4. 檢查輸出結果, 您應該會看見以下很長的一行:

    Compile item type contains Form1.cs;Form1.Designer.cs;Program.cs;Properties\AssemblyInfo.cs;Properties\Resources.Designer.cs;Properties\Settings.Designer.cs
    

項目類型的值預設會以分號分隔。

若要變更項目類型的分隔符號,請使用下列語法,其中 ItemType 是項目類型,而 Separator 是一個或多個分隔字元的字串:

@(ItemType, Separator)

變更 Message 工作,以使用歸位字元和換行字元 (%0A%0D) 顯示 Compile 項目 (每行一個)。

若要每行顯示一個項目類型值

  1. 從程式碼編輯器,以這行取代訊息工作:

    <Message Text="Compile item type contains @(Compile, '%0A%0D')" />
    
  2. 儲存專案檔案。

  3. 從 [命令視窗] 輸入並執行此行:

    msbuild buildapp.csproj /t:HelloWorld

  4. 檢查輸出結果, 您應該會看見下列各行:

    Compile item type contains Form1.cs
    Form1.Designer.cs
    Program.cs
    Properties\AssemblyInfo.cs
    Properties\Resources.Designer.cs
    Properties\Settings.Designer.cs
    

Dd393573.collapse_all(zh-tw,VS.110).gifInclude、Exclude 和萬用字元

您可以使用萬用字元 "*"、"**" 和 "?" 搭配 Include 屬性,將項目加入至項目類型。 例如:

<Photos Include="images\*.jpeg" />

會將 images 資料夾中副檔名為 ".jpeg" 的所有檔案加入到 Photos 項目類型,而

<Photos Include="images\**.jpeg" />

會將 images 資料夾與其所有子資料夾中副檔名為 ".jpeg" 的所有檔案加入到 Photos 項目類型。 如需更多範例,請參閱 HOW TO:選取要建置的檔案

請注意,項目會在宣告時加入至項目類型。 例如:

<Photos Include="images\*.jpeg" />
<Photos Include="images\*.gif" />

會在 image 資料夾中建立名為 Photo 的項目類型,而此項目類型會包含副檔名為 ".jpeg" 或 ".gif" 的所有檔案。 這等於下面這一行:

<Photos Include="images\*.jpeg;images\*.gif" />

您可以從具有 Exclude 屬性的項目類型中排除項目。 例如:

<Compile Include="*.cs" Exclude="*Designer*">

會將副檔名為 ".cs" 的所有檔案加入到 Compile 項目類型,但是名稱包含 "Designer" 字串的檔案除外。 如需更多範例,請參閱 HOW TO:從組建中排除檔案

只有在項目的項目 (Item Element) 同時包含 Exclude 屬性和 Include 屬性時,前者才會影響後者所加入的項目 (Item)。 例如:

<Compile Include="*.cs" />
<Compile Include="*.res" Exclude="Form1.cs">

不會排除前述項目的項目 (Item Element) 中所加入的檔案 Form1.cs。

若要包含和排除項目

  1. 從程式碼編輯器,以這行取代訊息工作:

    <Message Text="Compile item type contains @(XFiles)" />
    
  2. 將此項目 (Item) 群組加入到 Import 項目 (Element) 之後:

    <ItemGroup>
       <XFiles Include="*.cs;properties/*.resx" Exclude="*Designer*" />
    </ItemGroup>
    
  3. 儲存專案檔案。

  4. 從 [命令視窗] 輸入並執行此行:

    msbuild buildapp.csproj /t:HelloWorld
    
  5. 檢查輸出結果, 您應該會看見此行:

    Compile item type contains Form1.cs;Program.cs;Properties/Resources.resx
    

項目中繼資料

項目 (Item) 中除了有從 Include 和 Exclude 屬性收集的資訊之外,還會包含中繼資料。 這項中繼資料可供需要有關項目 (Item) 之詳細資訊 (不僅限於項目值) 的工作使用。

在專案檔中宣告項目 (Item) 中繼資料的方式,是使用中繼資料的名稱建立項目 (Element) 做為項目 (Item) 的子項目 (Element)。 項目 (Item) 可以不包含或包含更多中繼資料值。 例如,下列 CSFile 項目的 Culture 中繼資料值為 "Fr":

<ItemGroup>
    <CSFile Include="main.cs">
        <Culture>Fr</Culture>
    </CSFile>
</ItemGroup>

若要取得項目類型的中繼資料值,請使用下列語法,其中 ItemType 是項目類型的名稱,而 MetaDataName 是中繼資料的名稱:

%(ItemType.MetaDataName)

若要檢查項目中繼資料

  1. 從程式碼編輯器,以這行取代訊息工作:

    <Message Text="Compile.DependentUpon: %(Compile.DependentUpon)" />
    
  2. 儲存專案檔案。

  3. 從 [命令視窗] 輸入並執行此行:

    msbuild buildapp.csproj /t:HelloWorld
    
  4. 檢查輸出結果, 您應該會看見下列各行:

    Compile.DependentUpon:
    Compile.DependentUpon: Form1.cs
    Compile.DependentUpon: Resources.resx
    Compile.DependentUpon: Settings.settings
    

請注意 "Compile.DependentUpon" 片語如何出現數次。 在目標內使用中繼資料和此語法會造成「批次處理」。 批次處理表示目標內的工作會針對每個唯一的中繼資料值執行一次。 這是通用 "for loop" 程式設計建構的 MSBuild 指令碼對等項目。 如需詳細資訊,請參閱MSBuild 批次處理

Dd393573.collapse_all(zh-tw,VS.110).gif已知的中繼資料

在項目 (Item) 清單中加入項目時,即指派了某些已知的中繼資料給該項目。 例如,%(Filename) 會傳回任何項目的檔案名稱。 如需已知中繼資料的完整清單,請參閱 MSBuild 已知的項目中繼資料

若要檢查已知的中繼資料

  1. 從程式碼編輯器,以這行取代訊息工作:

    <Message Text="Compile Filename: %(Compile.Filename)" />
    
  2. 儲存專案檔案。

  3. 從 [命令視窗] 輸入並執行此行:

    msbuild buildapp.csproj /t:HelloWorld
    
  4. 檢查輸出結果, 您應該會看見下列各行:

    Compile Filename: Form1
    Compile Filename: Form1.Designer
    Compile Filename: Program
    Compile Filename: AssemblyInfo
    Compile Filename: Resources.Designer
    Compile Filename: Settings.Designer
    

比較上面兩個範例,您即可發現當 Compile 項目類型中並非每一個項目都具有 DependentUpon 中繼資料時,所有項目都具有已知的 Filename 中繼資料。

Dd393573.collapse_all(zh-tw,VS.110).gif中繼資料轉換

項目清單可以轉換為新的項目清單。 若要轉換項目清單,請使用下列語法,其中 ItemType 是項目類型的名稱,而 MetadataName 是中繼資料的名稱:

@(ItemType -> '%(MetadataName)')

例如,使用類似 @(SourceFiles -> '%(Filename).obj') 的運算式,可以將原始程式檔的項目清單轉換為物件檔的集合。 如需詳細資訊,請參閱MSBuild 轉換

若要使用中繼資料轉換項目

  1. 從程式碼編輯器,以這行取代訊息工作:

    <Message Text="Backup files: @(Compile->'%(filename).bak')" />
    
  2. 儲存專案檔案。

  3. 從 [命令視窗] 輸入並執行此行:

    msbuild buildapp.csproj /t:HelloWorld
    
  4. 檢查輸出結果, 您應該會看見此行:

    Backup files: Form1.bak;Form1.Designer.bak;Program.bak;AssemblyInfo.bak;Resources.Designer.bak;Settings.Designer.bak
    

請注意,此語法表示的中繼資料不會造成批次處理。

下一步

若要了解如何逐步建立簡單專案檔,請嘗試逐步解說:從頭開始建立 MSBuild 專案檔案

請參閱

其他資源

MSBuild

MSBuild 參考