生成 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 标记、属性、项、目标和任务。

Project 元素

正如 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)、部署清单(应用程序名称.xbap)和应用程序清单(应用程序名称.exe.manifest)。

  • false:创建独立应用程序。

如果 HostInBrowser 为 true,则 OutputType 必须是 winexe。

Install

指定是否在客户端上安装 XBAP。Install 可以为 true 或 false,并且其值与 HostInBrowser 相反。

GenerateManifests

指定是否使用 ClickOnce 部署发布独立应用程序,为下列值之一:

  • true:创建主应用程序可执行文件、部署清单(应用程序名称.application)和应用程序清单(应用程序名称.exe.manifest)。

  • false:只创建应用程序可执行文件 (.exe)。

仅当 Install 具有值 true 时才使用 GenerateManifests。

UICulture

指定要为其生成程序集的区域设置。指定该属性后,声明为 Resource 项目项和语言特定资源的文件将被编译到预期区域设置的附属程序集中。另一方面,非特定语言的内容被编译到主程序集中。默认情况下,应用程序不进行本地化,因此资源文件被嵌入到主程序集中。

说明:

如果设置了 UICulture,则必须使用 NeutralResourcesLanguageAttribute 指定非特定资源语言。必须将此属性添加到 WPF 应用程序的 AssemblyInfo 文件中。

项是由 MSBuild 引擎在生成过程中处理的 MSBuild 输入。项包含在 ItemGroup 元素中。

<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 项。Reference 和 Compile 项为所有 .NET Framework 应用程序所共有,常用的 MSBuild 项目项中对其进行详细介绍。

下表中列出了特定于 WPF 的 MSBuild 项。

属性

说明

ApplicationDefinition

标识包含应用程序定义的 XAML 标记文件(根元素为 Application 的 XAML 标记文件)。当 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 程序集实现。

目标为生成所有标准 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 项目示例

Windows 软件开发工具包 (SDK) 包含最常见类型的 WPF 应用程序的多个示例 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 项目

可以从命令提示符处或 Visual Studio 生成 MSBuild 项目。

从命令提示符处生成 WPF MSBuild 项目

可以通过从 Windows 命令提示符处或 Windows 软件开发工具包 (SDK) 命令提示符处调用 msbuild.exe 来生成 MSBuild 项目。

生成项目

若要生成 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 上为其生成的应用程序的代表性程序集,而且因为所有 WPF 程序集在每台安装了 .NET Framework 的计算机上都存在于同一位置,所以无需在清单中包含有关所有 .NET Framework 引用程序集的所有信息。

标记编译 — 第 1 趟

在此步骤中,将分析和编译 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);
}

默认情况下,标记编译在与 MSBuild 引擎相同的 AppDomain 中运行。这样可以显著提高性能。可以使用 AlwaysCompileMarkupFilesInSeparateDomain 属性切换此行为。其优点是可以通过卸载单独的 AppDomain 来卸载所有引用程序集。

标记编译 — 第 2 趟

并非所有 XAML 页都在标记编译的第 1 趟中得到编译。包含本地定义类型引用(对在同一项目中其他位置的代码中定义的类型的引用)的 XAML 文件此时将免于编译。这是因为这些本地定义的类型仅存在于源中,并且尚未进行编译。分析器使用试探法来确定这一点,这需要在标记文件中查找 x:Name 之类的项。如果找到这样的实例,则标记文件的编译将推迟至代码文件编译之后完成,此时,第二趟标记编译将处理这些文件。

文件分类

生成过程根据用来存放输出文件的应用程序集的不同将这些文件放在不同的资源组中。在典型的非本地化应用程序中,所有被标记为 Resource 的数据文件都将放在主程序集(可执行文件或库)中。如果在项目中设置了 UICulture,则所有经过编译的 XAML 文件以及那些被专门标记为特定于语言的资源都放在附属资源程序集中。此外,所有非特定语言的资源都放在主程序集中。在生成过程的这一步骤中,将做出这一决定。

项目文件中的 ApplicationDefinition、Page 和 Resource 生成操作可以使用 Localizable 元数据(可接受的值为 true 和 false)进行扩充,此元数据指示该文件是特定于语言的还是非特定语言的。

核心编译

核心编译步骤包括代码文件的编译。这是在特定于语言的目标文件 Microsoft.CSharp.targets 和 Microsoft.VisualBasic.targets 中的逻辑协调下进行的。如果试探法确定标记编译器运行一趟就足够了,则生成主程序集。但是,如果项目中的一个或多个 XAML 文件具有对本地定义类型的引用,则生成一个临时 .dll 文件,以便可以在第二趟标记编译完成之后创建最终的应用程序集。

清单生成

在生成过程的末尾,当所有应用程序集和内容文件都准备好之后,将生成应用程序的 ClickOnce 清单。

部署清单文件描述部署模型:当前版本、更新行为、发行者标识以及数字签名。此清单应该由处理部署的管理员创作。对于 XAML 浏览器应用程序 (XBAP),文件扩展名为 .xbap;对于安装的应用程序,文件扩展名为 .application。前者由 HostInBrowser 项目属性指示,因此,清单将应用程序标识为浏览器承载的应用程序。

应用程序清单(.exe.manifest 文件)描述应用程序集和依赖库,并列出应用程序所需的权限。此文件应该由应用程序开发人员创作。为了启动 ClickOnce 应用程序,用户应该打开应用程序的部署清单文件。

对于 XBAP,始终会创建这些清单文件。对于安装的应用程序,除非在项目文件中使用值 true 指定 GenerateManifests 属性,否则不会创建它们。

除了分配给典型的 Internet 区域应用程序的那些权限以外,XBAP 还获得了两项额外的权限:WebBrowserPermissionMediaPermission。WPF 生成系统在应用程序清单中声明这些权限。

增量生成支持

WPF 生成系统为增量生成提供了支持。它相当智能地检测对标记或代码所做的更改,并且仅编辑那些受到更改影响的项目。增量生成机制使用下列文件:

  • 一个 $(程序集名称)_MarkupCompiler.Cache 文件,用于保持当前编译器状态。

  • 一个 $(程序集名称)_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 功能更改。