配置目标和任务

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

注释

如果生成任务是使用 .NET 语言(如 Visual C# 或 Visual Basic)编写的,并且不使用本机资源或工具,则可以在任何目标上下文中运行,而无需适应。

UsingTask 属性和任务参数

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

  • 属性Runtime(如果存在)设置公共语言运行时(CLR)版本,并可以采用以下任何一个值:CLR2、、 CLR4CurrentRuntimeNET、(从 .NET SDK 10/Visual Studio 2026/MSBuild 18.0 开始)或*(任何运行时)。

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

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

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

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

<Project>
    <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>
    <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 安装提供的任务工厂:

任务工厂 DESCRIPTION
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与目标上下文匹配的进程中的任务。 即使当前上下文和目标上下文匹配,也可以通过设置为 TaskFactoryTaskHostFactory 强制任务运行进程外(出于隔离、安全性或其他原因)。

<UsingTask TaskName="MisbehavingTask"
    TaskFactory="TaskHostFactory"
    AssemblyFile="$(MSBuildToolsPath)\MyTasks.dll">
</UsingTask>

显式指定时 TaskHostFactory ,运行任务的进程生存期较短。 这样,作系统就可以在任务执行后立即清理与任务相关的所有资源。 出于此原因,指定 TaskHostFactory 在引用生成过程中生成的任务与使用相同的生成过程时,以避免在生成后更新任务程序集时出现文件内使用错误。

RoslynCodeTaskFactory

RoslynCodeTaskFactory 机制提供了一种机制,你可以通过该机制为项目文件中的任务编写 C# 或 Visual Basic 代码以供立即使用。 代码在生成过程中进行编译,以生成可在同一生成中执行的任务。 编写的代码面向 .NET Standard,因此可以在运行 dotnet build时使用它,该代码使用 MSBuild msbuild.exe的 .NET Core(和 .NET 5 及更高版本)以及使用 .NET Framework。 RoslynCodeTaskFactory 最适合在 MSBuild 逻辑中难以执行的自定义,但不够复杂,无法创建单独的项目。 请参阅 使用 RoslynCodeTaskFactory 创建 MSBuild 内联任务

CodeTaskFactory

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

MSBuild 中的 TaskHosts

MSBuild 在生成过程中执行任务,有时这些任务需要在与默认生成进程不同的运行时或体系结构上下文中运行。 为了支持这一点,MSBuild 可以使用“TaskHost”,这是一个单独的 MSBuild 进程,负责在请求的环境中运行任务。 TaskHosts 确保针对不同框架或平台的隔离、兼容性和支持。

从历史上看,TaskHosts 允许任务在特定版本的单独 .NET Framework 进程中运行(例如 CLR2 或 CLR4)。 此支持受项目文件或目标文件中<UsingTask>元素的RuntimeArchitecture属性的支配:

  • Architecture可以指定值,例如x86x64CurrentArchitecture* “任何体系结构”。
  • Runtime 可以指定值,例如 CLR2CLR4和(最近) NETCurrentRuntime

对于大多数 MSBuild 任务,默认进程就足够了。 但是,对于自定义或更高级的任务(尤其是具有特定于平台的依赖项的任务),TaskHosts 通过自动启动合适的运行时来解锁兼容性和灵活性。

使用 .NET TaskHost

随着 .NET 10 SDK 和 Visual Studio 2026 的发布,MSBuild 引入了对.NET TaskHost的支持。 此功能允许 MSBuild 在单独的 .NET 进程中运行必须使用 .NET 运行时的任务。 可以通过 <UsingTask> 元素中的 Runtime="NET" 属性启用:

<UsingTask TaskName="MyNetTask"
           Runtime="NET"
           AssemblyFile="path\to\task.dll" />

设置此属性时:

  • MSBuild 自动管理 .NET TaskHost 进程的池,并在该池的节点上执行指定的任务。
  • 任务可以利用新式 .NET 运行时独占的 API 或库。
  • 隔离可保护生成进程免受依赖项或版本冲突。

警告

此功能仅适用于使用 Microsoft.NET.Sdk .NET TaskHost和/或 Runtime="NET"版本(版本 18 或更高版本)的项目。 早期 SDK、早期 Visual Studio 版本或基于其他 SDK 的项目不支持它 。 尝试在这些上下文中使用 Runtime="NET" 可能会导致生成失败或忽略设置。

尝试在 10.0.100 之前将 .NET TaskHost 功能与 .NET SDK 配合使用会导致用户在生成时出错。 若要防止出现这种情况,可以执行版本检查以确定该功能是否安全使用。 下面,我们将使用版本比较 MSBuild 属性功能来检查当前构建是否在版本 10.0.100 或更高版本中进行,如果是,则使用 NET 运行时。 否则,如果低于 SDK 版本 10.0.100 并在 MSBuild 的 .NET Framework 版本上运行,我们将改用 .NET Framework 任务实现。

<UsingTask .... AssemblyFile="my/netcore/tasks.dll" Runtime="NET" Condition="$([MSBuild]::VersionGreaterThanOrEquals('$(SdkAnalysisLevel)', '10.0.100'))" />
<UsingTask .... AssemblyFile="my/netframework/tasks.dll" Condition="!$([MSBuild]::VersionGreaterThanOrEquals('$(SdkAnalysisLevel)', '10.0.100')) and $(MSBuildRuntimeType) == 'Full' " />

为何使用 .NET TaskHost?

  • 访问新式 .NET API: .NET TaskHost 使任务能够仅使用最近 .NET 版本中可用的功能和库。
  • 改进了兼容性: 分离任务执行可以避免版本控制和依赖项冲突。
  • 未来的校对: 我们打算进一步扩展 TaskHost 支持并统一 SDK/解析程序逻辑(请参阅 dotnet/msbuild#12895 以了解正在进行的工作)。

虚拟任务参数

与任何其他任务参数一样, MSBuildRuntimeMSBuildArchitecture 可以从生成属性进行设置。

<Project>
    <PropertyGroup>
        <FrameworkVersion>3.0</FrameworkVersion>
    </PropertyGroup>
    <Target Name="MyTarget">
        <SimpleTask MSBuildRuntime="$(FrameworkVerion)" MSBuildArchitecture= "x86"/>
    </Target>
</Project>

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

注释

UsingTask 可以从工具集和环境属性设置属性。

参数MSBuildRuntimeMSBuildArchitecture提供了设置目标上下文的最灵活方法,但也提供了范围中限制最大的方法。 一方面,由于它们是在任务实例本身上设置的,在任务即将运行之前不会进行评估,因此它们可以从评估时和生成时可用的属性的完整范围派生其值。 另一方面,这些参数仅适用于特定目标中任务的特定实例。

注释

任务参数是在父节点的上下文中计算的,而不是在任务主机的上下文中计算的。 依赖于运行时或体系结构的环境变量(如 Program Files 位置)的计算结果为与父节点匹配的值。 但是,如果任务直接读取相同的环境变量,则会在任务主机的上下文中正确计算该变量。