【问题标题】:Use custom MSBuild tasks from the same solution?使用来自同一解决方案的自定义 MSBuild 任务?
【发布时间】:2010-09-21 21:49:04
【问题描述】:

我是 MSBuild 的新手,想尝试一下,但我就是不明白为什么这不起作用。

所以我的解决方案有两个项目:“模型”和“BuildTasks”。 BuildTasks 只有一个类:

using Microsoft.Build.Utilities;

namespace BuildTasks
{
    public class Test : Task
    {
        public override bool Execute()
        {
            Log.LogMessage( "FASDfasdf" );
            return true;
        }
    }
}

然后在 Model.csproj 中我添加了这个:

  <UsingTask TaskName="BuildTasks.Test" AssemblyFile="$(SolutionDir)src\BuildTasks\bin\BuildTasks.dll" />
  <Target Name="AfterBuild">
    <Test />
  </Target>

我已经设置了构建顺序,因此“BuildTasks”在“Model”之前构建。但是当我尝试构建模型时,我得到了这个错误:

“BuildTasks.Test”任务无法 从程序集中加载 C:\WIP\TestSolution\src\BuildTasks\bin\BuildTasks.dll。 无法加载文件或程序集 'file:///C:\WIP\TestSolution\src\BuildTasks\bin\BuildTasks.dll' 或其依赖项之一。系统 找不到指定的文件。 确认 声明是正确的,并且 程序集及其所有依赖项是 可用。

这个文件肯定存在,为什么MSBuild找不到呢?

我什至尝试用硬编码“C:\WIP\TestSolution”代替“$(SolutionDir)”并得到同样的错误。但是,如果我将该 .dll 复制到我的桌面并将路径硬编码到我的桌面,它确实可以工作,我不知道为什么。

编辑:我没有路径错误。我修改了 BuildTasks 的 Debug/Release 构建以将 .dll 输出到 bin 文件夹,因为我不希望 Debug/Release 具有不同的路径。

【问题讨论】:

  • 您解决问题了吗?我有同样的问题。
  • 3 年没有解决方案?我遇到了这个问题,但这篇文章并没有帮助,因为不清楚问题是否已经解决......

标签: .net msbuild


【解决方案1】:

我们尝试了这个,我们发现您必须将 UsingTask 放在项目文件的顶部(并且所有路径都正确)。但是,一旦到位并且任务加载,它只会工作一次。之后构建开始失败,因为它无法复制任务所在的 DLL。我们实际上是在我们正在构建的同一个程序集/项目中运行一个构建后任务。

我们解决此问题的方法是在单独的 MSBuild 文件上启动单独的 MSBuild 进程以运行 Post Build 任务。这样,DLL 在构建并复制到 bin 目录之后才会加载。

<Target Name="AfterBuild">
    <Exec Command="$(MSBuildBinPath)\MSBuild.exe 
          &quot;$(MSBuildProjectDirectory)\PostBuild.msbuild&quot; 
          /property:SomeProperty=$(SomeProperty)" />
</Target>

请注意,您可以在命令行上将属性传递给此子构建任务。

PostBuild.msbuild 看起来像这样:

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="PostBuild" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
    <UsingTask TaskName="PostBuild" AssemblyFile="$(MSBuildProjectDirectory)\bin\AssemblyThatJustBuiltAndContainsBuildTask.dll" />
    <PropertyGroup>
        <SomeProperty>SomePropertyDefaultValue</SomeProperty>
    </PropertyGroup>

    <Target Name="PostBuild">
        <MyPostBuildTask SomeProperty="$(SomeProperty)" />
    </Target>
</Project>

【讨论】:

    【解决方案2】:

    如果所有自定义任务都继承自AppDomainIsolatedTask,则可以避免锁定自定义任务DLL 如果在启动 Visual Studio 之前设置了环境变量 MSBUILDDISABLENODEREUSE = 1

    带有自定义构建任务的程序集被 devenv.exe 和 msbuild.exe 锁定。

    您可以使用 MSBUILDDISABLENODEREUSE = 1 使 msbuild.exe 进程消失,但如果您的自定义任务继承自 Task,devenv.exe 仍会偶尔锁定自定义任务程序集。

    另一方面,如果您仅从 AppDomainIsolatedTask 继承并且未设置 MSBUILDDISABLENODEREUSE,则空闲的 MSBuild 进程仍将锁定程序集。

    【讨论】:

    • 你能再解释一下吗?
    • 我已经扩展了答案。
    【解决方案3】:

    Slace 说得对。您很可能有错误的组装路径。它可能应该是:

    <UsingTask 
        TaskName="BuildTasks.Test" 
        AssemblyFile="$(SolutionDir)src\BuildTasks\bin\$(Configuration)\BuildTasks.dll" />
    
    <Target Name="AfterBuild">
        <Test />
    </Target>
    

    【讨论】:

    • @Tinister:根据您上面的编辑,在路径中使用 $(Configuration) 是正确的方法,因为它将是“Release”或“Debug”(或您使用的任何其他名称)
    【解决方案4】:

    禁用 MSBuild 节点重用也将解决此问题:

    • 在 MSBuild 命令行中,传递 /nr:false 选项。
    • 对于 Visual Studio,您必须在启动 VS 之前将 MSBUILDDISABLENODEREUSE 环境变量设置为 1

    Visual Studio 2012 RTM has MSBuild.exe in memory after close

    【讨论】:

      【解决方案5】:

      你确定你有你的路径吗?不应该在bin\Configuration Type\BuildTasks.dll吗?

      我发现这个链接:http://bartdesmet.net/blogs/bart/archive/2008/02/15/the-custom-msbuild-task-cookbook.aspx 在开始编写 MSBuild 任务时很有帮助。

      【讨论】:

        【解决方案6】:

        您可能会尝试使用 fuslogvw 来诊断问题,但我不清楚它是否已经到了那么远...

        http://msdn.microsoft.com/en-us/library/e74a18c4.aspx

        【讨论】:

          【解决方案7】:

          在我们的案例中,将 PlaformTarget 添加到项目文件 (.csproj) 中解决了问题。

          【讨论】:

            猜你喜欢
            • 2015-07-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多