配置目标和任务

当开发计算机支持目标环境时,可以将选定的 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.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 更广泛的适用性。

虚拟任务参数

与任何其他任务参数一样, 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 位置)的计算结果为与父节点匹配的值。 但是,如果任务直接读取相同的环境变量,则会在任务主机的上下文中正确计算该变量。