Visual Studio 2008锁定自定义MSBuild任务程序集

Ste*_*per 28 c# msbuild msbuild-task visual-studio-2008

我正在开发一个自定义的MSBuild任务,它可以构建一个ORM层,并在项目中使用它.我受到Visual Studio保留MSBuild任务DLL而不放手的行为的阻碍.

我想像这样组织我的解决方案;

My Solution
 |
 +- (1) ORM Layer Custom Task Project
 |  |
 |  +- BuildOrmLayerTask.cs     // here's my task
 |  
 +- (2) Business Logic Project  // and here's the project that uses it.
    |
    +- <UsingTask TaskName="BuildOrmLayerTask" AssemblyFile="$(TaskAssembly)" />
Run Code Online (Sandbox Code Playgroud)

但是,当项目(2)构建时,它会从项目(1)锁定到程序集.所以现在我无法在不关闭解决方案并重新打开它的情况下再次构建项目(1).

有没有什么方法可以组织事情,以便自定义构建任务不被Visual Studio锁定?

Ste*_*per 26

(编辑: Sayed Ibrahim Hashimi,他在msbuild上写了这本书,建议使用AppDomainIsolatedTask类来获得更好的方法)

我自己设法解决了这个问题......

从Microsoft Moseley,Microsoft的MSBuild开发人员发现此论坛帖子:

嗨,您好,

不幸的是,这是因为MSBuild在主应用程序域中加载任务程序集.CLR不允许程序集从appdomain卸载,因为这样可以对其进行重要的优化.

我建议的唯一解决方法是调用tomsbuild.exe来构建使用该任务的项目.为此,请在VS中创建MSBuild.exe <>作为外部工具.

Dan
开发人员在msbuild
DanMoseley - MSFT上

因此,似乎要停止锁定,您必须生成一个新的MSBuild.exe进程.它不能是在Visual Studio中运行的那个,因为当MSBuild运行时,它会将任务加载到Visual Studio的主应用程序域中,并且永远不能卸载.

  • 创建一个新的MSBuild项目(.csproj或类似项目),它覆盖"Build"目标并执行自定义操作,例如;

    <!-- fragment of Prebuild.csproj -->   
    <Target Name="Build">   
         <BuildOrmLayerTask Repository="$(Repository)" />   
    </Target>
    
    Run Code Online (Sandbox Code Playgroud)
  • 如果需要,可将其添加到visual studio,但使用Configuration Manager确保它不是以任何配置构建的.只是让VS负责源代码控制等,而不是构建.

  • 编辑依赖项目的.csproj文件Prebuild.csproj.添加BeforeBuild使用该Exec任务调用MSBuild 的目标.这将启动一个新进程,当该进程结束时,将释放文件锁.例;

    <PropertyGroup>   
         <PrebuildProject>$(SolutionDir)Prebuild\Prebuild.csproj</PrebuildProject>   
    </PropertyGroup>   
    <Target Name="BeforeBuild">   
         <Exec Command="msbuild.exe &quot;$(PrebuildProject)&quot;" />   
    </Target>
    
    Run Code Online (Sandbox Code Playgroud)

现在,当您构建依赖项目时,它会在运行编译之前在新进程中执行MSBuild.

  • 启动另一个msbuild.exe进程似乎是唯一有效的解决方案.我没有看到扩展AppDomainIsolatedTask应该如何在这种情况下工作,因为MSBuild在尝试读取类型时已经在主AppDomain中加载了程序集.项目文件本身需要有一种方法告诉M​​SBuild在另一个AppDomain中加载任务.微软拒绝解决这个主要问题,因为使用新的AppDomain会导致性能下降 - 让我们覆盖一个选项并自行决定?为什么MS"工程师"要解决这个问题呢? (4认同)
  • 您不必创建单独的MSBuild项目。您可以简单地在目标上放置一个条件,并使用某些参数(例如`&lt;Target Name =“ TypeLite” Condition =“ $(ExecuteTypeLite)”&gt;和`&lt;Exec Command = “&quot; $(MSBuildBinPath)\ MSBuild.exe” / t:TypeLite / p:ExecuteTypeLite = true&quot; $(ProjectDir)$(ProjectFileName)&quot;“ /&gt;`。 (2认同)