面向 .NET Framework 的编程语言将使用 MSBuild 项目文件来介绍并控制应用程序生成过程。使用 Visual Studio 创建 MSBuild 项目文件时,会自动将适当的 XML 添加到该文件。但是,你可能会发现,了解 XML 的组织方式以及如何能够更改 XML 来控制生成将非常有用。
有关创建 C++ 项目的项目文件的信息,请参阅MSBuild (Visual C++)。
此演练演示如何只使用文本编辑器以增量方式创建基本项目文件。演练采用以下步骤:
-
创建最小的应用程序源文件。
-
创建最小的 MSBuild 项目文件。
-
扩展 PATH 环境变量以包括 MSBuild。
-
使用项目文件生成应用程序。
-
添加属性以控制生成。
-
通过更改属性值来控制生成。
-
将目标添加到生成。
-
通过指定目标来控制生成。
-
以增量方式生成。
此演练演示如何在命令提示符下生成项目并检查结果。有关 MSBuild 以及如何在命令提示符下运行 MSBuild 的详细信息,请参阅 演练:使用 MSBuild。
若要完成演练,你必须安装 .NET Framework(版本 2.0、3.5、4.0 或 4.5),因为其中包括演练所需的 MSBuild 和 Visual C# 编译器。
本节演示如何使用文本编辑器创建最小的 Visual C# 应用程序源文件。
创建最小的应用程序
-
在命令提示符下,浏览到要在其中创建应用程序的文件夹,例如,\My Documents\ 或 \Desktop\。
-
键入 md HelloWorld 创建名为 \HelloWorld\ 的子文件夹。
-
键入 cd HelloWorld 切换到该新文件夹。
-
启动记事本或其他文本编辑器,然后键入以下代码。
using System; class HelloWorld { static void Main() { #if DebugConfig Console.WriteLine("WE ARE IN THE DEBUG CONFIGURATION"); #endif Console.WriteLine("Hello, world!"); } }
-
保存此源代码文件,并将其命名为 Helloworld.cs。
-
在命令提示符下,键入 csc helloworld.cs 来生成应用程序。
-
在命令提示符下,键入 helloworld 测试应用程序。
此时应显示 Hello, world! 消息。
-
在命令提示符下,键入 del helloworld.exe 删除应用程序。
既然有了最小的应用程序源文件,你就可以创建最小的项目文件来生成应用程序。此项目文件包含以下元素:
-
必需的根 Project 节点。
-
用于包含项元素的 ItemGroup 节点。
-
引用应用程序源文件的项元素。
-
一个 Target 节点,用于包含生成应用程序所需的任务。
-
一个 Task 元素,用于启动 Visual C# 编译器以生成应用程序。
创建最小的 MSBuild 项目文件
-
在文本编辑器中,用以下两行替换现有文本:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> </Project>
-
插入此 ItemGroup 节点,作为 Project 节点的子元素:
<ItemGroup> <Compile Include="helloworld.cs" /> </ItemGroup>
请注意,此 ItemGroup 已包含一个项元素。
-
添加一个 Target 节点,作为 Project 节点的子元素。将该节点命名为 Build。
<Target Name="Build"> </Target>
-
插入此 task 元素,作为 Target 节点的子元素:
<Csc Sources="@(Compile)"/>
-
保存此项目文件,并将其命名为 Helloworld.csproj。
你的最小项目文件应类似于以下代码:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> <Compile Include="helloworld.cs" /> </ItemGroup> <Target Name="Build"> <Csc Sources="@(Compile)"/> </Target> </Project>
Build 目标中的任务按顺序执行。在本例中,Visual C# 编译器 Csc 任务是唯一的任务。它需要编译一系列源文件,这一系列文件由 Compile 项的值指定。 Compile 项只引用一个源文件,即 Helloworld.cs。
![]() |
---|
在项元素中,可以使用星号通配符 (*) 来引用文件扩展名为 .cs 的所有文件,如下所示: <Compile Include="*.cs" /> 但是,建议不要使用通配符,因为在添加或删除了源文件的情况下,这样会使调试和选择性目标设定更为困难。 |
必须先扩展 PATH 环境变量以包括 .NET Framework 文件夹,然后才能访问 MSBuild。
向你的路径添加 MSBuild
-
从 Visual Studio 2013 开始,你可以在 MSBuild 文件夹中查找 MSBuild.exe(32 位操作系统上的 %ProgramFiles%\MSBuild,或者 64 位操作系统上的 %ProgramFiles(x86)%\MSBuild)。
在命令提示符处,键入 set PATH=%PATH%;%ProgramFiles%\MSBuild 或 set PATH=%PATH%;%ProgramFiles(x86)%\MSBuild。
或者,如果安装了 Visual Studio,则可以使用“Visual Studio 命令提示”,其中有包括 MSBuild 文件夹的路径。
现在,为了生成应用程序,请使用刚刚创建的项目文件。
生成应用程序
-
在命令提示符处,键入 msbuild helloworld.csproj /t:Build。
此操作将调用 Visual C# 编译器来创建 Helloworld 应用程序,从而生成 Helloworld 项目文件的 Build 目标。
-
通过键入 helloworld 测试应用程序。
此时应显示 Hello, world! 消息。
![]() |
---|
可以通过提高详细信息级别来查看有关生成的更多详细信息。要将详细信息级别设置为“详细”,请在命令提示符下键入以下任一命令: msbuild helloworld.csproj /t:Build /verbosity:detailed |
可以将生成属性添加到项目文件中,从而进一步控制生成。现在添加以下属性:
-
一个 AssemblyName 属性,用于指定应用程序的名称。
-
一个 OutputPath 属性,用于指定要包含应用程序的文件夹。
添加生成属性
-
在命令提示符下,键入 del helloworld.exe 删除现有应用程序。
-
在项目文件中,插入此 PropertyGroup 元素,置于起始 Project 元素的后面:
<PropertyGroup> <AssemblyName>MSBuildSample</AssemblyName> <OutputPath>Bin\</OutputPath> </PropertyGroup>
-
将此任务添加到 Build 目标,置于 Csc 任务的前面:
<MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" />
MakeDir 任务将创建一个由 OutputPath 属性命名的文件夹,前提是当前不存在具有该名称的文件夹。
-
将此 OutputAssembly 特性添加到 Csc 任务:
<Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe" />
这将指示 Visual C# 编译器生成由 AssemblyName 属性命名的程序集,并将其放在由 OutputPath 属性命名的文件夹中。
-
保存更改。
你的项目文件现在应类似于以下代码:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <AssemblyName>MSBuildSample</AssemblyName> <OutputPath>Bin\</OutputPath> </PropertyGroup> <ItemGroup> <Compile Include="helloworld.cs" /> </ItemGroup> <Target Name="Build"> <MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" /> <Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe" /> </Target> </Project>
![]() |
---|
当你在 OutputPath 元素中指定文件夹名称时,建议你在文件夹名称的末尾添加反斜杠 (\) 路径分隔符,而不是将其添加到 OutputAssembly任务的 Csc 特性中。因此, <OutputPath>Bin\</OutputPath> OutputAssembly=="$(OutputPath)$(AssemblyName).exe" /> 优于 <OutputPath>Bin</OutputPath> OutputAssembly=="$(OutputPath)\$(AssemblyName).exe" /> |
现在即可使用项目文件来生成应用程序,在该项目文件中,你使用了生成属性来指定输出文件夹和应用程序名称。
测试生成属性
-
在命令提示符处,键入 msbuild helloworld.csproj /t:Build。
这将创建 \Bin\ 文件夹,然后调用 Visual C# 编译器创建 MSBuildSample 应用程序,并将其放在 \Bin\ 文件夹中。
-
要验证 \Bin\ 文件夹是否已创建,以及该文件夹是否包含 MSBuildSample 应用程序,请键入 dir Bin。
-
通过键入 Bin\MSBuildSample 测试应用程序。
此时应显示 Hello, world! 消息。
接下来,向项目文件中另外添加两个目标,如下所示:
-
一个用于删除旧文件的 Clean 目标。
-
一个 Rebuild 目标,该目标使用 DependsOnTargets 特性,强制使 Clean 任务在 Build 任务之前运行。
既然有多个目标,就可以将 Build 目标设置为默认目标。
添加生成目标
-
在项目文件中添加以下两个目标,置于 Build 目标的后面:
<Target Name="Clean" > <Delete Files="$(OutputPath)$(AssemblyName).exe" /> </Target> <Target Name="Rebuild" DependsOnTargets="Clean;Build" />
Clean 目标调用 Delete 任务来删除应用程序。在 Clean 目标和 Build 目标均已运行之前,Rebuild 目标不会运行。尽管 Rebuild 目标没有任务,但它可使 Clean 目标在 Build 目标之前运行。
-
将此 DefaultTargets 特性添加到起始 Project 元素:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
这会将 Build 目标设置为默认目标。
你的项目文件现在应类似于以下代码:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <AssemblyName>MSBuildSample</AssemblyName> <OutputPath>Bin\</OutputPath> </PropertyGroup> <ItemGroup> <Compile Include="helloworld.cs" /> </ItemGroup> <Target Name="Build"> <MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" /> <Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe" /> </Target> <Target Name="Clean" > <Delete Files="$(OutputPath)$(AssemblyName).exe" /> </Target> <Target Name="Rebuild" DependsOnTargets="Clean;Build" /> </Project>
可以执行新的生成目标来测试项目文件的以下功能:
-
生成默认生成。
-
在命令提示符下设置应用程序名称。
-
在生成其他应用程序之前删除应用程序。
-
删除应用程序,而不生成其他应用程序。
测试生成目标
-
在命令提示符处,键入 msbuild helloworld.csproj /p:AssemblyName=Greetings。
由于未使用 /t 开关显式地设置目标,因此 MSBuild 将运行默认的 Build 目标。 /p 开关将重写 AssemblyName 属性,并为其指定新值Greetings。这将导致在 \Bin\ 文件夹中创建一个新应用程序 Greetings.exe。
-
要验证 \Bin\ 文件夹是否同时包含 MSBuildSample 应用程序和新的 Greetings 应用程序,请键入 dir Bin。
-
通过键入 Bin\Greetings 测试 Greetings 应用程序。
此时应显示 Hello, world! 消息。
-
通过键入 msbuild helloworld.csproj /t:clean 删除 MSBuildSample 应用程序。
这将运行 Clean 任务,以移除具有默认 AssemblyName 属性值 MSBuildSample 的应用程序。
-
通过键入 msbuild helloworld.csproj /t:clean /p:AssemblyName=Greetings 删除 Greetings 应用程序。
这将运行 Clean 任务,以移除具有指定 AssemblyName 属性值 Greetings 的应用程序。
-
要验证 \Bin\ 文件夹现在是否为空,请键入 dir Bin。
-
键入 msbuild。
尽管未指定项目文件,但 MSBuild 会生成 helloworld.csproj 文件,因为当前文件夹中只有一个项目文件。这将导致在 \Bin\ 文件夹中创建 MSBuildSample 应用程序。
要验证 \Bin\ 文件夹是否包含 MSBuildSample 应用程序,请键入 dir Bin。
可以指示 MSBuild 仅在目标所依赖的源文件或目标文件发生更改时才生成目标。MSBuild 使用文件的时间戳来确定文件是否已更改。
以增量方式生成
-
在项目文件中,将以下特性添加到起始 Build 目标:
Inputs="@(Compile)" Outputs="$(OutputPath)$(AssemblyName).exe"
它指定 Build 目标依赖于 Compile 项组中指定的输入文件,并且输出目标为应用程序文件。
生成的 Build 目标应类似于以下代码:
<Target Name="Build" Inputs="@(Compile)" Outputs="$(OutputPath)$(AssemblyName).exe"> <MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" /> <Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe" /> </Target>
-
在命令提示符下,键入 msbuild /v:d 测试 Build 目标。
请记住,helloworld.csproj 是默认项目文件,并且 Build 为默认目标。
/v:d 开关指定生成过程的详细说明。
此时应显示以下各行:
Skipping target "Build" because all output files are up-to-date with respect to the input files.
Input files: HelloWorld.cs
Output files: Bin\MSBuildSample.exe
MSBuild 将跳过 Build 目标,原因是自上次生成应用程序以来没有任何源文件发生更改。
下面的示例演示一个项目文件,该项目文件编译 Visual C# 应用程序,并记录一条包含输出文件名的消息。
<Project DefaultTargets = "Compile" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" > <!-- Set the application name as a property --> <PropertyGroup> <appname>HelloWorldCS</appname> </PropertyGroup> <!-- Specify the inputs by type and file name --> <ItemGroup> <CSFile Include = "consolehwcs1.cs"/> </ItemGroup> <Target Name = "Compile"> <!-- Run the Visual C# compilation using input files of type CSFile --> <CSC Sources = "@(CSFile)" OutputAssembly = "$(appname).exe"> <!-- Set the OutputAssembly attribute of the CSC task to the name of the executable file that is created --> <Output TaskParameter = "OutputAssembly" ItemName = "EXEFile" /> </CSC> <!-- Log the file name of the output file --> <Message Text="The output file is @(EXEFile)"/> </Target> </Project>
下面的示例演示一个项目文件,该项目文件编译 Visual Basic 应用程序,并记录一条包含输出文件名的消息。
<Project DefaultTargets = "Compile" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" > <!-- Set the application name as a property --> <PropertyGroup> <appname>HelloWorldVB</appname> </PropertyGroup> <!-- Specify the inputs by type and file name --> <ItemGroup> <VBFile Include = "consolehwvb1.vb"/> </ItemGroup> <Target Name = "Compile"> <!-- Run the Visual Basic compilation using input files of type VBFile --> <VBC Sources = "@(VBFile)" OutputAssembly= "$(appname).exe"> <!-- Set the OutputAssembly attribute of the VBC task to the name of the executable file that is created --> <Output TaskParameter = "OutputAssembly" ItemName = "EXEFile" /> </VBC> <!-- Log the file name of the output file --> <Message Text="The output file is @(EXEFile)"/> </Target> </Project>
Visual Studio 能够自动执行本演练中演示的大部分工作。若要了解如何使用 Visual Studio 来创建、编辑、生成和测试 MSBuild 项目文件,请参阅演练:使用 MSBuild。