配置目标和任务

当开发计算机支持目标环境时,可将所选的 MSBuild 任务设置为在目标环境中运行。 例如,当使用 64 位 Windows 计算机生成面向 32 位 Windows 体系结构的应用程序时,将在 32 位进程中运行所选的任务。

注意

如果生成任务采用 .NET 语言(例如 Visual C# 或 Visual Basic)编写,并且不使用本机资源或工具,则该任务无需修改便可在任何目标上下文中运行。

UsingTask 属性和任务参数

以下 UsingTask 属性影响特定生成过程中任务的所有操作:

  • Runtime 属性(如果存在)可设置公共语言运行时 (CLR) 版本,并可采用以下值之一:CLR2CLR4CurrentRuntime*(任何运行时)。

  • Architecture 属性(如果存在)可设置平台和位数,并可采用以下值之一:x86x64CurrentArchitecture*(任何体系结构)。

  • TaskFactory 属性(如果存在)可设置创建和运行任务实例的任务工厂,并仅使用值 TaskHostFactory。 有关详细信息,请参阅本文档后面的任务工厂部分。

<UsingTask TaskName="SimpleTask"
    Runtime="CLR2"
    Architecture="x86"
    AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v3.5.dll" />

还可以使用 MSBuildRuntimeMSBuildArchitecture 参数来设置单个任务调用的目标上下文。

<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 且它们都具有匹配的 TaskNameRuntimeArchitecture 属性,则要进行评估的第一个值将替换其他值。 这一点与 PropertyTarget 元素的行为不同。

如果对任务设置参数,则 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.exedotnet 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

CodeTaskFactoryRoslynCodeTaskFactory 的旧版本,仅限于 MSBuild 的 .NET Framework 版本。 请参阅 MSBuild 内联任务。 支持此任务工厂,但较新的代码应使用 RoslynCodeTaskFactory 以获得更广泛的适用性。

虚拟任务参数

与任何其他任务参数类似,可以从生成属性设置 MSBuildRuntimeMSBuildArchitecture

<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>

与其他任务参数不同,MSBuildRuntimeMSBuildArchitecture 并不对任务本身显示。 若要编写可识别其运行的上下文的任务,必须通过调用 .NET Framework 来测试上下文,或使用生成属性通过其他任务参数来传递上下文信息。

注意

可通过工具集和环境属性设置 UsingTask 特性。

MSBuildRuntimeMSBuildArchitecture 参数提供设置目标上下文的最灵活方式,但其范围也最受限制。 一方面,因为这些参数是在任务实例本身上设置的,并在任务运行之前不会进行计算,因此可从计算时和生成时都可用的全部属性范围中派生其值。 另一方面,这些参数仅适用于特定目标中任务的特定实例。

注意

任务参数在父节点的上下文中,而不是在任务主机的上下文中进行计算。 运行时相关或体系结构相关的环境变量(例如程序文件位置)将计算为与该父节点匹配的值。 但是,如果同一个环境变量直接由任务读取,则它会在任务主机的上下文中正确计算。