配置目标和任务
当开发计算机支持目标环境时,可将所选的 MSBuild 任务设置为在目标环境中运行。 例如,当使用 64 位 Windows 计算机生成面向 32 位 Windows 体系结构的应用程序时,将在 32 位进程中运行所选的任务。
注意
如果生成任务采用 .NET 语言(例如 Visual C# 或 Visual Basic)编写,并且不使用本机资源或工具,则该任务无需修改便可在任何目标上下文中运行。
UsingTask 属性和任务参数
以下 UsingTask
属性影响特定生成过程中任务的所有操作:
Runtime
属性(如果存在)可设置公共语言运行时 (CLR) 版本,并可采用以下值之一:CLR2
、CLR4
、CurrentRuntime
或*
(任何运行时)。Architecture
属性(如果存在)可设置平台和位数,并可采用以下值之一:x86
、x64
、CurrentArchitecture
或*
(任何体系结构)。TaskFactory
属性(如果存在)可设置创建和运行任务实例的任务工厂,并仅使用值TaskHostFactory
。 有关详细信息,请参阅本文档后面的任务工厂部分。
<UsingTask TaskName="SimpleTask"
Runtime="CLR2"
Architecture="x86"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v3.5.dll" />
还可以使用 MSBuildRuntime
和 MSBuildArchitecture
参数来设置单个任务调用的目标上下文。
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="MyTarget">
<SimpleTask MSBuildRuntime="CLR2" MSBuildArchitecture= "x86"/>
</Target>
</Project>
在 MSBuild 运行任务之前,它将查找具有相同目标上下文的匹配 UsingTask
。 在 UsingTask
中指定的参数(但不在相应的任务中)视为要进行匹配的参数。 在任务中指定的参数(但不在相应的 UsingTask
中)也视为要进行匹配的参数。 如果未在 UsingTask
或任务中指定参数值,则该值将默认为 *
(任何参数)。
警告
如果存在多个 UsingTask
且它们都具有匹配的 TaskName
、Runtime
和 Architecture
属性,则要进行评估的第一个值将替换其他值。 这一点与 Property
和 Target
元素的行为不同。
如果对任务设置参数,则 MSBuild 将尝试查找匹配这些参数或至少不与这些参数冲突的 UsingTask
。 多个 UsingTask
可指定具有相同任务的目标上下文。 例如,针对不同的目标环境具有不同的可执行文件的任务可能类似于:
<UsingTask TaskName="MyTool"
Runtime="CLR2"
Architecture="x86"
AssemblyFile="$(MyToolsPath)\MyTool.v2.0.dll" />
<UsingTask TaskName="MyTool"
Runtime="CLR4"
Architecture="x86"
AssemblyFile="$(MyToolsPath)\MyTool.4.0.dll" />
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="MyTarget">
<MyTool MSBuildRuntime="CLR2" MSBuildArchitecture= "x86"/>
</Target>
</Project>
重写默认 UsingTasks
默认情况下,MSBuild 将 UsingTask 视为“第一个优先”。从 17.2 开始,MSBuild 支持通过 Override
参数重写此行为。 将参数 Override
设置为 true
的 UsingTask 优先于同一 TaskName 的任何其他 UsingTask。
<UsingTask TaskName="MyTool"
Runtime="CLR4"
Architecture="x86"
Override="true"
AssemblyFile="$(MyToolsPath)\MyTool.4.0.dll" />
警告
每个任务只能执行此操作一次。 尝试为同一任务添加多个替代的生成将收到 MSBuild 错误 MSB4275
。
任务工厂
下表显示了 MSBuild 安装提供的任务工厂:
任务工厂 | 说明 |
---|---|
AssemblyTaskFactory |
这是默认值。 在进程内运行任务。 |
TaskHostFactory |
在进程外运行任务。 |
RoslynCodeTaskFactory |
用于用 C# 或 Visual Basic 编写的内联任务,并以 .NET Standard 为目标;同时适用于 msbuild.exe 和 dotnet build 。 |
CodeTaskFactory |
用于用 C# 或 Visual Basic 编写的内联任务,并以 .NET Framework 为目标;仅适用于 msbuild.exe 。 |
任务工厂机制是可扩展的,因此可以使用第三方创建的机制,也可以创建自己的机制。 创建机制的原因是为了支持另一种语言来编写内联任务。
TaskHostFactory
在其运行任务之前,MSBuild 将检查该任务是否指定为在当前软件上下文中运行。 如果该任务指定为在当前软件上下文中运行,则 MSBuild 将其传递给 AssemblyTaskFactory
(它在当前进程中运行该任务);否则,MSBuild 将其传递给 TaskHostFactory
(它在匹配目标上下文的进程中运行该任务)。 即使当前上下文和目标上下文互相匹配,也可以通过将 TaskFactory
设置为 TaskHostFactory
,强制任务在进程外运行(出于隔离、安全性或其他原因)。
<UsingTask TaskName="MisbehavingTask"
TaskFactory="TaskHostFactory"
AssemblyFile="$(MSBuildToolsPath)\MyTasks.dll">
</UsingTask>
显式指定 TaskHostFactory
时,运行任务的过程是短暂的。 这样,操作系统就可以在任务执行后立即清理与任务相关的所有资源。 因此,请在引用与其使用相同的生成过程中生成的任务时指定 TaskHostFactory
,以避免在生成后更新任务程序集时出现文件正在使用错误。
RoslynCodeTaskFactory
RoslynCodeTaskFactory
提供了一种机制,可以通过该机制为项目文件中的任务编写 C# 或 Visual Basic 代码以供立即使用。 代码是在生成过程中编译的,以生成可以在同一生成中执行的任务。 编写的代码面向 .NET Standard,因此可以在运行 dotnet build
时使用它,其使用 MSBuild 的 .NET Core(和 .NET 5 及更高版本)以及 msbuild.exe
(其使用 .NET Framework)。 RoslynCodeTaskFactory
最适合在 MSBuild 逻辑中难以执行的自定义,但又不够复杂,无法创建单独的项目。 请参阅使用 RoslynCodeTaskFactory 创建 MSBuild 内联任务。
CodeTaskFactory
CodeTaskFactory
是 RoslynCodeTaskFactory
的旧版本,仅限于 MSBuild 的 .NET Framework 版本。 请参阅 MSBuild 内联任务。 支持此任务工厂,但较新的代码应使用 RoslynCodeTaskFactory
以获得更广泛的适用性。
虚拟任务参数
与任何其他任务参数类似,可以从生成属性设置 MSBuildRuntime
和 MSBuildArchitecture
。
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<FrameworkVersion>3.0</FrameworkVersion>
</PropertyGroup>
<Target Name="MyTarget">
<SimpleTask MSBuildRuntime="$(FrameworkVerion)" MSBuildArchitecture= "x86"/>
</Target>
</Project>
与其他任务参数不同,MSBuildRuntime
和 MSBuildArchitecture
并不对任务本身显示。 若要编写可识别其运行的上下文的任务,必须通过调用 .NET Framework 来测试上下文,或使用生成属性通过其他任务参数来传递上下文信息。
注意
可通过工具集和环境属性设置 UsingTask
特性。
MSBuildRuntime
和 MSBuildArchitecture
参数提供设置目标上下文的最灵活方式,但其范围也最受限制。 一方面,因为这些参数是在任务实例本身上设置的,并在任务运行之前不会进行计算,因此可从计算时和生成时都可用的全部属性范围中派生其值。 另一方面,这些参数仅适用于特定目标中任务的特定实例。
注意
任务参数在父节点的上下文中,而不是在任务主机的上下文中进行计算。 运行时相关或体系结构相关的环境变量(例如程序文件位置)将计算为与该父节点匹配的值。 但是,如果同一个环境变量直接由任务读取,则它会在任务主机的上下文中正确计算。