瞭解專案檔

作者 :Jason Lee

Microsoft Build Engine (MSBuild) 專案檔位於建置和部署程式的核心。 本主題從 MSBuild 和專案檔的概念概觀開始。 它描述您在使用專案檔時將遇到的主要元件,並透過如何使用專案檔來部署真實世界應用程式的範例來運作。

您將學到什麼:

  • MSBuild 如何使用 MSBuild 專案檔來建置專案。
  • MSBuild 如何與部署技術整合,例如 Internet Information Services (IIS) Web Deployment Tool (Web Deploy) 。
  • 如何瞭解專案檔的主要元件。
  • 如何使用專案檔來建置和部署複雜的應用程式。

MSBuild 和專案檔

當您在 Visual Studio 中建立和建置方案時,Visual Studio 會使用 MSBuild 在您的方案中建置每個專案。 每個 Visual Studio 專案都包含 MSBuild 專案檔,副檔名反映專案的類型,例如 C# 專案 (.csproj) 、Visual Basic.NET 專案 (.vbproj) ,或資料庫專案 (.dbproj) 。 若要建置專案,MSBuild 必須處理與專案相關聯的專案檔。 專案檔是一份 XML 檔,其中包含 MSBuild 建置專案所需的所有資訊和指示,例如要包含的內容、平臺需求、版本設定資訊、網頁伺服器或資料庫伺服器設定,以及必須執行的工作。

MSBuild 專案檔是以 MSBuild XML 架構為基礎,因此建置程式會完全開啟且透明。 此外,您不需要安裝 Visual Studio 才能使用 MSBuild 引擎—MSBuild.exe 可執行檔是.NET Framework的一部分,而且您可以從命令提示字元執行它。 身為開發人員,您可以使用 MSBuild XML 架構來製作自己的 MSBuild 專案檔,以對專案建置和部署方式施加複雜且精細的控制。 這些自訂專案檔的運作方式與 Visual Studio 自動產生的專案檔完全相同。

注意

您也可以使用 MSBuild 專案檔搭配 Team Foundation Server 中的 Team Build 服務, (TFS) 。 例如,您可以在持續整合中使用專案檔, (CI) 案例,在簽入新程式碼時自動部署到測試環境。 如需詳細資訊,請參閱 設定 Team Foundation Server 以進行自動化 Web 部署

專案檔命名慣例

當您建立自己的專案檔時,可以使用任何您想要的副檔名。 不過,為了讓其他人更容易瞭解您的解決方案,您應該使用這些常見的慣例:

  • 當您建立建置專案的專案檔時,請使用 .proj 副檔名。
  • 當您建立可重複使用的專案檔以匯入其他專案檔時,請使用 .targets 副檔名。 副檔名為 .targets 的檔案通常不會自行建置任何專案,它們只會包含您可以匯入 .proj 檔案的指示。

與部署技術整合

如果您已在 Visual Studio 2010 中使用 Web 應用程式專案,例如 ASP.NET Web 應用程式和 ASP.NET MVC Web 應用程式,您將知道這些專案包含封裝 Web 應用程式的內建支援,並將 Web 應用程式部署至目標環境。 這些專案的 [ 屬性 ] 頁面包括 [封裝/發佈 Web ] 和 [ 封裝/發佈 SQL ] 索引標籤,可用來設定應用程式的元件封裝和部署方式。 這會顯示 [套件/發佈 Web ] 索引標籤:

[套件/發佈 Web] 索引標籤

這些功能背後的基礎技術稱為 Web 發佈管線 (WPP) 。 WPP 基本上會將 MSBuild 和 Web Deploy 結合在一起,為 Web 應用程式提供完整的建置、封裝和部署程式。

好消息是,當您為 Web 專案建立自訂專案檔時,您可以利用 WPP 所提供的整合點。 您可以在專案檔中包含部署指示,這可讓您建置專案、建立 Web 部署套件,以及透過單一專案檔和單一呼叫 MSBuild,在遠端伺服器上安裝這些套件。 您也可以呼叫任何其他可執行檔作為建置程式的一部分。 例如,您可以執行 VSDBCMD.exe 命令列工具,從架構檔案部署資料庫。 在本主題的課程中,您將瞭解如何利用這些功能來符合企業部署案例的需求。

注意

如需 Web 應用程式部署程式運作方式的詳細資訊,請參閱 ASP.NET Web 應用程式專案部署概觀

專案檔的結構

