共用方式為


建置 WPF 應用程式 (WPF)

更新: 2008 年 7 月

Windows Presentation Foundation (WPF) 應用程式可以建置為 .NET Framework 可執行檔 (.exe)、程式庫 (.dll) 或是這兩種類型組件的組合。本主題一開始會先顯示如何從命令提示字元建置簡單的 WPF 應用程式,然後才說明 WPF 如何利用 Microsoft Build Engine (MSBuild) 的擴充性建置更為複雜的應用程式。本主題最後會提供 MSBuild 建置過程中主要步驟的深入討論做為結束。

這個主題包含下列章節。

  • 使用命令列編譯建置 WPF 應用程式
  • 使用 MSBuild 建置 WPF 應用程式
  • WPF 的 MSBuild 專案檔
  • 使用 Visual Studio 建立 WPF 的 MSBuild 專案
  • 建置 WPF 的 MSBuild 專案
  • Windows Presentation Foundation 建置管線
  • 累加建置支援
  • 相關主題

使用命令列編譯建置 WPF 應用程式

完全以程式碼 (沒有標記) 撰寫的 WPF 可以使用命令列編譯器進行建置。舉例來說,請考慮包含下列原始程式碼檔的 C# WPF 獨立應用程式:

  • 應用程式定義檔案 (app.cs)。

  • 視窗 (mainwindow.cs)。

這個應用程式可以從命令提示字元使用 C# 編譯器 csc.exe 進行建置,如下列範例所示:

csc.exe
  /out:WPFApplication.exe
  /target:winexe 
  app.cs mainwindow.cs 
  /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\presentationframework.dll" 
  /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\windowsbase.dll" 
  /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\presentationcore.dll"

在這個範例中:

  • /out 參數會指定所建置可執行檔組件 (WPFApplication.exe) 的名稱。

  • /target 參數會指定要編譯組件的類型 (Microsoft Windows 可執行檔)。

  • 構成應用程式的 C# 原始程式碼檔 (app.cs 和 mainwindow.cs)。

  • /reference 參數,用於識別要實作應用程式所使用類型的參考組件。

命令列編譯可用來建置更具複雜度的應用程式,雖然編譯器不支援包含可延伸標記語言 (XAML) 原始程式碼的 WPF 應用程式。再者,命令列編譯不支援一般 WPF 應用程式的完整建置需求,包括組態管理和 ClickOnce 資訊清單產生。為了支援這些建置需求和其他更為複雜的建置需求,WPF 可以整合並擴充 MSBuild。

注意事項:

如需命令列編譯的詳細資訊,請參閱使用 csc.exe 建置命令列從命令列建置 (Visual Basic)

使用 MSBuild 建置 WPF 應用程式

MSBuild 這項穩固而可擴充的技術是 .NET Framework 所引進的。MSBuild 技術的核心是跨越下表所述組件而實作的。

組件

說明

Microsoft.Build.Engine.dll

讀取和處理 MSBuild 專案檔。

Microsoft.Build.Tasks.dll

