使用同一解决方案中的自定义MSBuild任务?

时间:2008-11-12 00:23:47

标签: .net msbuild

我是MSBuild的新手并希望稍微使用它,但我无法弄清楚为什么这不起作用。

所以我的解决方案有两个项目:“Model”和“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。   无法加载文件或程序集   '文件:/// C:\ WIP \ TestSolution的\ src \ BuildTasks \ BIN \ BuildTasks.dll'   或其中一个依赖项。系统   找不到指定的文件。   确认&lt; UsingTask&gt;   声明是正确的,那个   程序集及其所有依赖项   可用。

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

我甚至尝试用硬编码“C:\ WIP \ TestSolution”代替“$(SolutionDir)”并得到同样的错误。但是,如果我将.dll复制到我的桌面并硬编码到我的桌面的路径,它 DOES 工作,我无法弄清楚原因。

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

7 个答案:

答案 0 :(得分:11)

我们尝试了这个,我们发现你必须将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>

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

Slace说得对。你很可能错过了装配路径。它可能应该是:

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

<Target Name="AfterBuild">
    <Test />
</Target>

答案 3 :(得分:1)

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

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

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

答案 4 :(得分:1)

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

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

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

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

答案 5 :(得分:0)

您可以尝试使用fuslogvw来诊断问题,我想我还不清楚它是否已经走得那么远......

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

答案 6 :(得分:0)

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