在更詳細地查看建置程式之前,請花一些時間熟悉 MSBuild 專案檔的基本結構。 本節提供檢閱、編輯或建立專案檔時所遇到的更常見元素概觀。 特別是,您將瞭解:

  • 如何使用 屬性 來管理建置程式的變數。
  • 如何使用 專案 來識別建置程式的輸入,例如程式碼檔案。
  • 如何使用目標和工作,使用專案檔中其他地方定義的屬性專案,提供 MSBuild 的執行指示。

這會顯示 MSBuild 專案檔中主要元素之間的關聯性:

MSBuild 專案檔中索引鍵專案之間的關聯性。

Project 元素

Project元素是每個專案檔的根項目。 除了識別專案檔的 XML 架構之外, Project 元素 還可以包含屬性來指定建置程式的進入點。 例如,在 Contact Manager 範例解決方案中, Publish.proj 檔案會指定組建應該從呼叫名為 FullPublish的目標開始。

<Project ToolsVersion="4.0" DefaultTargets="FullPublish" 
         xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  
</Project>

屬性和條件

專案檔通常需要提供許多不同的資訊片段,才能成功建置和部署專案。 這些資訊片段可能包括伺服器名稱、連接字串、認證、組建組態、來源和目的地檔案路徑,以及您想要包含以支援自訂的任何其他資訊。 在專案檔中,屬性必須在 PropertyGroup 元素內定義。 MSBuild 屬性是由索引鍵/值組所組成。 在 PropertyGroup 元素內,元素名稱會定義屬性索引鍵,而元素的內容則定義屬性值。 例如,您可以定義名為ServerNameConnectionString的屬性來儲存靜態伺服器名稱和連接字串。

<PropertyGroup>    
   <ServerName>FABRIKAM\TEST1</ServerName>
   <ConnectionString>
     Data Source=FABRIKAM\TESTDB;InitialCatalog=ContactManager,...
   </ConnectionString>
</PropertyGroup>

若要擷取屬性值,請使用 $ (PropertyName 格式) 。 例如,若要擷取 ServerName 屬性的值,您可以輸入:

$(ServerName)

注意

您會在本主題稍後看到如何使用屬性值的範例和時機。

將資訊內嵌為專案檔中的靜態屬性不一定是管理建置程式的理想方法。 在很多情況下,您會想要從其他來源取得資訊,或讓使用者能夠從命令提示字元提供資訊。 MSBuild 可讓您將任何屬性值指定為命令列參數。 例如,當使用者從命令列執行 MSBuild.exe 時,可能會提供 ServerName 的值。

msbuild.exe Publish.proj /p:ServerName=FABRIKAM\TESTWEB1

注意

如需您可以搭配 MSBuild.exe 使用之引數和參數的詳細資訊,請參閱 MSBuild 命令列參考

您可以使用相同的屬性語法來取得環境變數和內建專案屬性的值。 已為您定義許多常用的屬性,而且您可以藉由包含相關的參數名稱,在專案檔中使用它們。 例如,若要擷取目前的專案平臺,例如 x86AnyCpu,您可以在專案檔中包含 $ (Platform) 屬性參考。 如需詳細資訊,請參閱 建置命令和屬性一般 MSBuild 專案屬性保留屬性的宏。

屬性通常會與 條件搭配使用。 大部分的 MSBuild 元素都支援 Condition 屬性,可讓您指定 MSBuild 應該評估元素的準則。 例如,請考慮此屬性定義:

<PropertyGroup>
   <OutputRoot Condition=" '$(OutputRoot)'=='' ">..\Publish\Out\</OutputRoot>
   ...
</PropertyGroup>

當 MSBuild 處理這個屬性定義時,它會先檢查是否有 $ (OutputRoot) 屬性值。 如果屬性值為空白,換句話說,使用者尚未提供此屬性的值,條件會評估為 true ,而屬性值會設定為 。。\Publish\Out。如果使用者已提供此屬性的值,條件會評估為 false ,而且不會使用靜態屬性值。

如需您可以指定條件之不同方式的詳細資訊,請參閱 MSBuild 條件

專案和專案群組

專案檔的其中一個重要角色是定義建置程式的輸入。 一般而言,這些輸入是檔案—程式碼檔案、組態檔、命令檔,以及您需要在建置程式中處理或複製的任何其他檔案。 在 MSBuild 專案架構中,這些輸入是由 Item 元素表示。 在專案檔中,專案必須在 ItemGroup 元素 內定義。 就像 Property 元素一樣,您可以視需要命名 Item 元素 。 不過,您必須指定 Include 屬性,以識別專案所代表的檔案或萬用字元。

<ItemGroup>
   <ProjectsToBuild Include="$(SourceRoot)ContactManager-WCF.sln"/>
