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

问题描述:

我是一个MSBuild的新手,想玩一下它,但我无法弄清楚为什么这不起作用。使用来自同一解决方案的自定义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”被前“建模型”。但是当我试图建立模型我得到这个错误:

The "BuildTasks.Test" task could not be loaded from the assembly C:\WIP\TestSolution\src\BuildTasks\bin\BuildTasks.dll. Could not load file or assembly 'file:///C:\WIP\TestSolution\src\BuildTasks\bin\BuildTasks.dll' or one of its dependencies. The system cannot find the file specified. Confirm that the <UsingTask> declaration is correct, and that the assembly and all its dependencies are available.

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

我甚至试过在“$(SolutionDir)”的地方硬编码“C:\ WIP \ TestSolution”,并得到相同的错误。但是,如果我将该.dll复制到我的桌面并将路径硬编码到我的桌面,则工作,我不明白为什么。

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

+3

你是否设法解决这个问题?我有同样的问题。 – sean 2009-05-03 17:18:12

+0

3年没有解决?我有这个问题,但这篇文章没有帮助,因为它不清楚问题是不是已经解决了...... – DaveN59 2012-04-16 19:34:58

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

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

Slace说得没错。你很可能有错误的路径。它也许应该是:

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

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

@Tinister:根据上面的编辑,在路径中使用$(配置)是正确的方式,因为它将是'释放'或'调试'(或其他任何你使用的名字) – gregmac 2010-06-29 02:54:13

你可以尝试fuslogvw对问题进行诊断,还以为我不清楚,如果它越来越远......

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

我们尝试这样做,我们发现您必须将UsingTask放置在项目文件的顶部(并且拥有正确的所有路径)。然而,一旦这些就绪,并加载任务,它只会工作一次。之后,构建开始失败,因为它不能复制任务所在的DLL。我们实际上正在运行一个后期构建任务,这些任务位于我们正在构建的相同程序集/项目中。

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

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

非常感谢我为我工作的大好时光。 – daljit 2014-01-13 16:52:34

禁用的MSBuild节点再利用也将解决这个问题:

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

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

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

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

您可以使msbuild.exe进程与MSBUILDDISABLENODEREUSE = 1一起消失,但如果您的自定义任务继承自Task,devenv.exe仍会零星地锁定自定义任务程序集。另一方面,如果你只从AppDomainIsolatedTask继承,并且不设置MSBUILDDISABLENODEREUSE,空闲的MSBuild进程仍然会锁定程序集。