實作所有 MSBuild 專案常用的功能,包括命令列編譯引動過程 (例如 C# 的 csc.exe 和 Visual Basic 的 vbc.exe)。

Microsoft.Build.Utilities.dll

公開可以使用自訂建置功能擴充 MSBuild 的公用程式類別。

Microsoft.Build.Framework.dll

實作用於定義 MSBuild 功能與 MSBuild 引擎互動方式的介面。

Microsoft.Build.Conversion.dll

支援從舊版 Microsoft Visual Studio .NET 2002 和 Microsoft Visual Studio .NET 2003 專案檔格式到 Microsoft Visual Studio 2005 MSBuild 專案檔格式的轉換。

注意事項:

如需 MSBuild 組件的詳細資訊,請參閱 MSBuild 參考

WPF 的 MSBuild 專案檔

構成 MSBuild 的組件稱為 MSBuild 引擎。若要建置應用程式,MSBuild 引擎通常需要下列資訊:

  • 原始程式碼檔參考。

  • 相依組件參考。

  • 組態詳細資料。

  • 建置需求。

為了要讓 MSBuild 來處理,這項資訊是封裝在符合自訂 MSBuild 結構描述的 XML 檔案中 (請參閱 MSBuild 專案檔案結構描述參考)。這類檔案稱為 MSBuild 專案檔。下列是稍早使用命令列編譯器建置的 WPF 應用程式版本的 MSBuild 專案檔,再加上可延伸標記語言 (XAML) 原始程式碼檔。

<Project xmlns="https://schemas.microsoft.com/developer/msbuild/2003">
     <PropertyGroup>
         <AssemblyName>WPFApplication</AssemblyName>
         <OutputType>winexe</OutputType>
     </PropertyGroup>
     <ItemGroup>
         <Reference Include="System" />
         <Reference Include="WindowsBase" />
         <Reference Include="PresentationCore" />
         <Reference Include="PresentationFramework" />
     </ItemGroup>
     <ItemGroup>
         <ApplicationDefinition Include="App.xaml" />
         <Compile Include="App.xaml.cs" />
         <Page Include="MainWindow.xaml" />
         <Compile Include="MainWindow.xaml.cs" />
     </ItemGroup>
     <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
     <Import Project="$(MSBuildBinPath)\Microsoft.WinFX.targets" />
</Project>

本範例包含大部分 MSBuild 專案檔常用的項目,包括 Project 標記、「屬性」(Property)、「項目」(Item)、「目標」(Target) 和「工作」(Task)。

專案項目

如 MSBuild 專案檔結構描述所指定,MSBuild 專案檔是以 Project 做為最上層項目的 XML 檔案:

<Project xmlns="https://schemas.microsoft.com/developer/msbuild/2003">
     ...
</Project>

Project 項目是 MSBuild 引擎開始處理專案檔的地方。若要指定 MSBuild 專案檔做為目標的 MSBuild 版本,就要提供適當的 XML 命名空間宣告。

屬性

屬性是同時具有兩種使用目的的變數:設定 MSBuild 專案並提供建置特定的資訊給 MSBuild 引擎。屬性是包含在 PropertyGroup 項目內的,如下列範例所示。

<Project xmlns="https://schemas.microsoft.com/developer/msbuild/2003">
     <PropertyGroup>
         <AssemblyName>WPFApplication</AssemblyName>
         <OutputType>winexe</OutputType>
     </PropertyGroup>
     ...
</Project>

有些所有應用程式類型常用的屬性,例如 AssemblyName 和 OutputType,在一般 MSBuild 專案屬性中有提供描述說明。下表列出專屬於 WPF 的 MSBuild 屬性。

屬性

說明

OutputType

指定所建置組件的類型,為下列其中一值:

  • winexe:建置可執行組件 (.exe)。獨立應用程式和 XBAP 是以這種輸出類型設定的。

  • library:建置程式庫組件 (.dll)。共用組件和自訂控制項程式庫是以這種輸出類型設定的。

HostInBrowser

指定 WPF 應用程式是否要裝載於瀏覽器中,為下列其中一值:

  • true:建立的 XBAP 包含主應用程式組件 (.exe)、部署資訊清單 (applicationName.xbap) 和應用程式資訊清單 (applicationName.exe.manifest)。

  • false:建立獨立應用程式。

如果 HostInBrowser 是 true,則 OutputType 必須是 winexe。

Install

指定 XBAP 是否安裝在用戶端上。Install 可以是 true 或 false,且值跟 HostInBrowser 相反。

GenerateManifests

指定獨立應用程式是否要使用 ClickOnce 部署發行,為下列其中一值:

  • true:建立主應用程式可執行檔、部署資訊清單 (applicationName.application) 和應用程式資訊清單 (applicationName.exe.manifest)。

  • false:只建立應用程式可執行檔 (.exe)。

只有在 Install 的值為 true 時才使用 GenerateManifests。

UICulture

指定要建置組件的地區設定 (Locale)。在有指定時,宣告為 Resource 專案項目和語言特定資源的檔案,會編譯成所要地區設定的附屬組件。另一方面,非語言相關的內容會編譯到主要組件中。根據預設,應用程式不用當地語系化,因而資源檔會內嵌到主要組件中。

注意事項:

在有設定 UICulture 時,非語言相關的資源必須使用 NeutralResourcesLanguageAttribute 指定。這個屬性必須加入到 WPF 應用程式的 AssemblyInfo 檔案中。

項目

項目 (Item) 是在建置過程期間 MSBuild 引擎所處理的 MSBuild 輸入。項目 (Item) 是包含在 ItemGroup 項目 (Element) 內。

<Project xmlns="https://schemas.microsoft.com/developer/msbuild/2003">
     ...
     <ItemGroup>
         <Reference Include="System" />
         <Reference Include="WindowsBase" />
         <Reference Include="PresentationCore" />
         <Reference Include="PresentationFramework" />
     </ItemGroup>
     <ItemGroup>
         <ApplicationDefinition Include="App.xaml" />
         <Compile Include="App.xaml.cs" />
         <Page Include="MainWindow.xaml" />
         <Compile Include="MainWindow.xaml.cs" />
     </ItemGroup>
     ...
</Project>

項目型別可以使用中繼資料設定,前述範例中的組件參考是設定為 Reference 項目,而原始程式碼檔是設定為 Compile 項目。一般 MSBuild 專案項目中會進一步討論的 Reference 和 Compile 項目,是所有 .NET Framework 應用程式中常見的。

下表列出 WPF 特定的 MSBuild 項目。

屬性

說明

ApplicationDefinition

識別用於包含應用程式定義的 XAML 標記檔案 (XAML 標記檔案的根項目為 Application)。當 Install 是 true 且 OutputType 是 winexe 時,ApplicationDefinition 是強制的。WPF 應用程式只可以有一個 ApplicationDefinition,因而 MSBuild 專案也只可以有一個該關鍵字。

Page

識別其內容要轉換為二進位格式並編譯成組件的 XAML 標記檔案。Page 項目通常會搭配程式碼後置類別而實作。

最為常見的 Page 項目是其最上層項目為下列其中一個項目的 XAML 檔案:

Resource

識別編譯為應用程式組件的資源檔。如先前所述,UICulture 會處理 Resource 項目。

Content

識別以應用程式散發的內容檔。描述內容檔的中繼資料會編譯到應用程式中 (使用 AssemblyAssociatedContentFileAttribute)。

SplashScreen

識別應用程式的啟動視窗所使用的影像檔案。PresentationBuildTasks 組件會在 App.g.cs 或 Application.g.vb 中產生程式碼,建立 SplashScreen 的執行個體,並在應用程式載入時顯示。這個項目從 Visual Studio 2008 SP1 起開始提供。

目標

目標會決定專案的建置方式並同時取決於屬性和項目。WPF 應用程式必須有語言特定的目標和 WPF 特定的目標。

<Project xmlns="https://schemas.microsoft.com/developer/msbuild/2003">
     ...
     <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
     <Import Project="$(MSBuildBinPath)\Microsoft.WinFX.targets" />
</Project>

目標是以 .targets 副檔名結束的個別檔案。隨著 .NET Framework 所包含的目標檔案是安裝在下列位置中:

%WINDIR%\Microsoft.NET\Framework\vX.X.X

語言特定的目標會建置語言特定的原始程式碼。C# 的語言特定目標是 Microsoft.CSharp.targets,而 Visual Basic 的語言特定目標是 Microsoft.VisualBasic.targets。這兩個目標都衍生自 Microsoft.Common.targets 目標並加以擴充,該目標會執行與語言無關的大量常用建置工作。如需常用的語言特定 MSBuild 目標的詳細資訊,請參閱 MSBuild .Targets 檔案

WPF 特定的建置工作是由 Microsoft.WinFX.targets 目標所執行的。這項工作包括 XAML 標記編譯、XBAP 應用程式的資訊清單產生,以及處理 WPF 資源和內容檔。

工作

工作是用於執行特定建置動作的類別。目標會結合一或多個工作以定義建置過程,MSBuild 在處理目標時會執行目標所包含的工作。常用的語言特定目標所使用的工作,是由 Microsoft.Build.Tasks 組件實作的,而專屬於 WPF 的工作是由 PresentationBuildTasks assembly 實作的。

目標提供可以建置所有標準 WPF 應用程式的支援。您也可以使用替代的工作組合以實作自訂建置行為。舉例來說,下列 MSBuild GetWinFXPath 工作是用於偵測 .NET Framework 執行階段的原生路徑,這會受到工作是否在 64 位元處理器上執行而決定:

<Project xmlns="https://schemas.microsoft.com/developer/msbuild/2003">
     <UsingTask 
         TaskName="Microsoft.Build.Tasks.Windows.GetWinFXPath" 
         AssemblyFile="C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\PresentationBuildTasks.dll" />
     <Target Name="GetWinFXPathTask">
         <GetWinFXPath
             WinFXNativePath="c:\DOTNet3Native" 
             WinFXWowPath="c:\DOTNet3WowNative" />
     </Target>
     <Import Project="$(MSBuildBinPath)\Microsoft.WinFX.targets" />
</Project>

如需常用 MSBuild 工作的詳細資訊,請參閱 MSBuild 工作參考

Windows Presentation Foundation MSBuild 專案範例

對於最常用的 WPF 應用程式類型,Windows Software Development Kit (SDK) 包含數個範例 MSBuild 專案檔:

使用 Visual Studio 建立 WPF 的 MSBuild 專案

在使用 Visual Studio 專案範本建立新的 WPF 應用程式時,Visual Studio 會自動產生 MSBuild 專案檔。舉例來說,WPF 應用程式專案範本會產生下列專案檔 (適用於 C#):

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="https://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>9.0.20726</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{E0EA3EBA-718C-4122-B20C-EB97B7DC6604}</ProjectGuid>
    <OutputType>WinExe</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>WpfApplication1</RootNamespace>
    <AssemblyName>WpfApplication1</AssemblyName>
    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <ProjectTypeGuids>
      {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};
      {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
    </ProjectTypeGuids>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Core">
      <RequiredTargetFramework>3.5</RequiredTargetFramework>
    </Reference>
    <Reference Include="System.Xml.Linq">
      <RequiredTargetFramework>3.5</RequiredTargetFramework>
    </Reference>
    <Reference Include="System.Data.DataSetExtensions">
      <RequiredTargetFramework>3.5</RequiredTargetFramework>
    </Reference>
    <Reference Include="System.Data" />
    <Reference Include="System.Xml" />
    <Reference Include="WindowsBase" />
    <Reference Include="PresentationCore" />
    <Reference Include="PresentationFramework" />
  </ItemGroup>
  <ItemGroup>
    <ApplicationDefinition Include="App.xaml">
      <Generator>MSBuild:Compile</Generator>
      <SubType>Designer</SubType>
    </ApplicationDefinition>
    <Page Include="Window1.xaml">
      <Generator>MSBuild:Compile</Generator>
      <SubType>Designer</SubType>
    </Page>
    <Compile Include="App.xaml.cs">
      <DependentUpon>App.xaml</DependentUpon>
      <SubType>Code</SubType>
    </Compile>
    <Compile Include="Window1.xaml.cs">
      <DependentUpon>Window1.xaml</DependentUpon>
      <SubType>Code</SubType>
    </Compile>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Properties\AssemblyInfo.cs">
      <SubType>Code</SubType>
    </Compile>
    <Compile Include="Properties\Resources.Designer.cs">
      <AutoGen>True</AutoGen>
      <DesignTime>True</DesignTime>
      <DependentUpon>Resources.resx</DependentUpon>
    </Compile>
    <Compile Include="Properties\Settings.Designer.cs">
      <AutoGen>True</AutoGen>
      <DependentUpon>Settings.settings</DependentUpon>
      <DesignTimeSharedInput>True</DesignTimeSharedInput>
    </Compile>
    <EmbeddedResource Include="Properties\Resources.resx">
      <Generator>ResXFileCodeGenerator</Generator>
      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
      <SubType>Designer</SubType>
    </EmbeddedResource>
    <None Include="Properties\Settings.settings">
      <Generator>SettingsSingleFileGenerator</Generator>
      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
    </None>
    <AppDesigner Include="Properties\" />
  </ItemGroup>
  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>

所產生 MSBuild 專案檔副檔名的名稱會併入原始程式碼語言:

  • 對於 C# 專案,副檔名是 .csproj。

  • 對於 Visual Basic 專案,副檔名是 **.**vbproj。

專案檔會比先前範例還要大,部分是因為額外的多個屬性。然而,額外的資訊是 Visual Studio 特有的並包括下列項目:

  • 專案組態。

  • 組建組態。

  • 原始程式碼檔關聯。

  • 預設專案屬性、資源和設定管理。

專案組態

專案組態詳細資料包括專案的唯一識別項、專案類型的唯一識別項,以及各種用於識別 .NET Framework 和 Visual Studio 版本的資料:

<Project 
  ToolsVersion="3.5"
  DefaultTargets="Build"
  xmlns="https://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <ProductVersion>9.0.20726</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{E0EA3EBA-718C-4122-B20C-EB97B7DC6604}</ProjectGuid>
    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
    <ProjectTypeGuids>
      {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};
      {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
    </ProjectTypeGuids>
  </PropertyGroup>
  ...
</Project>

組建組態

預設 Visual Studio 專案具有兩種建置組態:Debug 和 Release (請參閱組建組態)。在 MSBuild 專案檔中,這些是使用屬性設定的:

<Project ... >
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">
      Debug
    </Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <OutputType>WinExe</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>WpfApplication1</RootNamespace>
    <AssemblyName>WpfApplication1</AssemblyName>
    <FileAlignment>512</FileAlignment>
    <WarningLevel>4</WarningLevel>
    ...
  </PropertyGroup>
  ...
</Project>

目前的建置組態是由 Configuration 屬性所指定的:

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

原始程式碼檔關聯

Visual Studio 會維持相關原始程式碼檔間的關聯,例如標記和程式碼後置的檔案。這樣可以讓 Visual Studio 在 Visual Studio [方案總管] 視窗中以視覺化方式呈現關聯:

方案總管螢幕擷取畫面

相關原始程式碼檔間的關聯是使用 DependentUpon 和 SubType 中繼資料組成的:

<Project ... >
  ...
  <ItemGroup>
    <ApplicationDefinition Include="App.xaml">
      <Generator>MSBuild:Compile</Generator>
      <SubType>Designer</SubType>
    </ApplicationDefinition>
    <Page Include="Window1.xaml">
      <Generator>MSBuild:Compile</Generator>
      <SubType>Designer</SubType>
    </Page>
    <Compile Include="App.xaml.cs">
      <DependentUpon>App.xaml</DependentUpon>
      <SubType>Code</SubType>
    </Compile>
    <Compile Include="Window1.xaml.cs">
      <DependentUpon>Window1.xaml</DependentUpon>
      <SubType>Code</SubType>
    </Compile>
  </ItemGroup>
  ...
</Project>

在這個專案中,App.xaml (標記) 是與 App.xaml.cs (程式碼後置) 關聯的,而 Window1.xaml (標記) 是與 Window1.xaml.cs (程式碼後置) 關聯的。

預設專案屬性、資源和設定管理

Visual Studio 可以讓您以視覺化的方式編輯 Visual Studio 專案的屬性。這些屬性大部分會影響建置過程並儲存在 Visual Studio 所管理的 Visual Studio 專案檔中。Windows Presentation Foundation (WPF) 專案範本也會產生用於提供強型別設定和資源支援的檔案。這些全部都顯示在下圖中:

方案總管螢幕擷取畫面

這些是由 MSBuild 專案檔使用下列程式碼所管理的:

<Project xmlns="https://schemas.microsoft.com/developer/msbuild/2003">
  ...
  <ItemGroup>
    <Compile Include="Properties\AssemblyInfo.cs">
      <SubType>Code</SubType>
    </Compile>
    <Compile Include="Properties\Resources.Designer.cs">
      <AutoGen>True</AutoGen>
      <DesignTime>True</DesignTime>
      <DependentUpon>Resources.resx</DependentUpon>
    </Compile>
    <Compile Include="Properties\Settings.Designer.cs">
      <AutoGen>True</AutoGen>
      <DependentUpon>Settings.settings</DependentUpon>
      <DesignTimeSharedInput>True</DesignTimeSharedInput>
    </Compile>
    <EmbeddedResource Include="Properties\Resources.resx">
      <Generator>ResXFileCodeGenerator</Generator>
      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
      <SubType>Designer</SubType>
    </EmbeddedResource>
    <None Include="Properties\Settings.settings">
      <Generator>SettingsSingleFileGenerator</Generator>
      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
    </None>
    <AppDesigner Include="Properties\" />
  </ItemGroup>
  ...
</Project>

建置 WPF 的 MSBuild 專案

MSBuild 專案可以從命令提示字元或 Visual Studio 建置。

從命令提示字元建置 WPF 的 MSBuild 專案

MSBuild 專案的建置是藉由從 Windows 命令提示字元或是 Windows Software Development Kit (SDK) 命令提示字元呼叫 msbuild.exe 來進行的。

建置專案

若要建置 MSBuild 專案,您可以執行 msbuild.exe,傳遞所要 MSBuild 專案的檔名:

msbuild.exe msbuildprojectfile.proj

建置 Visual Studio 所產生的語言特定專案

Visual Studio 所產生的語言特定 MSBuild 專案檔:

  • 具有相關副檔名 (.csproj、.vbproj)。

  • 包含語言特定目標 (Microsoft.CSharp.targets、Microsoft.VisualBasic.targets)。

下列顯示如何從命令提示字元建置 C# 專案:

msbuild.exe VSGeneratedProjectFileForCSharp.csproj

下列顯示如何從命令提示字元建置 Visual Basic 專案:

msbuild.exe VSGeneratedProjectFileForVisualBasic.vbproj

建置 Visual Studio 所產生的方案

msbuild.exe 也會建置 Visual Studio 所產生的方案檔 (.sln):

msbuild.exe VSGeneratedSolutionFile.sln

在 Visual Studio 中建置 WPF 的 MSBuild 專案

如果使用的是 Visual Studio,您不需要從命令提示字元建置專案和方案,Visual Studio 可以讓您從 IDE 建置專案和方案。

在 Visual Studio 中建置專案

若要在 Visual Studio 中建置專案,請在 [方案總管] 視窗中以滑鼠右鍵按一下專案,並選擇 [建置]。

在 Visual Studio 中建置方案

若要建置方案,請進行下列任何一項作業:

  • 按 F6 建置方案。

  • 按 F5 以啟動偵錯方案。

  • 選擇 [建置] | [建置方案]。

  • 選擇 [偵錯] | [開始偵錯]。

  • 選擇 [偵錯] | [啟動但不偵錯]。

針對專案或方案進行任一項這些作業會讓 Visual Studio 執行 msbuild.exe,以建置適當的 MSBuild 檔案。

Windows Presentation Foundation 建置管線

建置 WPF 專案時,會同時叫用語言特定的和 WPF 特定的目標組合。執行這些目標的過程稱為建置管線,下圖說明主要步驟。

WPF 建置程序

下列小節會詳細描述這些步驟。

建置前初始化

在建置前,MSBuild 會判斷重要工具和程式庫的位置,包括下列項目:

  • .NET Framework。

  • Windows SDK 目錄。

  • WPF 參考組件的位置。

  • 組件搜尋路徑的屬性。

參考組件目錄 (%ProgramFiles%\Reference Assemblies\Microsoft\Framework\v3.0\) 是尋找組件的第一個位置。這個步驟期間,建置過程也會初始化各種屬性和項目群組並執行任何必要的清除工作。

解析參考

建置過程會找出並繫結建置應用程式專案所必要的組件。這個邏輯包含在 ResolveAssemblyReference 工作中。在專案檔中描述為 Reference 的所有組件,會隨著搜尋路徑資訊和系統上已安裝組件的中繼資料,而一起提供給工作。工作會查詢組件,並使用已安裝組件的中繼資料,以篩選出不需要顯示在輸出資訊清單中的那些核心 WPF 組件。進行這項作業是避免在 ClickOnce 資訊清單中出現重複資訊。舉例來說,因為 PresentationFramework.dll 可以視為是 WPF 的建置應用程式代表,此外,因為在每個安裝有 .NET Framework 的電腦上,所有的 WPF 組件都存在於相同位置,所以沒有需要在資訊清單中的所有 .NET Framework 參考組件上包含所有資訊。

標記編譯 - 第一階段

這個步驟會剖析並編譯 XAML 檔案,這樣執行階段就不需要花時間剖析 XML 和驗證屬性值。編譯過的 XAML 檔案會預先經過語彙基元化,這樣在執行階段的載入作業就比 XAML 檔案的載入時間快許多。

在這個步驟期間,對於屬於 Page 建置項目的每個 XAML 檔案,都會發生下列活動:

  1. 標記編譯器會剖析 XAML 檔案。

  2. 針對該 XAML 建立編譯好的表示,並複製到 obj\Release 資料夾。

  3. 建立新部分類別的 CodeDOM 表示,並複製到 obj\Release 資料夾。

此外,會針對每個 XAML 檔案產生語言特定的程式碼檔。舉例來說,對於 Visual Basic 專案中的 Page1.xaml 頁面會產生 Page1.g.vb,而對於 C# 專案中的 Page1.xaml 頁面會產生 Page1.g.cs。檔名中的 ".g" 代表檔案是產生的程式碼,具有標記檔案最上層項目 (例如 Page 或 Window) 的部分類別定義。在 C# 中使用 partial 修飾詞 (Visual Basic 中的 Extends) 宣告的類別,表示在其他地方有另一個類別宣告,通常是在程式碼後置的檔案 Page1.xaml.cs 中。

部分類別是從適當的基底類別 (例如頁面的 Page) 擴充的,並會實作 System.Windows.Markup.IComponentConnector 介面。IComponentConnector 介面具有方法可以初始化元件,並在內容中連接項目的名稱和事件。因此,產生的程式碼檔具有類似下列的方法實作:

public void InitializeComponent() {
    if (_contentLoaded) {
        return;
    }
    _contentLoaded = true;
    System.Uri resourceLocater = 
        new System.Uri(
            "window1.xaml", 
            System.UriKind.RelativeOrAbsolute);
    System.Windows.Application.LoadComponent(this, resourceLocater);
}

根據預設,標記編譯所執行的 AppDomain 與 MSBuild 引擎相同。這會提供非常重要的效能好處。這個行為可以使用 AlwaysCompileMarkupFilesInSeparateDomain 屬性進行切換。好處在於可以藉由卸載個別的 AppDomain 而卸載所有參考組件。

標記編譯 - 第二階段

並不是所有的 XAML 頁面都會在標記編譯的第一階段期間編譯。具有區域定義的型別參考的 XAML 檔案 (參考到相同專案中任何地方的程式碼所定義的型別) 就不是在第一階段編譯的。這是因為這些區域定義的型別只存在於來源中,且尚未經過編譯。為了判斷這個情況,剖析器會使用牽涉到尋找標記檔案中項目的啟發方式,例如 x:Name。找到這樣的項目後,就會將標記檔案編譯延後到程式碼檔案編譯過後,在那之後,第二階段的標記編譯才會處理這些檔案。

檔案分類

建置過程會依據輸出檔將要置放於哪個應用程式組件中,而將輸出檔放入不同的資源群組。在一般的非當地語系化應用程式中,標記為 Resource 的所有資料檔會放入主要組件 (可執行檔或程式庫)。當專案中有設定 UICulture 時,所有編譯的 XAML 檔案和特別標為語言特定的那些資源,就會放入附屬資源組件中。此外,所有非語言相關的資源會放入主要組件中。在這個建置過程中即完成該判斷。

專案檔中的 ApplicationDefinition、Page 和 Resource 建置動作,可以搭配使用 Localizable 中繼資料 (可接受值有 true 和 false),這是用來表示檔案是語言特定的還是非語言相關的。

核心編譯

核心編譯步驟牽涉到程式碼檔案的編譯。這是由語言特定的目標檔 Microsoft.CSharp.targets 和 Microsoft.VisualBasic.targets 所安排的。如果啟發方式判斷標記編譯器的單一階段即已足夠,則會產生主要組件。然而,如果專案中一或多個 XAML 檔案具有區域定義型別的參考,則會產生暫時的 .dll 檔案,這樣最後的應用程式組件就可以在標記編譯第二階段完成後建立。

資訊清單產生

在建置過程的最後,所有應用程式組件和內容檔都就緒後,就會產生應用程式的 ClickOnce 資訊清單。

部署資訊清單檔適用於描述部署模型:目前版本、更新行為,以及具有數位簽章的發行者識別。這份資訊清單是要讓處理部署作業的系統管理員來撰寫的。副檔名是 .xbap (針對 XAML 瀏覽器應用程式 (XBAP)),以及 .application (針對安裝應用程式)。前者是由 HostInBrowser 專案屬性指示的,因此資訊清單能將應用程式識別為瀏覽器裝載的。

應用程式資訊清單 (.exe.manifest 檔案) 會描述應用程式組件和相依程式庫,並列出應用程式所需的權限。這個檔案是要讓應用程式開發人員來撰寫的。為了啟動 ClickOnce 應用程式,使用者會開啟應用程式的部署資訊清單檔。

對於 XBAP,一定會建立這些資訊清單檔。對於安裝應用程式,除非專案檔中的 GenerateManifests 屬性有以值 true 指定,否則就不會建立資訊清單檔。

相較於一般的網際網路區域應用程式,XBAP 有額外的兩個權限:WebBrowserPermissionMediaPermission。WPF 建置系統會在應用程式資訊清單中宣告這些權限。

累加建置支援

WPF 建置系統提供對累加建置的支援。這個系統在偵測標記或程式碼的變更方面相當有智慧,並且只會編譯受到變更影響的那些成品。累加建置機制使用下列檔案:

  • $(AssemblyName)_MarkupCompiler.Cache 檔案,用於維護目前編譯器狀態。

  • $(AssemblyName)_MarkupCompiler.lref 檔案,用於快取具有區域定義型別參考的 XAML 檔案。

下列是控管累加建置的規則集:

  • 檔案是建置系統偵測變更的最小單位。因此對於程式碼檔,建置系統無法得知型別是否變更或是否有加入程式碼。同樣的情況也適用於專案檔。

  • 累加建置機制必須認定 XAML 頁面有定義類別或是使用其他類別。

  • 如果 Reference 項目有變更,則會重新編譯所有頁面。

  • 如果程式碼檔有變更,則會重新編譯具有區域定義型別參考的所有頁面。

  • 如果 XAML 檔案有變更:

    • 如果 XAML 在專案中是宣告為 Page:如果 XAML 沒有區域定義的型別參考,則重新編譯該 XAML,再加上具有區域參考的所有 XAML 頁面。如果 XAML 有區域參考,則重新編譯具有區域參考的所有 XAML 頁面。

    • 如果 XAML 在專案中是宣告為 ApplicationDefinition:重新編譯所有 XAML 頁面 (原因:每個 XAML 都具有可能已經變更的 Application 型別參考)。

  • 如果專案檔是將程式碼檔宣告為應用程式定義,而非 XAML 檔案:

    • 檢查專案檔中的 ApplicationClassName 值是否變更 (是否有新的應用程式類型)。如果有變更,重新編譯整個應用程式。

    • 否則,重新編譯具有區域參考的所有 XAML 頁面。

  • 如果專案檔有變更:套用所有前述規則,並查看哪些項目需要重新編譯。對下列屬性的變更會觸發完整的重新編譯:AssemblyName、IntermediateOutputPath、RootNamespace 和 HostInBrowser。

有可能會發生下列的重新編譯案例:

  • 重新編譯整個應用程式。

  • 只會重新編譯具有區域定義型別參考的那些 XAML 檔案。

  • 不會重新編譯任何項目 (當專案中沒有任何變更時)。

請參閱

概念

部署 WPF 應用程式 (WPF)

Windows Presentation Foundation 中的 Pack URI

Windows Presentation Foundation 應用程式資源、內容及資料檔案

其他資源

Windows Presentation Foundation MSBuild 參考

變更記錄

日期

記錄

原因

2008 年 7 月

加入 SplashScreen 建置屬性的相關資訊。

SP1 功能變更。