</ItemGroup>

藉由指定多個 具有相同名稱的 Item 元素 ,您可以有效地建立具名的資源清單。 查看此運作方式的好方法是查看 Visual Studio 所建立的其中一個專案檔。 例如,範例方案中 的 ContactManager.Mvc.csproj 檔案包含許多專案群組,每個群組都有數個完全相同的 Item 元素

<ItemGroup>
   <Reference Include="Microsoft.CSharp" />
   <Reference Include="System.Runtime.Serialization" />
   <Reference Include="System.ServiceModel" />
   ...
</ItemGroup>
<ItemGroup>
   <Compile Include="Controllers\AccountController.cs" />
   <Compile Include="Controllers\ContactsController.cs" />
   <Compile Include="Controllers\HomeController.cs" />
   ...
</ItemGroup>
<ItemGroup>
   <Content Include="Content\Custom.css" />
   <Content Include="CreateDatabase.sql" />
   <Content Include="DropDatabase.sql" />
   ...
</ItemGroup>

如此一來,專案檔會指示 MSBuild 建構需要以相同方式處理的檔案清單— [參考 ] 清單包含必須就地建置成功建置的元件、 [編譯 ] 清單包含必須編譯的程式碼檔案,而 內容 清單包含必須複製未變更的資源。 我們將在本主題稍後探討建置程式參考和使用這些專案的方式。

Item 元素也可以包含 ItemMetadata 子項目。 這些是使用者定義的索引鍵/值組,基本上代表該專案特有的屬性。 例如,專案檔中的 編譯專案元素 有許多包括 DependentUpon 子項目。

<Compile Include="Global.asax.cs">
   <DependentUpon>Global.asax</DependentUpon>
</Compile>

注意

除了使用者建立的專案中繼資料之外,所有專案都會在建立時指派各種常見的中繼資料。 如需詳細資訊,請參閱已知的項目中繼資料

您可以在根層級Project 元素或特定Target元素內建立ItemGroup元素。 ItemGroup 元素也支援 Condition 屬性,可讓您根據專案組態或平臺等條件量身打造建置程式的輸入。

目標和工作

在 MSBuild 架構中, Task 元素代表個別的建置指令 (或工作) 。 MSBuild 包含許多預先定義的工作。 例如:

  • 複製工作會將檔案複製到新的位置。
  • Csc工作會叫用 Visual C# 編譯器。
  • Vbc工作會叫用 Visual Basic 編譯器。
  • Exec工作會執行指定的程式。
  • 訊息工作會將訊息寫入記錄器。

注意

如需現用工作的完整詳細資料,請參閱 MSBuild 工作參考。 如需工作的詳細資訊,包括如何建立您自己的自訂工作,請參閱 MSBuild 工作

工作必須一律包含在 Target 元素內。 Target元素是一組依序執行的一或多個工作,而且專案檔可以包含多個目標。 當您想要執行工作或一組工作時,您可以叫用包含這些工作的目標。 例如,假設您有記錄訊息的簡單專案檔。

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <Target Name="LogMessage">
      <Message Text="Hello world!" />
   </Target>
</Project>

您可以使用 /t 參數來指定目標,從命令列叫用目標。

msbuild.exe Publish.proj /t:LogMessage

或者,您可以將 DefaultTargets 屬性新增至 Project 元素,以指定您想要叫用的目標。

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" 
         DefaultTargets="FullPublish">
   <Target Name="LogMessage">
      <Message Text="Hello world!" />
   </Target>
</Project>

在此情況下,您不需要從命令列指定目標。 您可以直接指定專案檔,而 MSBuild 會為您叫用 FullPublish 目標。

msbuild.exe Publish.proj

目標和工作都可以包含 Condition 屬性。 因此,如果符合特定條件,您可以選擇省略整個目標或個別工作。

一般而言,當您建立有用的工作和目標時,您必須參考您在專案檔中其他地方定義的屬性和專案:

  • 若要使用屬性值,請輸入 $ (PropertyName) ,其中 PropertyName 是 Property元素的名稱 或參數的名稱。
  • 若要使用專案,請輸入 @ (ItemName) ,其中 ItemNameItem 元素的名稱。

注意

請記住,如果您建立多個具有相同名稱的專案,您要建置清單。 相反地,如果您建立多個具有相同名稱的屬性,您提供的最後一個屬性值將會以相同名稱覆寫任何先前的屬性,屬性只能包含單一值。

例如,在範例解決方案的 Publish.proj 檔案中,查看 BuildProjects 目標。

<Target Name="BuildProjects" Condition=" '$(BuildingInTeamBuild)'!='true' ">
   <MSBuild Projects="@(ProjectsToBuild)"           
            Properties="OutDir=$(OutputRoot);
                        Configuration=$(Configuration);
                        DeployOnBuild=true;
                        DeployTarget=Package"
            Targets="Build" />
</Target>

在此範例中,您可以觀察下列重點:

  • 如果指定 BuildingInTeamBuild 參數且值為 true,則不會執行此目標內的任何工作。

  • 目標包含 MSBuild 工作的單一實例。 這項工作可讓您建置其他 MSBuild 專案。

  • ProjectsToBuild專案會傳遞至工作。 此專案可以代表專案或方案檔的清單,這些專案群組內所有 由 ProjectsToBuild 專案元素所定義。 在此情況下, ProjectsToBuild 專案是指單一方案檔。

    <ItemGroup>
       <ProjectsToBuild Include="$(SourceRoot)ContactManager-WCF.sln"/>
    </ItemGroup>
    
  • 傳遞至 MSBuild 工作的屬性值包括名為 OutputRootConfiguration的參數。 如果提供參數值,這些值會設定為參數值,如果不是,則會將其設定為靜態屬性值。

    <PropertyGroup>
       ... 
       <Configuration Condition=" '$(Configuration)'=='' ">Release
       </Configuration>
       <OutputRoot Condition=" '$(OutputRoot)'=='' ">..\Publish\Out\
       </OutputRoot>
       ...
    </PropertyGroup>
    

您也可以看到 MSBuild 工作會叫用名為 Build的目標。 這是 Visual Studio 專案檔中廣泛使用的數個內建目標之一,可在自訂專案檔中使用,例如 置、 清除重建發佈。 您將深入瞭解如何使用目標和工作來控制建置程式,以及本主題稍後的 MSBuild 工作。

注意

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

分割專案檔以支援多個環境

假設您想要能夠將解決方案部署到多個環境,例如測試伺服器、預備平臺和生產環境。 這些環境之間的設定可能會有很大的差異,不只是在伺服器名稱、連接字串等方面,也可能取決於認證、安全性設定,以及許多其他因素。 如果您需要定期執行此動作,當您每次切換目標環境時,都不需要在專案檔中編輯多個屬性。 也不需要無限的屬性值清單提供給建置程式的理想解決方案。

幸好有替代方案。 MSBuild 可讓您將組建組態分割成多個專案檔。 若要查看運作方式,請在範例解決方案中,請注意有兩個自訂專案檔:

  • Publish.proj,其中包含所有環境通用的屬性、專案和目標。
  • Env-Dev.proj,其中包含開發人員環境專屬的屬性。

現在請注意 ,Publish.proj 檔案包含 Import 元素,緊接在開啟 的 Project 標籤下方。

<Import Project="$(TargetEnvPropsFile)"/>

Import元素是用來將另一個 MSBuild 專案檔的內容匯入目前的 MSBuild 專案檔。 在此情況下, TargetEnvPropsFile 參數會提供您要匯入之專案檔的檔案名。 當您執行 MSBuild 時,可以為此參數提供值。

msbuild.exe Publish.proj /p:TargetEnvPropsFile=EnvConfig\Env-Dev.proj

這可有效地將兩個檔案的內容合併成單一專案檔。 使用此方法,您可以建立一個包含萬用群組建組態的專案檔,以及包含環境特定屬性的多個增補專案檔。 因此,只要執行具有不同參數值的命令,您就可以將解決方案部署到不同的環境。

執行具有不同參數值的命令可讓您將解決方案部署至不同的環境。

以這種方式分割專案檔是很好的作法。 它可讓開發人員執行單一命令來部署至多個環境,同時避免跨多個專案檔重複通用建置屬性。

注意

如需如何為您自己的伺服器環境自訂環境特定專案檔的指引,請參閱 設定目標環境的部署屬性

結論

本主題提供 MSBuild 專案檔的一般簡介,並說明如何建立自己的自訂專案檔來控制建置程式。 它也引進了將專案檔分割成通用建置指示和環境特定組建屬性的概念,以便輕鬆地建置專案並部署到多個目的地。

下一個主題 瞭解建置程式,可讓您深入瞭解如何使用專案檔來控制建置和部署,方法是逐步引導您部署具有實際複雜度的解決方案。

深入閱讀

如需專案檔和 WPP 的更深入簡介,請參閱在Microsoft Build Engine內:使用 MSBuild 和 Team Foundation Build by Sayed Ibimiim Hashimi 和 William Bartholomew,ISBN:978-0-7356-4524-0。